@scinos and I have collaborated on webpack-plugin-hash-output, which is working in our production environment without issues. See the discussion below for more details.
Original Ticket
This is a bug affecting long-term caching with CDNs.
During a recent dependency upgrade, webpack’s Uglify dependency moved from 2.8.10
to 2.8.25
, which produces slightly different output.
The issue is that [chunkhash]
doesn’t appear to actually hash the final file:
# Uglify 2.8.25
$ cat 4-c1bcb6390594024c54d3.js | md5
480d9646348a0cca88088c3755c54fd4
$ head -c 100 4-c1bcb6390594024c54d3.js
webpackJsonp([4],{963:function(e,a,n){!function(a,n){e.exports=n()}(0,function(){"use strict";return
Now, before the upgrade:
# Produced using Uglify 2.8.10 - manually appended `-old` to name
$ cat 4-c1bcb6390594024c54d3-old.js | md5
0103f905d3620c8af106ab46b50f9ab9 # Different hash, same chunkhash!
$ head -c 100 4-c1bcb6390594024c54d3-old.js
webpackJsonp([4],{963:function(e,a,n){!function(a,n){e.exports=n()}(this,function(){"use strict";ret
Notice the two bundles have the same [chunkhash]
but different contents; specifically, uglify 2.3.25 uses (0,function
rather than (this,function
.
This caused a production application to load an outdated file from a CDN which then did not match subresource integrity and failed to load.
This is Node 6.10.2, Webpack 2.3.3, Uglify versions as above. I was not using NamedModulesPlugin
or ChunkManifestPlugin
, but I am using UglifyJsPlugin
and CommonsChunkPlugin
.
Resolution
The crux of the issue is that webpack/lib/Compilation.js runs hashing before optimization, which means that two different-optimized files will have the same hash.
After some work with this issue, I’ve discovered two major reasons why it’s difficult for [chunkhash]
to actually equal the hash of the file:
- Appending a
//# sourceMappingURL
changes the hash, but requires the hash to determine the name of the sourceMap file (this is not a huge deal), and - Chunking requires the name of the module. For this reason, the main chunk (with the manifest) must be processed after all other files so that its manifest is correct, then optimized, then hashed.
I have a work-in-progress plugin at https://gist.github.com/STRML/a9c393c9b43d726663d212600fd81320
Update: (19/5/2017): If you’ve read this far, use https://www.npmjs.com/package/webpack-plugin-hash-output which fixes this issue.
I wrote https://www.npmjs.com/package/webpack-plugin-hash-output to solve that problem. As your gist, is a plugin that runs at the end of the compilation cycle and computes the hash based on the content of the final content of the chunks.
Wow… this is a big deal.
I have been using [chunkHash] without this plugin with Angular 2/4 and sometimes all indexes were changed but the hashes stayed exactly the same.
I was debugging why the chunks were loading successfully but the
loadChildren
mechanism in the router was crashing in Angular code.CDN or no CDN, this is a major issue to me. The patch is the key.
This is still a bug.
To reproduce, simply twiddle
global_defs
, like so:Then compile a module:
Notice that no matter what you change the value of the global to, the hash of the chunk is the same.