This guide helps you migrate to webpack 5 when you use webpack directly. If you rely on a higher-level tool to run webpack, follow that tool's own migration instructions instead.
webpack 5 requires at least Node.js 10.13.0 (LTS), so upgrade your Node.js installation if you are still running an older version.
-
Upgrade
webpack4 to the latest available version.- If you are already on webpack >= 4, upgrading to the latest webpack 4 release should not require additional guidance.
- If you are on a version earlier than 4, follow the webpack 4 migration guide first.
-
Upgrade
webpack-clito the latest available version (if you use it). -
Upgrade all of your plugins and loaders to their latest available versions.
Some plugins and loaders may have a beta version that is required for webpack 5 compatibility. Read each plugin's and loader's release notes when upgrading, since the latest version might only support webpack 5 and fail on v4. In that case, upgrade to the latest version that still supports webpack 4.
To assist with upgrading from webpack v4 to v5, Codemod provides open-source community codemods that automate much of the migration.
Note that these are not official webpack codemods, and while they aim to streamline the process, they may not cover every case. You may still need to perform additional manual steps to complete the upgrade.
Run the webpack v5 migration codemods:
npx codemod@latest webpack/v5/migration-recipeThis runs the following codemods from the Codemod registry:
webpack/v5/set-target-to-false-and-update-pluginswebpack/v5/migrate-library-target-to-library-objectwebpack/v5/json-imports-to-default-imports
Each of these automates a change described in this migration guide. For the complete list of available webpack v5 codemods, see the Codemod Registry.
The upgraded versions of webpack, webpack-cli, your plugins, and your loaders may introduce new errors or warnings. Watch for deprecation warnings during the build.
You can run webpack like this to get stack traces for deprecation warnings, which helps identify the responsible plugins and loaders:
node --trace-deprecation node_modules/webpack/bin/webpack.jsBecause webpack 5 removes all deprecated features, make sure there are no webpack deprecation warnings during the build before you proceed.
Set mode to either production or development so that the corresponding defaults are applied.
Update the following options to their new form (if you use them):
optimization.hashedModuleIds: true→optimization.moduleIds: 'hashed'optimization.namedChunks: true→optimization.chunkIds: 'named'optimization.namedModules: true→optimization.moduleIds: 'named'NamedModulesPlugin→optimization.moduleIds: 'named'NamedChunksPlugin→optimization.chunkIds: 'named'HashedModuleIdsPlugin→optimization.moduleIds: 'hashed'optimization.noEmitOnErrors: false→optimization.emitOnErrors: trueoptimization.occurrenceOrder: true→optimization: { chunkIds: 'total-size', moduleIds: 'size' }optimization.splitChunks.cacheGroups.vendors→optimization.splitChunks.cacheGroups.defaultVendorsoptimization.splitChunks.cacheGroups.test(module, chunks)→optimization.splitChunks.cacheGroups.test(module, { chunkGraph, moduleGraph })Compilation.entries→Compilation.entryDependenciesserve→ removed in favor ofDevServerRule.query(deprecated since v3) →Rule.options/UseEntry.optionsRule.loaders→Rule.use
[!TIP] Review the detailed configuration changes here.
Set the following options in your webpack 4 configuration and confirm that the build still works correctly.
export default {
// ...
node: {
Buffer: false,
process: false,
},
};Remove these options again when you upgrade your configuration for webpack 5.
[!TIP] webpack 5 removes these options from the configuration schema and always treats them as
false.
Now upgrade webpack to version 5:
- npm:
npm install webpack@latest - Yarn:
yarn add webpack@latest - pnpm:
pnpm add webpack@latest
If you were unable to upgrade some plugins or loaders to their latest versions in the earlier step, upgrade them now.
-
Consider removing
optimization.moduleIdsandoptimization.chunkIdsfrom your configuration. The defaults may be better, because they support long-term caching inproductionmode and easier debugging indevelopmentmode. -
If you use the
[hash]placeholder in your configuration, consider switching to[contenthash]. It is not identical, but has proven more effective. -
If you use Yarn's PnP with the
pnp-webpack-plugin, good news: it is now supported by default, so remove the plugin from your configuration. -
If you use
IgnorePluginwith a regular expression argument, it now takes anoptionsobject:new IgnorePlugin({ resourceRegExp: /regExp/ }). -
If you use something like
node.fs: 'empty', replace it withresolve.fallback.fs: false. -
If you use
watch: truein the webpack Node.js API, remove it. It is unnecessary, since the compiler method you call already indicates watch mode:watch()for watching andrun()for a single build. -
If you have
rulesthat load assets withraw-loader,url-loader, orfile-loader, use Asset Modules instead, as those loaders will be deprecated soon. -
If you have
targetset to a function, set it tofalseand apply that function in thepluginsoption instead. For example:// for webpack 4 { target: WebExtensionTarget(nodeConfig) } // for webpack 5 { target: false, plugins: [ WebExtensionTarget(nodeConfig) ] }Note: Codemod for this change:
npx codemod webpack/v5/set-target-to-false-and-update-plugins(See the registry here.)
-
If you have
output.libraryoroutput.libraryTargetdefined, rename the properties (output.libraryTarget→output.library.type,output.library→output.library.name). For example:// for webpack 4 { output: { library: 'MyLibrary', libraryTarget: 'commonjs2' } } // for webpack 5 { output: { library: { name: 'MyLibrary', type: 'commonjs2' } } }Note: Codemod for this change:
npx codemod webpack/v5/migrate-library-target-to-library-object(See the registry here.)
If you were importing WebAssembly, follow this two-step process:
- Enable the deprecated spec by setting
experiments.syncWebAssembly: true, which reproduces the webpack 4 behavior. - After successfully migrating to webpack 5, switch to
experiments: { asyncWebAssembly: true }to use the up-to-date WASM integration spec.
Reconsider optimization.splitChunks:
- It is recommended to use either the defaults or
optimization.splitChunks: { chunks: 'all' }. - If you use a custom configuration, drop
name: falseand replacename: string | functionwithidHint: string | function. - It used to be possible to turn off the defaults with
optimization.splitChunks.cacheGroups: { default: false, vendors: false }. We do not recommend this, but if you really want the same effect in webpack 5, useoptimization.splitChunks.cacheGroups: { default: false, defaultVendors: false }.
Consider removing values that are now defaults:
entry: './src/index.js'— you can omit it; it is the default.output.path: path.resolve(__dirname, 'dist')— you can omit it; it is the default.output.filename: '[name].js'— you can omit it; it is the default.
-
If you have browserslist enabled for your project, webpack 5 will reuse your
browserslistconfig to decide which code style to emit for the runtime code.Make sure to:
- Set
targettobrowserslist, or removetargetand let webpack setbrowserslistautomatically. - Add
IE 11to your browserslist configuration.
- Set
-
Without a
browserslist, webpack's runtime code uses ES2015 syntax (for example, arrow functions) to produce smaller bundles. In that case, settarget: ['web', 'es5']to emit ES5 syntax for browsers (such as IE 11) that do not support ES2015. -
For Node.js builds, include the supported Node.js version in the
targetoption, and webpack will work out which syntax is supported. For example,target: 'node8.6'.
Be clear about the intent:
- The chunk's name here is meant to be public.
- It is not a development-only name.
- webpack uses it to name files in both production and development modes.
- webpack 5 automatically assigns useful file names in
developmentmode even withoutwebpackChunkName.
This is not supported by the new specification, and you will get a warning. Instead of:
import { version } from './package.json';
console.log(version);use:
import pkg from './package.json';
console.log(pkg.version);Note: Codemod for this change:
npx codemod webpack/v5/json-imports-to-default-imports(See the registry here.)
- When using
const compiler = webpack(...);, close the compiler after you are done with it:compiler.close(callback);.- This does not apply to the
webpack(..., callback)form, which closes automatically. - This is optional if you use webpack in watch mode until the user ends the process. The idle phases in watch mode are used for this kind of work.
- This does not apply to the
Read the build errors and warnings carefully. If there is no corresponding advice, please open an issue and we will try to resolve it.
Repeat the following steps until you have at least reached level 3 or 4:
-
Level 1: Schema validation fails.
Configuration options have changed. There should be a validation error with a
BREAKING CHANGE:note, or a hint about which option to use instead. -
Level 2: webpack exits with an error.
The error message should tell you what to change.
-
Level 3: Build errors.
The error message should include a
BREAKING CHANGE:note. -
Level 4: Build warnings.
The warning message should tell you what can be improved.
-
Level 5: Runtime errors.
These are tricky; you will probably need to debug to find the problem. General advice is difficult here, but a few common cases are listed below:
processis not defined.- webpack 5 no longer includes a polyfill for this Node.js variable. Avoid using it in frontend code.
- Want to support browser usage? Use the
exportsorimportsfield inpackage.jsonto serve different code depending on the environment.- Also use the
browserfield to support older bundlers. - Alternatively, wrap code blocks with
typeof processchecks. Note that this increases bundle size.
- Also use the
- Want to use environment variables via
process.env.VARIABLE? UseDefinePluginorEnvironmentPluginto define those variables in your configuration.- Consider using
VARIABLEdirectly instead, and checktypeof VARIABLE !== 'undefined'as well.process.envis Node.js-specific and should be avoided in frontend code.
- Consider using
- 404 errors pointing to URLs containing
auto.- Not all ecosystem tooling is ready for the new default automatic
publicPath(output.publicPath: "auto").- Use a static
output.publicPath: ""instead.
- Use a static
- Not all ecosystem tooling is ready for the new default automatic
Cannot read properties of undefined (reading 'call').- If you see this at runtime, it may be related to the ModuleConcatenationPlugin. Check whether you are using the plugin: if you have added it to the
pluginssection of a config that is also set toproductionmode, remove it (for example,new webpack.optimize.ModuleConcatenationPlugin()). In webpack 5 the plugin is enabled by default in production mode, so it may get included twice. - In general, disabling each plugin and testing the build is a good way to narrow down where the issue comes from.
- See this issue for more details.
- If you see this at runtime, it may be related to the ModuleConcatenationPlugin. Check whether you are using the plugin: if you have added it to the
-
Level 6: Deprecation warnings.
You will probably see many deprecation warnings. This is not directly a problem; plugins need time to catch up with core changes. Please report these deprecations to the affected plugins. They are only warnings, and the build will still work with minor drawbacks (such as reduced performance).
- You can hide deprecation warnings by running Node with the
--no-deprecationflag, for example:node --no-deprecation node_modules/webpack/bin/webpack.js. This should only be a temporary workaround. - Plugin and loader authors can follow the advice in the deprecation messages to improve their code.
- You can hide deprecation warnings by running Node with the
-
Level 7: Performance issues.
Performance usually improves with webpack 5, but there are a few cases where it gets worse.
Here are some things you can do to improve the situation:
- Profile where the time is spent.
--profile --progressnow displays a simple performance profile.node --inspect-brk node_modules/webpack/bin/webpack.jstogether withchrome://inspectoredge://inspect(see the profiler tab).- You can save these profiles to files and attach them to issues.
- Try the
--no-turbo-inliningflag for better stack traces in some cases.
- Module build time for incremental builds can be improved by reverting to unsafe caching like in webpack 4:
module.unsafeCache: true- However, this may affect the ability to handle some changes to the code base.
- Full builds:
- The backward-compatibility layer for deprecated features generally performs worse than the new features.
- Generating many warnings can hurt build performance, even when those warnings are ignored.
- Source maps are expensive. Check the
devtooloption in the documentation for a comparison of the available choices. - Anti-virus protection can affect the performance of file system access.
- Persistent caching can improve repeated full builds.
- Module Federation lets you split the application into several smaller builds.
- Profile where the time is spent.
Please tweet that you have successfully migrated to webpack 5. Tweet it
Create an issue and tell us about the problems you encountered during the migration.
Please open a Pull Request to help the next person who uses this guide.
The following changes to webpack internals (added types, refactored code, renamed methods) are listed here for anyone interested, but they are not part of the common migration path.
Module.nameForCondition,Module.updateCacheModule, andModule.chunkConditionare no longer optional.
webpack 5 ships with a built-in this.getOptions method available in the loader context. This is a breaking change for loaders that previously used the getOptions method from schema-utils:
this.getOptionsis available since webpack 5.- It supports JSON rather than JSON5 as a query string:
?{arg:true}→?{"arg":true}. Using JSON5 should be considered deprecated and documented as such in each loader's documentation, in favor of JSON. loader-utilshad specific behavior for parsing query strings (true,false, andnullwere parsed as primitives rather than strings). This is no longer the case for the new built-inthis.getOptionsmethod, which uses Node.js's nativequerystringparsing. You can still add custom handling for these cases in your loader's code after callingthis.getOptions.- The schema argument is optional for the new
this.getOptionsmethod, but we strongly recommend adding schema validation for your loader's options. Thetitlefield in the schema can customize the validation error message; for example,"title": "My Loader ooooptions"produces errors likeInvalid 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.