Webpack 4 - create vendor chunk

Tomasz Mularczyk picture Tomasz Mularczyk · Feb 26, 2018 · Viewed 96.1k times · Source

In a webpack 3 configuration I would use the code below to create separate vendor.js chunk:

entry: {
    client: ['./client.js'],
    vendor: ['babel-polyfill', 'react', 'react-dom', 'redux'],
},

output: {
  filename: '[name].[chunkhash].bundle.js',
  path: '../dist',
  chunkFilename: '[name].[chunkhash].bundle.js',
  publicPath: '/',
},

plugins: [
    new webpack.HashedModuleIdsPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'runtime',
    }),
],

With all the changes I'm not sure how to do it with Webpack 4. I know that CommonChunksPlugin was removed, so there is a different way to achieve that. I've also read this tutorial but I'm still not sure about extracting runtime chunk and properly defining output property.

EDIT: Unfortunately, I was experiencing issues with the most popular answer here. Check out my answer.

Answer

swapnil2993 picture swapnil2993 · Oct 24, 2018

In order to reduce the vendor js bundle size. We can split the node module packages into different bundle file. I referred this blog for splitting the bulky vendor file generated by webpack. Gist of that link which I used initially:

optimization: {
   runtimeChunk: 'single',
   splitChunks: {
    chunks: 'all',
    maxInitialRequests: Infinity,
    minSize: 0,
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name(module) {
        // get the name. E.g. node_modules/packageName/not/this/part.js
        // or node_modules/packageName
        const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

      // npm package names are URL-safe, but some servers don't like @ symbols
      return `npm.${packageName.replace('@', '')}`;
      },
    },
  },
 },
}

If one wants to group multiple packages and chunk then into different bundles then refer following gist.

optimization: {
runtimeChunk: 'single',
  splitChunks: {
    chunks: 'all',
    maxInitialRequests: Infinity,
    minSize: 0,
    cacheGroups: {
      reactVendor: {
        test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
        name: "reactvendor"
      },
      utilityVendor: {
        test: /[\\/]node_modules[\\/](lodash|moment|moment-timezone)[\\/]/,
        name: "utilityVendor"
      },
      bootstrapVendor: {
        test: /[\\/]node_modules[\\/](react-bootstrap)[\\/]/,
        name: "bootstrapVendor"
      },
      vendor: {
         test: /[\\/]node_modules[\\/](!react-bootstrap)(!lodash)(!moment)(!moment-timezone)[\\/]/,
      name: "vendor"
    },
    },
  },
}