Webpack 5 vendors chunks naming
Asked Answered
V

1

12

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}`;
    },
  },
},
Vadnais answered 7/4, 2021 at 13:3 Comment(1)
How do you know what should be the value of chunks?Wildfowl
S
7

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.

Succession answered 10/4, 2021 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.