mini-css-extract-plugin
mini-css-extract-plugin copied to clipboard
Different import order leads to multiple vendor bundles
Condition
Suppose I have a project have two entry file foo-entry.js
and bar-entry.js
, both of them import es6-promise
and normalize.css
. Additionally foo-entry
may also import other modules, e.g. object-assign
.
Now I want to split both shared node_modules es6-promise
and normalize.css
to shared-vendor.js
and shared-vendor.css
(use mini-css-extract-plugin to extract out from shared-vendor.js
), and split object-assign
to foo-vendor.js
.
So on foo page, I add shared-vendor.js
, foo-vendor.js
, foo-entry.js
to script tag in html
And on bar page, I add shared-vendor.js
and bar-entry.js
to script tag in html.
Reproduce
To do this, I pass a config array to webpack. the config like below. The only difference is two entry name
var webpack = require('webpack');
var MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = [{
mode: 'development',
entry: {
'foo-entry': './src/foo-entry.js',
},
output: {
filename: '[name].pack.[chunkhash:12].js',
chunkFilename: 'foo-chunk.[chunkhash:12].js'
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /\/node_modules\/(es6-promise|normalize\.css)\//,
name: 'shared-vendor',
filename: 'share-vendor.pack.[chunkhash:12].js',
chunks: 'initial'
},
// here may have other groups with lower priority to split rest modules
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].pack.[chunkhash:12].css'
})
],
module: {
rules: [
{
test: /\.css/,
// loader: ['style-loader', 'css-loader'],
loader: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
}
}, {
mode: 'development',
entry: {
'bar-entry': './src/bar-entry.js',
},
output: {
filename: '[name].pack.[chunkhash:12].js',
chunkFilename: 'bar-chunk.[chunkhash:12].js'
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /\/node_modules\/(es6-promise|normalize\.css)\//,
name: 'shared-vendor',
filename: 'share-vendor.pack.[chunkhash:12].js',
chunks: 'initial'
}
// here may have other groups with lower priority to split rest modules
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].pack.[chunkhash:12].css'
})
],
module: {
rules: [
{
test: /\.css/,
// loader: ['style-loader', 'css-loader'],
loader: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
}
}]
// src/foo-entry.js
import 'normalize.css';
import 'es6-promise/auto';
// src/bar-entry.js, the import order is different from foo-entry.js
import 'es6-promise/auto';
import 'normalize.css'
Expected result
Generate four files.
-
foo-entry.pack.[chunkhash].js
-
bar-entry.pack.[chunkhash].js
-
shared-vendor.pack.[chunkhash].js
, includees6-promise
-
shared-vendor.pack.[chunkhash].css
, includenormalize.css
Actual result
Generate six files. Two shared-vendor.js and two shared-vendor.css with the very same content
-
foo-entry.pack.[chunkhash].js
-
bar-entry.pack.[chunkhash].js
-
shared-vendor.pack.[chunkhash-1].js
, includees6-promise
-
shared-vendor.pack.[chunkhash-1].css
, includenormalize.css
-
shared-vendor.pack.[chunkhash-2].js
, includees6-promise
-
shared-vendor.pack.[chunkhash-2].css
, includenormalize.css
Search and find
- If I do not use mini-css-extract-plugin, replace it with
style-loader
(the commented line on above webpack config), only oneshared-vendor.pack.[chunkhash].js
andshared-vendor.pack.[chunkhash].css
will be generated. - If I change import order in
bar-entry.js
, firstly importnormalize.css
and then importes6-promise
likefoo-entry
, it will also generate only oneshared-vendor.pack.[chunkhash].js
andshared-vendor.pack.[chunkhash].css
.
Problem
- Does mini-css-extract-plugin change the chunkhash compute algorithm?
- Why same content have different chunkhash?
- Why different import order will generate different chunkhash but same content ?
- Does my this usage have problem? How can I do to split both shared modules to shared-vendor, and the rest modules to
[name]-vendor
?
Reproduce project
reproduce.zip
To mininal reproduce, I removed all other modules. So foo-entry and bar-entry will only import two modules es6-promise
and normalize.css
and have no any other code
Environment
- Node v8.11.1
- webpack 4.8.1
- mini-css-extract-plugin 0.4.0
- OS Mac 10.12.6
@Wyntau Thanks for issue, we known this problem and already fixed this problem, just wait improve documentation https://github.com/webpack/webpack.js.org/issues/2096. Thanks! Feel free to feedback!
@Wyntau I will leave open because looks like you have other issue around code splitting, right?
Does it mean I can now replace all [chunkhash]
with [contenthash]
safely in webpack 4.8.1?
@Wyntau yes, [chunkhash]
for backward compatibility, use always [contenthash]
, in webpack@5
it is right way to create long term caching
@evilebottnawi
I canged all [chunkhash]
to [contenthash]
, and only one shared-vendor.pack.[contenthash].css
will generated, But still two shared-vendor.pack.[contenthash].js
with same content.
- When I use mini-css-extract-plugin, the
bar-entry
's import modules order will still affect the[contenthash]
like above described - If I use
style-loader
, only oneshared-vendor.pack.[contenthash].js
(includedes6-promise
andnormalize.css
) will generated.
@Wyntau looks like problem with splitChunks
, ~~can you create minimum reproducible test repo?~~ sorry, found in original post. ~~It is hard to solve based only on configuration~~
hi @evilebottnawi , do you have any idea why will two vendor files with the same content be generated?
The [chunkhash]
change is to be expected, use [contenthash]
instead. Did you resolve the issue about multiple vendor bundles being generated ?
@michael-ciniawsky not yet