jantimon/html-webpack-plugin

Different HTML output with webpack 4 & 5 and html-webpack-plugin 3.x & 5.x

TimJans opened this issue ยท 9 comments

Current behaviour ๐Ÿ’ฃ

I have just migrated from webpack 4.x to 5.x and therefore also updated html-webpack-plugin from 3.x to 5.x. I have (for some reason) multiple entries PER page, that share common chunks e.g. runtime chunk and vendor chunks.
With the configuration shown below the generated common.html included only the runtime chunks as well as the vendor chunks from the respective cache group. The generated html files from the entry points included only the bundles but not the runtime & vendor chunks.
After migrating to webpack 5 & html-webpack-plugin 5.x the common.html included nothing and the html files from the entry points BOTH included runtime & vendors chunks as well as the bundle.

Is the new behaviour related to the webpack update or the update of the html-webpack-plugin?
What can i do to receive the former result meaning only runtime & vendors separated in common.html and only the bundles but no shared files in the entry html files?

I already googled my ass off and tried a zillion variations of below configuration but with no success. I'm running out of ideas so any help is appreciated. Thanks guys!

Reproduction Example ๐Ÿ‘พ

module.exports = {
    entry: {
        first: './first.js',
        second: './second.js',
    },
    output: {
        path: path.join(__dirname, 'dist/js'),
        filename: '[name].[contenthash].js',
        publicPath: ''
    },
    optimization: {
        runtimeChunk: "single",
        splitChunks: {
            cacheGroups: {
                default: false,
                defaultVendors: false,
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all',
                    enforce: true,
                    minChunks: 2
                },
            }
        }
    },
    plugins: [
        new packages.htmlWebpackPlugin({
            template: 'template.html',
            filename: 'common.html',
            excludeChunks: ['first', 'second'],
            inject: false,
        }),
        new packages.htmlWebpackPlugin({
            template: 'template.html',
            filename: 'first.html',
            chunks: ['first'],
            inject: false,
        }),
        new packages.htmlWebpackPlugin({
            template: 'template.html',
            filename: 'second.html',
            chunks: ['second'],
            inject: false,
        }),
    ]
};

Environment ๐Ÿ–ฅ

Node.js v16.1.0
darwin 20.4.0
npm 7.12.1
webpack@5.37.0
html-webpack-plugin@5.3.1

I have this problem as well - the chunks option seems to not work any more?

the way we get chunks from webpack changed from 3 to 4 for performance reasons

I am open for PRs to bring back the old behaviour

I managed to fix this by implementing my own filter plugin similar to he Html Webpack Skip Assets Plugin. It filters files based on a provided Regex. Cheers anyhow and keep up the good work dudes.

@jantimon

Can the documentation be updated?

This seems like a huge breaking change if chunks or excludeChunks is not working as intended.

https://github.com/jantimon/html-webpack-plugin#filtering-chunks

sure - the filtering logic by itself did not change it is still the same:

const filteredEntryNames = filterChunks(entryNames, options.chunks, options.excludeChunks);

/**
* Return all chunks from the compilation result which match the exclude and include filters
* @param {any} chunks
* @param {string[]|'all'} includedChunks
* @param {string[]} excludedChunks
*/
function filterChunks (chunks, includedChunks, excludedChunks) {
return chunks.filter(chunkName => {
// Skip if the chunks should be filtered and the given chunk was not added explicity
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) {
return false;
}
// Skip if the chunks should be filtered and the given chunk was excluded explicity
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) {
return false;
}
// Add otherwise
return true;
});
}

can you somehow explain why this old logic won't work anymore for webpack 4 & 5?

Just came across this issue while upgrading.

The chunks array in the template is completely empty after the upgrade, here it is stringified from files

{
   "publicPath":"/",
   "js":[
      "/js/chunk-vendors.js",
      "/js/chunk-common.js",
      "/js/%40dcw/platform-themes-core-project-dashboard-app.js"
   ],
   "css":[
      "/css/chunk-vendors.css",
      "/css/chunk-common.css",
      "/css/%40dcw/platform-themes-core-project-dashboard-app.css"
   ]
}

so the sorting and filtering is working, because I'm only getting the related chunk (sadly I have about 20 chunks)
but it's no longer writing into the chunks object, so I had to tweak my template to just write the js files

It actually works out slightly more convenient for me, but figured someone may benefit

stale commented

This issue had no activity for at least half a year. It's subject to automatic issue closing if there is no activity in the next 15 days.

@TimJans I am going through the upgrade now and hitting this exact same issue. Can you share a little more on how you fixed it with your plugin?

Same problem. Waiting for some solution, thanks.