In webpack 4, vendors chunks had names such as vendors~main~secondary.js
, which were referring to the chunks they where related to. Now, in webpack 5, vendors chunks names are like this : vendors-node_modules_react-dom_index_js.js
, which is really less readable and understandable.
Any tips on how to go back to webpack 4's behaviour while using webpack 5?
I guess I'll have to do something with splitChunks.name
, but I can't find the right function to do that.
EDIT
While @MrP01's answer is more thorough and gives more insight into using splitChunks.name
, here's a short snippet that I ended up using and that allowed me to go back to the exact old behaviour.
optimization: {
splitChunks: {
chunks: 'all',
name: (module, chunks, cacheGroupKey) => {
const allChunksNames = chunks.map((chunk) => chunk.name).join('~');
const prefix = cacheGroupKey === 'defaultVendors' ? 'vendors' : cacheGroupKey;
return `${prefix}~${allChunksNames}`;
},
},
},
I feel very similarly about the new naming schemes in webpack 5. With quite a bit of effort and testing, I came up with the following, by passing function handles to the filename
properties.
To get 'prettier' names - which is of course subject to everyone's personal judgment - the following function normalizes names and strips out large and unnecessary parts of them.
function normalizeName(name) {
return name.replace(/node_modules/g, "nodemodules").replace(/[\-_.|]+/g, " ")
.replace(/\b(vendors|nodemodules|js|modules|es)\b/g, "")
.trim().replace(/ +/g, "-");
}
The main problem was the naming of the chunks that were split out. The current documentation is not very explicit about this, but the cacheGroup settings configured in config.optimization.splitChunks
, without a specific cacheGroup, apply to all cacheGroups.
I've also enabled the normalization for chunk, asset names and the extracted css.
module.exports = async () => {
return {
config: {
context: BASE,
entry: entrypoints,
output: {
path: path.resolve(`./.dev/bundles/${locale}`),
publicPath: `/static/bundles/${locale}/`,
filename: (pathData) => {
return normalizeName(pathData.chunk.name) + ".js";
},
chunkFilename: (pathData) => {
return normalizeName(pathData.chunk.id) + ".js";
},
},
devtool: false,
optimization: {
splitChunks: {
chunks: "all",
name(module, chunks, cacheGroupKey) {
const moduleFileName = module.identifier().split("/").reduceRight((item) => item);
// const allChunksNames = chunks.map((item) => item.name).join("-");
return normalizeName(moduleFileName.replace(/[\/]/g, "-"));
}
}
},
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
cssLoader,
postCssLoader
]
},
{
test: /\.(ttf|woff|eot|png|jpg|jpeg|svg)$/,
type: "javascript/auto",
loader: "file-loader",
options: {
name: (resourcePath, resourceQuery) => {
let ext = path.extname(resourcePath); // for instance ".jpg"
return normalizeName(path.basename(resourcePath).slice(0, -ext.length)) + ext;
}
}
}]
},
plugins: [
new MiniCssExtractPlugin({
filename: (pathData) => normalizeName(pathData.chunk.name) + ".css",
chunkFilename: (pathData) => normalizeName(pathData.chunk.id) + ".css"
}),
],
};
};
This resulted in filenames exceeding the name limit to much shorter and concise filenames in the resulting output folder.