svg-sprite-loader icon indicating copy to clipboard operation
svg-sprite-loader copied to clipboard

Compatibility with webpack-manifest-plugin

Open timkelty opened this issue 7 years ago • 14 comments

When I use this with webpack-manifest-plugin, my manifest ends up like so: With these options:

{
      extract: true,
      spriteFilename: 'sprites.svg',
    }

I get:

{
  "Museo300-Regular-webfont.woff": "2646113a1f5c5ca4728b05d88b276e1e.woff",
  "hero-sample.jpg": "227cbd423e001d2649e678848b207cc8.jpg",
  "index.css": "index.de42babf90fb3ab19717.css",
  "index.js": "index.de42babf90fb3ab19717.js",
  "sprites.svg.svg": "sprites.svg"
}

What I want to see (as you can see I'm getting from file-loader, etc) is:

{
  "sprites.svg": "sprites.a939c9b13b21cd05a5e796ab6ba41769.svg"
}

So there's 2 issues.

  • The key is getting a duplicate .svg appended
  • I want a source: hashed pair in manifest. I suppose for that you might need another option like chunkSpriteFilename. that you could set to 'sprites.[hash].svg`

timkelty avatar Aug 02 '17 19:08 timkelty

Note, https://github.com/Karify/external-svg-sprite-loader seems to do this out of the box, simply by passing name: 'sprites.[hash].svg' as an option:

webpack output:

              index.0acbba93d0e18652feff.css    85.8 kB     index  [emitted]  index
sprites.b6a21263788a123dfff1f5d854291871.svg  721 bytes            [emitted]  sprites
                               manifest.json  964 bytes            [emitted]

manifest.json

{
  "Museo300-Regular-webfont.woff": "2646113a1f5c5ca4728b05d88b276e1e.woff",
  "hero-sample.jpg": "227cbd423e001d2649e678848b207cc8.jpg",
  "index.css": "index.de42babf90fb3ab19717.css",
  "index.js": "index.de42babf90fb3ab19717.js",
  "sprites.svg": "sprites.b6a21263788a123dfff1f5d854291871.svg"
}

timkelty avatar Aug 02 '17 19:08 timkelty

webpack-manifest-plugin compatibility shipped with version 3.2.2

kisenka avatar Aug 17 '17 21:08 kisenka

The key is getting a duplicate .svg appended

@kisenka This issue has been addressed, but the other issue remains, so it still isn't really usable with webpack-manifest…

The output of manifest.json is now something like:

  "index.js": "index.5aaa0284303daf026ee6.js",
  "sprites.9c565aa8c02d25eb352d121ae26b6b90.svg": "sprites.9c565aa8c02d25eb352d121ae26b6b90.svg"

For it to be useful, we want something like this:

  "index.js": "index.5aaa0284303daf026ee6.js",
  "sprites.svg": "sprites.9c565aa8c02d25eb352d121ae26b6b90.svg"

timkelty avatar Sep 06 '17 13:09 timkelty

I would also really like this feature, in the mean time you can kind of naively use regex to remove the hash in the key but not the value with webpack-assets-manifest

Because it has a customize option it let's you search emitted files, from the documentation:

new WebpackAssetsManifest({
  customize: function(key, value, originalValue, manifest) {
    // currently merging with an existing manifest file.
    if ( manifest.isMerging ) {
      // Do something
    }

    // Edit svg bundle name here, in the form file.min.[hash].svg
    if ( key.toLowerCase().endsWith('.svg') ) {
        const re = /(?=(\.min\.))(.*)(?=svg$)/;
	return {
            key: key.replace(re, '$1'), 
            value: value
          };
    }

    // The manifest instance is available if you need it.
    if ( manifest.options.publicPath ) {
      // Do something
    }

    // originalValue is the value before the publicPath option was applied.
    if ( originalValue ) {
      // Do something
    }

    // To alter the key/value, return an object with a key/value property.
    // The key should be a string and the value can be anything that can be JSON stringified.
    // If something else (or nothing) is returned, this callback will have no affect and the
    // manifest will add the entry normally.
    return {
      key: key,
      value: value,
    };
  },
}),

spookyuser avatar Dec 12 '17 15:12 spookyuser

just needs to provide a configurable chunkname in the loader options.

airtonix avatar Dec 19 '17 08:12 airtonix

@spookyUnknownUser could you please make a PR? :)

kisenka avatar Dec 19 '17 10:12 kisenka

Yeah I'll take a look 😄

spookyuser avatar Dec 19 '17 19:12 spookyuser

Has anyone been able to resolve this? The PR is stagnant and I'm running into this same issue. I tried an implementation of your example above @spookyUnknownUser but wasn't able to get it to work.

This thing is causing major problems with how I load my files from the manifest on my app :/ All my other assets work swimmingly!

codingwithchris avatar May 27 '18 12:05 codingwithchris

@kisenka could you please take a look at the PR? It's been up for a while. This problem doesn't allow me to setup correct sprite versioning on my project. :(

rchesnokov avatar Jun 04 '18 09:06 rchesnokov

Hey @codingwithchris sorry it's not working for you. If you want I can take a look at your AssetManifest config I definitely have a working project with this (super hacky) workaround.

And yeah @rchesnokov it would be great to hear back from @kisenka , I'm sure that my PR is super outdated. But I would be happy to give it another go if @kisenka has any feedback!

spookyuser avatar Jun 05 '18 16:06 spookyuser

Hey, @spookyUnknownUser! I appreciate you jumping on here and offering some support!

I ended up removing the fix from my Webpack config temporarily in hopes the PR would be looked at. Here's a link to my current config (in progress...so don't judge too harshly ;) ). The Manifest plugin is referenced on line 284.

Let me know if you need anything else! I appreciate this more than you know as this is the only bug I need to iron out in my existing build system.

codingwithchris avatar Jun 05 '18 16:06 codingwithchris

np @codingwithchris. So I checked your code sample and I think the problem is that your svg is saving as sprite.svg. I don't know if you've tried naming it sprite.min.[hash:6].svg. Because with that name this manifest config should work:

new WebpackAssetsManifest({
  customize: function(key, value, originalValue, manifest) {
    if (key.toLowerCase().endsWith(".svg")) {
      const re = /(?=(\.min\.))(.*)(?=svg$)/;
      return {
        key: key.replace(re, "$1"),
        value: value
      };
    }
    return {
      key: key,
      value: value
    };
  }
});

It doesn't have to be sprite.min.[hash:6].svg but the name does have to have the hash:6 between the .svg and another word so you could even do sprite.[hash:6].svg then just change the manifest config to look for that:

new WebpackAssetsManifest({
  customize: function(key, value, originalValue, manifest) {
    if (key.toLowerCase().endsWith(".svg")) {
      const re = /(?=(sprite\.))(.*)(?=svg$)/;
      return {
        key: key.replace(re, "$1"),
        value: value
      };
    }
    return {
      key: key,
      value: value
    };
  }
});

And you could just put that on L284. Tell me if that works 😄

spookyuser avatar Jun 07 '18 12:06 spookyuser

I worked around this by making the consumer of my manifest file more flexible. If it doesn't find asset_name.fileextension it will look for asset_name.[regex that matches any hash].fileextension. This is kind of terrible but it works for my case.

rosscreighton avatar Feb 08 '19 00:02 rosscreighton

Hey pals!

Come over to https://github.com/bensampaio/external-svg-sprite-loader

The external-svg-sprite-loader has it working.

Cya!

infabo avatar Dec 01 '20 14:12 infabo