To v5 from v4

This guide aims to help you migrating to webpack 5 when using webpack directly. If you are using a higher level tool to run webpack, please refer to the tool for migration instructions.

Preparations

webpack 5 requires at least Node.js 10.13.0 (LTS).

Using newer Node.js version can improve build performance.

Upgrade webpack and its dependencies

Upgrade webpack 4 to the latest available version

When using webpack >= 4, upgrading to the latest webpack 4 version should not require additional guidance. If you are using webpack version less than 4 please see the webpack 4 migration guide.

Upgrade webpack-cli to the latest available version (when used)

Upgrade all used Plugins and Loaders to the latest available version

Some Plugins and Loaders might have a beta version that has to be used in order to be compatible with webpack 5.

Check related Plugins and Loaders migration guide when upgrading across major versions.

ExtendedAPIPlugin is removed and the logic is merged into APIPlugin.

Make sure your build has no errors or warnings

There might be new errors or warnings because of the upgraded versions of webpack, webpack-cli, Plugins and Loaders. Keep an eye for deprecation warnings during the build.

You can invoke webpack this way to get stack traces for deprecation warnings to figure out which Plugins and Loaders are responsible.

node --trace-deprecation node_modules/webpack/bin/webpack.js

webpack 5 removes all deprecated features. In order to proceed, there should be no webpack deprecation warnings during the build.

Make sure you are using entry point information from stats

If you are using HtmlWebpackPlugin skip this step.

When using static HTML or creating HTML in other way, make sure to use entry points from stats JSON to generate <script>, <style> and <link> tags.

If this is not possible, avoid setting splitChunks.chunks: 'all' and splitChunks.maxSize later in this guide. Note that this is sub-optimal and a workaround.

Make sure to use mode

Set mode to either production or development to make sure that corresponding defaults are set.

Update outdated options

Update the following options to their new version (if used):

  • optimization.hashedModuleIds: trueoptimization.moduleIds: 'hashed'
  • optimization.namedChunks: trueoptimization.chunkIds: 'named'
  • optimization.namedModules: trueoptimization.moduleIds: 'named'
  • NamedModulesPluginoptimization.moduleIds: 'named'
  • NamedChunksPluginoptimization.chunkIds: 'named'
  • HashedModulesPluginoptimization.moduleIds: 'hashed'
  • optimization.occurrenceOrder: trueoptimization: { chunkIds: 'total-size', moduleIds: 'size' }
  • optimization.splitChunks.cacheGroups.vendorsoptimization.splitChunks.cacheGroups.defaultVendors
  • Compilation.entriesCompilation.entryDependencies
  • serveserve is removed in favor of DevServer

Test webpack 5 compatibility

Try to set the following options in your webpack 4 configuration and check if build still works correctly.

module.exports = {
  // ...
  node: {
    Buffer: false,
    process: false
  }
};

webpack 5 removes these options from the configuration schema and will always use false. You have to remove these options again when upgrading your configuration for webpack 5.

Upgrade webpack version

npm: npm install webpack@next --dev

Yarn: yarn add webpack@next -D

Clean up configuration

  • Consider removing optimization.moduleIds and optimization.chunkIds from your webpack configuration. The defaults could be better, because they support long term caching in production mode and debugging in development mode.
  • When using [hash] placeholder in webpack configuration, consider changing it to [contenthash]. It is not the same, but proven to be more effective.
  • If you are using Yarn's PnP and the pnp-webpack-plugin, we have good news: it is supported by default now. You have to remove it from the configuration.
  • If you are using IgnorePlugin with a regular expression as argument, it takes an options object now: new IgnorePlugin({ resourceRegExp: /regExp/ }).

If you were using WASM via import you should follow this two step process:

  • Enable the deprecated spec by setting experiments.syncWebAssembly: true, to get the same behavior as in webpack 4.
  • After successful migration to webpack 5, change the experiments value to experiments: { asyncWebAssembly: true, importAsync: true } to use the up-to-date spec for WASM integration.

Reconsider optimization.splitChunks:

  • It's recommended to use either the defaults or optimization.splitChunks: { chunks: 'all' }.
  • When using HTTP/2 and long term caching, set optimization.splitChunks: { chunks: 'all', maxInitialRequests: 30, maxAsyncRequests: 30, maxSize: 100000 }.
  • When using a custom configuration, replace name with idHint.
  • It was possible to turn off the defaults by setting optimization.splitChunks: { default: false, vendors: false }. We don't recommend doing this, but if you really want to get the same effect in webpack 5: optimization.splitChunks: { default: false, defaultVendors: false }.

Cleanup the code

Using /* webpackChunkName: '...' */: Make sure to understand the intention:

  • The chunk's name here is intended to be public.
  • It's not a development-only name.
  • webpack will use it to name files in production and development modes.
  • webpack 5 will automatically assign useful file names in development mode even when not using webpackChunkName.

Using named exports from JSON modules: this is not supported by the new specification and you will get a warning. Instead of import { version } from './package.json' use import package from './package.json'; const { version } = package;

Cleanup the build code

  • When using const compiler = webpack(...);, make sure to close the compiler after using it: compiler.close();.

Run a single build and follow advises

If there is no corresponding advise? Please create an issue and we will try to resolve it. Repeat this step until you solved at least level 3 or 4:

  • Level 1: Schema validation fails. Configuration options have changed. There should be a validation error with a BREAKING CHANGE: note.
  • Level 2: webpack exits with an error. The error message should tell you what needs to be changed.
  • Level 3: Build Errors. The error message should have a BREAKING CHANGE: note.
  • Level 4: Build Warnings. The warning message should tell you what can be improved.

Deprecation warnings. You might get a lot of deprecation warnings. This is not a problem right now. Plugins need time to catch up with core changes. Please ignore them until release candidate out of Beta.

  • You can hide deprecation warnings by running node with --no-deprecation flag, e.g.: node --no-deprecation node_modules/webpack/bin/webpack.js. This should only be a temporary workaround.
  • Plugins and Loaders contributors can follow the advises in the deprecation messages to improve the code.

Turn off ES2015 syntax in runtime code, if necessary

By default, webpack's runtime code uses ES2015 syntax to build smaller bundles. If your build targets environments that don't support this syntax (like IE11), you'll need to set output.ecmaVersion: 5 to revert to ES5 syntax.

Everything works?

Please tweet that you have successfully migrated to webpack 5. Tweet it

It is not working?

Create an issue and tell us about the issues you have encountered during the migration.

Something missing in this guide?

Please open a Pull Request to help the next person using this guide.

Changes to internals

The changes to webpack internals such as: adding types, refactoring code and methods renaming are listed here for anyone interested. But they are not intended as a part of common use-case migration.

  • Module.nameForCondition, Module.updateCacheModule and Module.chunkCondition are no longer optional.

getOptions method for Loaders

webpack 5 ships with built-in this.getOptions method available in loader context. This is a breaking change for loaders that had been using getOptions method from previously preferred schema-utils:

  • this.getOptions is available since webpack 5
  • Instead of JSON5 it supports JSON as a query string: ?{arg:true}?{"arg":true}. Using JSON5 should be considered and documented as deprecated in favor of JSON in respective Loader's documentation.
  • loader-utils has specific behavior for parsing query strings (true, false and null won't be parsed as string but as a primitive value). This is no longer the case for the new built-in this.getOptions method, which uses native querystring parsing (ships with Node.js). It is still possible to add custom behavior for these cases in the Loader's code after getting the options by using this.getOptions method.
  • Schema argument is optional for the new this.getOptions method, but we strongly advise to add schema validation for your Loader's options. The title field in the schema, can be used to customize the validation error message e.g. "title": "My Loader ooooptions" will result in displaying errors this way: Invalid ooooptions object. My Loader has been initialised using an ooooptions object that does not match the API schema. - ooooptions.foo.bar.baz should be a string.