shellscape / webpack-manifest-plugin

webpack plugin for generating asset manifests
MIT License
1.44k stars 185 forks source link

Manifest keys contain source path #238

Closed bigskillet closed 3 years ago

bigskillet commented 3 years ago

Expected Behavior

  "/assets/main.css": "/assets/main-fed4ead9.css",
  "/assets/main.js": "/assets/main-31d6cfe0.js",
  "/assets/test.png": "/assets/test-7f730f47.png",
  "/assets/font.woff2": "/assets/font.woff2"

Actual Behavior

  "/assets/main.css": "/assets/main-fed4ead9.css",
  "/assets/main.js": "/assets/main-31d6cfe0.js",
  "/assets/assets/test.png": "/assets/test-7f730f47.png",
  "/assets/index.html": "/index.html",
  "/assets/src/assets/static/font.woff2": "/assets/font.woff2"

Additional Information

The manifest plugin is adding the source path the entry key. For example, /src/assets/static/ is being added to the copied static font file. It's not adding the source path to the main.css and main.js keys though. I had to add a basePath to get them matching, which caused the test.png key to double the /assets/ path and also added it to the index.html key. If I remove the basePath, the main entries don't match up:

Sorry, I'm a bit of n00b, so I'm not sure if this is a bug, feature, or if I'm just using it wrong.

Thanks!

bigskillet commented 3 years ago

This map function seems to have resolved the issue and can be used as a temporary fix:

map: (file) => {
  file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
  return file;
}
andrewmcodes commented 3 years ago

@bigskillet where exactly did you put that map?

bigskillet commented 3 years ago

@andrewmcodes, here's my setup:

new WebpackManifestPlugin({
  fileName: 'assets/manifest.json',
  basePath: '/assets/',
  map: (file) => {
    file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
    return file;
  }
})
coreyworrell commented 3 years ago

@bigskillet That fix seems to be for a separate issue where the hashes were in the keys. That replace() doesn't seem to remove the source path from the key, it would only remove the hash.

Here's is what I am using for the time being.

new WebpackManifestPlugin({
    basePath: `dist/`,
    publicPath: `dist/`,
    map: f => ({ ...f, name: f.path.replace(/\.[a-f0-9]{32}\./, '.') }),
}),
bigskillet commented 3 years ago

@coreyworrell, I'm glad you chimed in, which gave me another look at this.

I thought the addition of the map fixed my issue, but I removed the map and it's working correctly right out of the box now. I'm going to chalk it up to user error on my end. I'm not sure what changed or what I was doing wrong before, but I blame the holidays when I originally posted this issue.

I'm going to close this since it's a non-issue.

coreyworrell commented 3 years ago

@bigskillet oh that’s weird. I’m still experiencing the issue here, if I remove the map function then the source path still shows in the key.

bigskillet commented 3 years ago

@coreyworrell, weird!

I was testing with JS and CSS files only, but I just added a copied image and I see that the src path is still being included:

{
  "/assets/main.css": "/assets/main-170f3e42.css",
  "/assets/main.js": "/assets/main-dd84ccd5.js",
  "/assets/main.css.map": "/assets/main-170f3e42.css.map",
  "/assets/main.js.map": "/assets/main-dd84ccd5.js.map",
  "/assets/src/images/apple-touch-icon.png": "/assets/apple-touch-icon.png"
}

I added the map back in, but it's still adding the /src/images/ path to the copied image key, as you can see above. So maybe that's not the solution either!

I'm going to reopen this, sigh...

coreyworrell commented 3 years ago

Exactly what I'm experiencing as well. The main entries are fine, but other Asset Module files and assets are including the source path. Using the map() function in my previous comment fixes it for now, but may not continue to work well.

bigskillet commented 3 years ago

Yeah and the map I was using before isn't working for me anymore. I tried using your version, which removes the src path, but it also adds the hash to the key, which I don't want.

{
  "/assets/main-170f3e42.css": "/assets/main-170f3e42.css",
  "/assets/main-dd84ccd5.js": "/assets/main-dd84ccd5.js",
  "/assets/main-170f3e42.css.map": "/assets/main-170f3e42.css.map",
  "/assets/main-dd84ccd5.js.map": "/assets/main-dd84ccd5.js.map",
  "/assets/apple-touch-icon.png": "/assets/apple-touch-icon.png"
}

I've tried using your map in combination with removeKeyHash: true, but that's not working either. Any idea how to remove the hash as well?

coreyworrell commented 3 years ago

