Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chunk IDs change when new chunks are added or removed #4837

Closed
hedgepigdaniel opened this issue May 9, 2017 · 13 comments
Closed

Chunk IDs change when new chunks are added or removed #4837

hedgepigdaniel opened this issue May 9, 2017 · 13 comments

Comments

@hedgepigdaniel
Copy link
Contributor

Do you want to request a feature or report a bug?
feature

What is the current behavior?
Currently it is possible to make chunk hashes remain constant when modules are added or removed from the compilation through the use of the HashedModuleIdsPlugin or the NamedModulesPlugin. However I can't find such a plugin for chunks. In my project I have many chunks, some of which are commons chunks etc. When a new chunk is added, virtually all the other chunks hashes change, even though they contain the same modules.

If the current behavior is a bug, please provide the steps to reproduce.
At the minimum, create a compilation with 1 entry point, HashedModuleIdsPlugin, and generally cache busting set up as per the guide. Add another entry point with different code and notice that the has of the chunk for the first entry point changes as a result (depending on some ordering of chunk IDs which I haven't worked out). I will try to put together a specific example.

What is the expected behavior?
Ideally the chunkIds should be deterministic based on e.g. the entry modules, the chunk name, the set of modules in it, etc. Something that doesn't change unless the code in the chunk changes

If this is a feature request, what is motivation or use case for changing the behavior?
Because this results in unnecessary cache busting which increases load time

Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.
webpack 2.5.1

@pksjce
Copy link

pksjce commented Jul 11, 2017

Do you have a minimal working example for this? Would help me figure something out?
Also have you read https://webpack.js.org/concepts/manifest/ ? Might be close to what you are facing. Just a guess.

@benstevens48
Copy link

Hi,
I also have this problem. It's seems to be quite a big issue not being able to long-term cache vendor code so I'm surprised this hasn't been addressed. There is a third-party plugin that appears to fix it - webpack-chunk-hash - but it has a deprecation warning and I don't know if it's reliable.

Here is a suggestion on how to reproduce it. The following is the contents of a simplified webpack config.

const path = require('path');
const webpack = require('webpack');

module.exports = {
    context: path.resolve(__dirname, 'src'),
    entry: {
        vendor: ['jquery'],
        main: './app/main.js'
    },
    plugins: [
        new webpack.HashedModuleIdsPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: Infinity
        }),  
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            minChunks: Infinity
        })
    ],
    output: {
        filename: '[name].[chunkhash].js',
        chunkFilename: '[id].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    }
}

Now if you add a conditional import to app/main.js such as

import * as $ from 'jquery';
$(() => {
    import('./test.js');
});

Where test.js is another module, then it will generate an extra chunk, and the chunk ids will all change, so the vendor chunkhash will change. Also, using loaders like file-loader can change the chunk ids.

@shaodahong
Copy link
Contributor

shaodahong commented Oct 12, 2017

@pksjce Yes, I have the same problem, I found that I used the HashedModuleIdsPlugin to stabilize the moduleId, but chunkId would still be incremented by resources

webpackJsonp([0],{

/***/ "lVK7":
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/***/ })

},["lVK7"]);

You can see the use of HashedModuleIdsPlugin moduleId based on the default parameters to generate a length of 4 id

and I found that applyChunkIds implementation is an incremental, is unstable

applyChunkIds() {
    const unusedIds = [];
    let nextFreeChunkId = 0;

    function getNextFreeChunkId(usedChunkIds) {
        const keyChunks = Object.keys(usedChunkIds);
        let result = -1;

        for(let index = 0; index < keyChunks.length; index++) {
            const usedIdKey = keyChunks[index];
            const usedIdValue = usedChunkIds[usedIdKey];

            if(typeof usedIdValue !== "number") {
                continue;
            }

            result = Math.max(result, usedIdValue);
        }

        return result;
    }
    if(this.usedChunkIds) {
        nextFreeChunkId = getNextFreeChunkId(this.usedChunkIds) + 1;
        let index = nextFreeChunkId;
        while(index--) {
            if(this.usedChunkIds[index] !== index) {
                unusedIds.push(index);
            }
        }
}

@benstevens48
Copy link

Update - I found that using the undocumented new webpack.NamedChunksPlugin() helps, although unnamed chunks (such as created by automatic code splitting where an explicit name is not provided) will still have unstable chunk ids. This plugin does accept an argument to generate names for chunks without them but it's a bit awkward to generate a sensible name in some cases.

@hxlniada
Copy link

@alexander-akait
Copy link
Member

Problem still exists with latest webpack?

@alexander-akait
Copy link
Member

Closing due to inactivity. Thanks!

For long term caching please use:
1.https://webpack.js.org/guides/caching/
2. https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31

Feel free to feedback and create new issue 👍

@Strate
Copy link

Strate commented Jun 15, 2018

You can use NamedChunksPlugin to generate hash for chunks:

        new webpack.NamedChunksPlugin(function() {
                const usedIds = new Set()
                const defaultLen = 4;
                return function nameResolver(chunk) {
                    const moduleIds = chunk.getModules().map(m => m.id).sort().join(';')
                    const hash = crypto.createHash("sha256") // Like HashedModuleIdsPlugin
                    hash.update(moduleIds)
                    const hashId = hash.digest("hex")
                    let len = defaultLen
                    let resultId
                    do {
                        resultId = hashId.substr(0, len)
                        len++
                    } while (usedIds.has(resultId))
                    usedIds.add(resultId)
                    return resultId
                }
            }())

@Rowno
Copy link

Rowno commented Sep 13, 2018

I recently implemented long term caching by following https://webpack.js.org/guides/caching/ and ran into the same issue, a chunk id incremented but the contenthash remained the same.

@Rowno
Copy link

Rowno commented Sep 13, 2018

Nevermind, I just saw https://github.com/webpack/webpack/releases/tag/v4.17.0, hopefully updating to latest version of Webpack will fix the issue for us (we were a couple of minor versions behind). 🙂

@Zane0816
Copy link

Zane0816 commented Sep 6, 2019

I have the same problem.I configured my webpack file exactly as https://webpack.js.org/guides/caching/
When I removed a dynamically loaded component, I repackaged it.I got it:

  • 8.3d10e659.css
  • 9.3d10e659.css
  • vendor.2cc887c0.js
  • vendor.c37abe15.js

I am using contenthash to sign the file.
The contents of the 8.3d10e659.css and 9.3d10e659.css files are identical.
vendor.2cc887c0.js and vendor.c37abe15.js are only slightly different in the first line.
The first line of vendor.2cc887c0.js is (window.webpackJsonp=window.webpackJsonp||[]).push([[12],
The first line of vendor.c37abe15.js is (window.webpackJsonp=window.webpackJsonp||[]).push([[13],

What should I do to solve this problem?

@TwilightOwl
Copy link

@Zane0816 to solve this problem you can add moduleIds: 'hashed' to optimization block of webpack configuration file (see https://webpack.js.org/guides/caching/#module-identifiers)

@webpack-bot
Copy link
Contributor

For maintainers only:

  • webpack-4
  • webpack-5
  • bug
  • critical-bug
  • enhancement
  • documentation
  • performance
  • dependencies
  • question

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests