Migrating from webpack 3 to 4

Adam Jahnke
Adam Jahnke

After hearing lots of stories about the large performance improvements of the webpack 4 beta, when the final release came out, I was eager to migrate our project from v3.

webpack’s configuration can be difficult to understand anyway, and unfortunately, the webpack team was trying to hit a deadline and was unable to write any migration documentation before the v4 release. Lucky for you, we decided to push through anyway, and we took notes!

For more info about the release, check out:

Upgrade node to 8.9.4

To get the best performance out of v4, @wSokra says use at least node 8.9.4.

Upgrade webpack

webpack’s core functionality and CLI code have been split into two repos now:

$ npm i -D webpack webpack-cli

Use a mode

You may see an error like: The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.

In v4, you have to set a mode in your config:

{
  mode: "production",
}

It can also be set when invoked from CLI:

$ webpack --mode production

Change CommonsChunkPlugin to splitChunks

You may see an error like: Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.

The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points.

This functionality has moved from the CommonsChunkPlugin to the optimization.splitChunks setting.

Previously in v3, we used runtime and vendor chunks like so:

{
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ["runtime"],
      minChunks: Infinity,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: ({ resource }) => /node_modules/.test(resource),
    }),
  ];
}

In v4, this roughly translates to:

{
  optimization: {
    runtimeChunk: "single", // enable "runtime" chunk
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendor",
          chunks: "all"
        }
      }
    }
  }
}

More information about the new optimization.splitChunks option can be found here.

Get rid of ModuleConcatenationPlugin

Also known as "scope hoisting". It is now on by default in production mode.

Change UglifyJsPlugin

You may see an error like: Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead.

v4 now handles dead code elimination internally. Both it and minimization are on by default in production mode, but to continue tuning Uglify settings, add uglifyjs-webpack-plugin:

$ npm i -D uglifyjs-webpack-plugin

And in the optimization.minimizer section:

const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

{
  optimization: {
    minimizer: [
      new UglifyJSPlugin({
        sourceMap: true,
        uglifyOptions: {
          …
        }
      })
    ]
  }
}

Upgrade loaders

You may see an error like: Module build failed: TypeError: Cannot read property 'eslint' of undefined

This happened for us with eslint-loader and file-loader. Just upgrade the loaders:

$ npm i -D eslint-loader file-loader