Looks like your hashes are only 8 characters, so just change the 32 to an 8 in the map function and you should be good.

bigskillet commented 3 years ago

@coreyworrell, that's not working for me. I can set it to 0 and it removes the hash, but the src path is still in the key :(

map: (file) => {
  file.name = file.name.replace(/(\.[a-f0-9]{0})(\..*)$/, '$2');
  return file;
}

Changing your version to 8 or 0, the src path is removed, but the hash still remains in the key:

map: f => ({ ...f, name: f.path.replace(/\.[a-f0-9]{0}\./, '.') })

coreyworrell commented 3 years ago

Oh sorry @bigskillet, I was using format filename.hash.ext, and you are using filename-hash.ext (dot vs dash before the hash).

Just change that first \. in the regex to -and it should work.

map: f => ({ ...f, name: f.path.replace(/-[a-f0-9]{8}\./, '.') }),
bigskillet commented 3 years ago

@coreyworrell, thanks, that worked!

shellscape commented 3 years ago

Hey all, is this still an issue or is there a good workaround in place?

bigskillet commented 3 years ago

@shellscape, yes, still an issue. We're having to use the map filter as a workaround:

map: f => ({ ...f, name: f.path.replace(/.[a-f0-9]{8}\./, '.') })

shellscape commented 3 years ago

OK thanks. If anyone would like to open a PR to fix this, it would be welcome.

NovaLagnus commented 3 years ago

@bigskillet Try this: https://webpack.js.org/plugins/copy-webpack-plugin/

You also need to make sure any versioning is disabled or the file-loader [hash] isn't in use in the pipeline. To get right of "31d6cfe0" which is [hash:8] and used for cache busting.

weaverryan commented 3 years ago

Hi! I may have fixed this on #249 - there are details on how to test at the bottom :).

yoriiis commented 3 years ago

Any news about the fix and when the #249 will be merged? I've test the PR from @weaverryan and the problem is resolved in my case, thanks you πŸ‘

shellscape commented 3 years ago

@yoriiis if you don't see any updates on the pull requests or issues, there is no news. I'll never understand why people ask this on GitHub when everything is available to see. please refrain from replies like this in this repo, as it just adds to noise.

mrceperka commented 3 years ago

Hello, after upgrading to webpack 5, I have problem with combination of WebpackManifestPlugin (3.0.0) and CopyWebpackPlugin (8.0.0).

Problem: Tke keys in manifest file contains full source path:

node_modules/@some-vendor/ui/dist/images/icon-to-top.svg

instead of

ui-images/icon-to-top.svg

:point_up: This was not problem before, with webpack 4.

Any idea what I am doing wrong? Will #249 fix this issue as well?

Also... CopyWebpackPlugin might be causing this behavior. Can someone confirm?

Config:

 new WebpackManifestPlugin({
      publicPath: 'assets/',
      // https://github.com/shellscape/webpack-manifest-plugin/issues/238
      map: (f) => {
        console.log(
          f.name,
          // this replace somehow fixes it...
          f.name.replace(
            'node_modules/@some-vendor/ui/dist/images',
            'ui-images'
          )
        )
        return f;
      },
    }),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: path.resolve(
            __dirname,
            '../node_modules/@some-vendor/ui/dist/images'
          ),
          to: path.resolve(__dirname, '../../backend/www/assets') + '/ui-images',
        },
      ],
    }),
bigskillet commented 3 years ago

This works for me, but I have to use the map mentioned above:

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'src/static',
      to: 'assets'
    }
  ]
}),
new WebpackManifestPlugin({
  fileName: 'assets/manifest.json',
  map: f => ({ ...f, name: f.path.replace(/.[a-f0-9]{8}/, '') })
})
mrceperka commented 3 years ago

I've tried yours and other versions of map from this thread, but none seemed to work.

I had to modify that map function a bit. Because it did not work on strings like this: node_modules/@some-vendor/ui/dist/images/icon-to-top.svg

'node_modules/@some-vendor/ui/dist/images/icon-to-top.svg'.replace(/.[a-f0-9]{8}/, '')
// bad
"node_modules/@some-vendor/ui/dist/images/icon-to-top.svg"

So instead I'm doing it in less generic way:

'node_modules/@some-vendor/ui/dist/images/icon-to-top.svg'.replace('node_modules/@some-vendor/ui/dist/images', 'ui-images')
// good
'ui-images/icon-to-top.svg'

Anyway, I'd rather not use map at all :D