Printable
Migrate
This section contains information about migrating from older versions of webpack to newer ones.
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), so make sure you upgrade your Node.js if you're still running an older one.
Upgrade webpack 4 and its plugins/loaders
-
Upgrade
webpack4 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-clito 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. Make sure to read release notes of each individual plugin/loader when upgrading it, since latest version might only support webpack 5 and will fail in v4. In such case, it's recommended to update to the latest version that supports webpack 4.
Codemods
To assist with the upgrade from webpack v4 to v5, Codemod provides open-source community codemods that can help automate most of the migration process.
Please note that these are not official webpack codemods, and while it aims to streamline the migration, it may not cover all cases. You may still need to perform additional manual steps to fully complete the upgrade.
Run the webpack v5 migration codemods:
npx codemod@latest webpack/v5/migration-recipeThis will run the following codemods from 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 codemods automates a change listed in the webpack v5 migration guide. For a complete list of available webpack v5 codemods, see Codemod Registry.
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.jsAs webpack 5 removes all deprecated features, make sure there's no webpack deprecation warnings during the build in order to proceed.
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: 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→serveis removed in favor ofDevServerRule.query(deprecated since v3) →Rule.options/UseEntry.optionsRule.loaders→Rule.use
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,
},
};You have to remove these options again when upgrading your configuration for webpack 5.
Upgrade webpack to 5
Now let's upgrade webpack to version 5:
-
npm:
npm install webpack@latest -
Yarn:
yarn add webpack@latest
If you were not able to upgrade some plugins/loaders to the latest in Upgrade webpack 4 and its plugins/loaders step, don't forget to upgrade them now.
Clean up configuration
-
Consider removing
optimization.moduleIdsandoptimization.chunkIdsfrom your webpack configuration. The defaults could be better, because they support long term caching inproduction modeand debugging indevelopmentmode. -
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
IgnorePluginwith a regular expression as argument, it takes anoptionsobject now:new IgnorePlugin({ resourceRegExp: /regExp/ }). -
If you are using something like
node.fs: 'empty'replace it withresolve.fallback.fs: false. -
If you are using
watch: truein webpack Node.js API, remove it. There's no need to set it as it's indicated by the compiler method you call, eithertrueforwatch()orfalseforrun(). -
If you have
rulesdefined for loading assets usingraw-loader,url-loader, orfile-loader, please use Asset Modules instead as they're going to be deprecated in near future. -
If you have
targetset to a function, update it tofalseand apply that function withinpluginsoption. See example below:// 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.library or output.libraryTarget defined, change the property names: (output.libraryTarget -> output.library.type, output.library -> output.library.name). 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 using WebAssembly 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
experimentsvalue toexperiments: { asyncWebAssembly: 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 a custom configuration, drop
name: falseand replacename: string | functionwithidHint: string | function. - It was possible to turn off the defaults by setting
optimization.splitChunks.cacheGroups: { 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.cacheGroups: { default: false, defaultVendors: false }.
Consider removing defaults:
- Using
entry: './src/index.js': you can omit it, that's the default. - Using
output.path: path.resolve(__dirname, 'dist'): you can omit it, that's the default. - Using
output.filename: '[name].js': you can omit it, that's the default.
Need to support an older browser like IE 11?
-
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
targettobrowserslistor removetargetletting webpack setbrowserslistautomatically for you. - add a
IE 11to your browserslist configuration.
- set
-
Without a
browserslistwebpack's runtime code uses ES2015 syntax (e.g., arrow function) to build smaller bundles. Hence you'll need to settarget: ['web', 'es5']to use the ES5 syntax for browsers (like IE11) which don't support ES2015 syntax . -
For Node.js, builds include the supported Node.js version in the
targetoption and webpack will automatically figure out which syntax is supported, e.g.target: 'node8.6'.
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
developmentmode even when not usingwebpackChunkName.
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";
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.)
Cleanup the build code
- When using
const compiler = webpack(...);, make sure to close the compiler after using it:compiler.close(callback);.- This doesn't apply to the
webpack(..., callback)form which automatically closes. - This is optional if you use webpack in watching mode until the user ends the process. The idle phases in watch mode will be used for this kind of work.
- This doesn't apply to the
Run a single build and follow advice
Please make sure to read the building errors/warnings carefully. If there is no corresponding advice, please create an issue and we will try to resolve it.
Repeat the following steps 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, or a hint of which option should be used instead. -
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.
-
Level 5: Runtime Errors.
This is tricky. You probably have to debug to find the problem. General advice is difficult here. But we do list some common advice below regarding Runtime Errors:
processis not defined.- webpack 5 does no longer include a polyfill for this Node.js variable. Avoid using it in the frontend code.
- Want to support browser usage? Use the
exportsorimportspackage.json field to use different code depending on the environment.- Also use the
browserfield to support older bundlers. - Alternative: Wrap code blocks with the
typeof processchecks. Note that this will have a negative impact on the bundle size.
- Also use the
- Want to use environment variables with
process.env.VARIABLE? You need to use theDefinePluginorEnvironmentPluginto define these variables in the configuration.- Consider using
VARIABLEinstead and make sure to checktypeof VARIABLE !== 'undefined'too.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
publicPathviaoutput.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 error during runtime, it may be related to the ModuleConcatenationPlugin. Check if you are using the plugin, and if you've included it in the
pluginssections of a config, and that config is also set toproductionmode, remove the plugin (ienew webpack.optimize.ModuleConcatenationPlugin()) from your plugins list. In webpack 5, the plugin is enabled by default in production mode, and it may get included twice. - In general, disabling each plugin and testing the build is a good way to triage where the issue might be coming from.
- See: this issue for more details.
- If you see this error during runtime, it may be related to the ModuleConcatenationPlugin. Check if you are using the plugin, and if you've included it in the
-
Level 6: Deprecation Warnings.
You probably get a lot of deprecation warnings. This is not directly a problem. Plugins need time to catch up with core changes. Please report these deprecations to the plugins. These deprecations are only warnings and the build will still work with only minor drawbacks (like less performance).
- You can hide deprecation warnings by running node with
--no-deprecationflag, 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 advice in the deprecation messages to improve the code.
- You can hide deprecation warnings by running node with
-
Level 7: Performance issues.
Usually, performance should improve with webpack 5, but there are also a few cases where performance gets worse.
And here are something you can do to improve the situation:
- Profile where the time is spent.
--profile --progressdisplays a simple performance profile nownode --inspect-brk node_modules/webpack/bin/webpack.js+chrome://inspect/edge://inspect(see profiler tab).- You can save these profiles to files and provide them in issues.
- Try using
--no-turbo-inliningflag for better stack traces in some cases.
- Time for building modules in incremental builds can be improved by reverting to unsafe caching like in webpack 4:
module.unsafeCache: true- But this might affect the ability to handle some of the changes to the code base
- Full build
- Backward-compatibility layer for the deprecated features will usually have worse performance compared to the new features.
- Creating many warnings can affect build performance, even if they are ignored.
- Source Maps are expensive. Check
devtooloption in the documentation to see a comparison of the different options. - Anti-Virus protection might affect performance of the file system access.
- Persistent Caching can help to improve the repetitive full builds.
- Module Federation allows to split the application into multiple smaller builds.
- Profile where the time is spent.
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.updateCacheModuleandModule.chunkConditionare 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.getOptionsis 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 the respective Loader's documentation. loader-utilshas specific behavior for parsing query strings (true,falseandnullwon't be parsed asstringbut as a primitive value). This is no longer the case for the new built-inthis.getOptionsmethod, which uses nativequerystringparsing (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 usingthis.getOptionsmethod.- Schema argument is optional for the new
this.getOptionsmethod, but we strongly advise to add schema validation for your Loader's options. Thetitlefield 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.
To v4 from v3
This guide only shows major changes that affect end users. For more details please see the changelog.
Node.js v4
If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher.
Instructions for upgrading your Node.js version can be found here.
CLI
The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see basic setup.
The installation guide can be found here.
Update plugins
Many 3rd party plugins need to be updated to the latest versions to be compatible with webpack 4. Links to popular plugins can be found here.
mode
Add the new mode option to your configuration. Set it to 'production', 'development' or 'none' depending on your configuration type.
webpack.config.js
module.exports = {
// ...
+ mode: 'production',
}Deprecated/Removed plugins
These plugins can be removed from configuration as they are default in production mode:
webpack.config.js
module.exports = {
// ...
plugins: [
- new NoEmitOnErrorsPlugin(),
- new ModuleConcatenationPlugin(),
- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") })
- new UglifyJsPlugin()
],
}These plugins are default in development mode
webpack.config.js
module.exports = {
// ...
plugins: [
- new NamedModulesPlugin()
],
}These plugins were deprecated and are now removed:
webpack.config.js
module.exports = {
// ...
plugins: [
- new NoErrorsPlugin(),
- new NewWatchingPlugin()
],
}CommonsChunkPlugin
The CommonsChunkPlugin was removed. Instead the optimization.splitChunks options can be used.
See documentation of the optimization.splitChunks for more details. The default configuration may already suit your needs.
import() and CommonJS
When using import() to load non-ESM the result has changed in webpack 4. Now you need to access the default property to get the value of module.exports.
non-esm.js
module.exports = {
sayHello: () => {
console.log("hello world");
},
};example.js
function sayHello() {
import("./non-esm.js").then((module) => {
module.default.sayHello();
});
}json and loaders
When using a custom loader to transform .json files you now need to change the module type:
webpack.config.js
module.exports = {
// ...
rules: [
{
test: /config\.json$/,
loader: 'special-loader',
+ type: 'javascript/auto',
options: {...}
}
]
};When still using the json-loader, it can be removed:
webpack.config.js
module.exports = {
// ...
rules: [
{
- test: /\.json$/,
- loader: 'json-loader'
}
]
};module.loaders
module.loaders were deprecated since webpack 2 and are now removed in favor of module.rules.
To v2 or v3 from v1
The following sections describe the major changes from webpack 1 to 2.
resolve.root, resolve.fallback, resolve.modulesDirectories
These options were replaced by a single option resolve.modules. See resolving for more usage.
resolve: {
- root: path.join(__dirname, "src")
+ modules: [
+ path.join(__dirname, "src"),
+ "node_modules"
+ ]
}resolve.extensions
This option no longer requires passing an empty string. This behavior was moved to resolve.enforceExtension. See resolving for more usage.
resolve.*
Several APIs were changed here. Not listed in detail as it's not commonly used. See resolving for details.
module.loaders is now module.rules
The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more.
For compatibility reasons, the old module.loaders syntax is still valid and the old names are parsed.
The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using module.rules.
module: {
- loaders: [
+ rules: [
{
test: /\.css$/,
- loaders: [
- "style-loader",
- "css-loader?modules=true"
+ use: [
+ {
+ loader: "style-loader"
+ },
+ {
+ loader: "css-loader",
+ options: {
+ modules: true
+ }
+ }
]
},
{
test: /\.jsx$/,
loader: "babel-loader", // Do not use "use" here
options: {
// ...
}
}
]
}Chaining loaders
Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the rule.use
configuration option, use can be set to an array of loaders.
In webpack 1, loaders were commonly chained with !. This style is only supported using the legacy option module.loaders.
module: {
- loaders: [{
+ rules: [{
test: /\.less$/,
- loader: "style-loader!css-loader!less-loader"
+ use: [
+ "style-loader",
+ "css-loader",
+ "less-loader"
+ ]
}]
}Automatic -loader module name extension removed
It is not possible anymore to omit the -loader extension when referencing loaders:
module: {
rules: [
{
use: [
- "style",
+ "style-loader",
- "css",
+ "css-loader",
- "less",
+ "less-loader",
]
}
]
}You can still opt-in to the old behavior with the resolveLoader.moduleExtensions configuration option, but this is not recommended.
+ resolveLoader: {
+ moduleExtensions: ["-loader"]
+ }See #2986 for the reason behind this change.
json-loader is not required anymore
When no loader has been configured for a JSON file, webpack will automatically try to load the JSON
file with the json-loader.
module: {
rules: [
- {
- test: /\.json/,
- loader: "json-loader"
- }
]
}We decided to do this in order to iron out environment differences between webpack, node.js and browserify.
Loaders in configuration resolve relative to context
In webpack 1, configured loaders resolve relative to the matched file. However, in webpack 2, configured loaders resolve relative to the context option.
This solves some problems with duplicate modules caused by loaders when using npm link or referencing modules outside of the context.
You may remove some hacks to work around this:
module: {
rules: [
{
// ...
- loader: require.resolve("my-loader")
+ loader: "my-loader"
}
]
},
resolveLoader: {
- root: path.resolve(__dirname, "node_modules")
}module.preLoaders and module.postLoaders were removed:
module: {
- preLoaders: [
+ rules: [
{
test: /\.js$/,
+ enforce: "pre",
loader: "eslint-loader"
}
]
}UglifyJsPlugin sourceMap
The sourceMap option of the UglifyJsPlugin now defaults to false instead of true. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set sourceMap: true for UglifyJsPlugin.
devtool: "source-map",
plugins: [
new UglifyJsPlugin({
+ sourceMap: true
})
]UglifyJsPlugin warnings
The compress.warnings option of the UglifyJsPlugin now defaults to false instead of true.
This means that if you want to see uglifyjs warnings, you need to set compress.warnings to true.
devtool: "source-map",
plugins: [
new UglifyJsPlugin({
+ compress: {
+ warnings: true
+ }
})
]UglifyJsPlugin minimize loaders
UglifyJsPlugin no longer switches loaders into minimize mode. The minimize: true setting needs to be passed via loader options in the long-term. See loader documentation for relevant options.
The minimize mode for loaders will be removed in webpack 3 or later.
To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin:
plugins: [
+ new webpack.LoaderOptionsPlugin({
+ minimize: true
+ })
]DedupePlugin has been removed
webpack.optimize.DedupePlugin isn't needed anymore. Remove it from your configuration.
BannerPlugin - breaking change
BannerPlugin no longer accepts two parameters, but a single options object.
plugins: [
- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true});
+ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true});
]OccurrenceOrderPlugin is now on by default
The OccurrenceOrderPlugin is now enabled by default and has been renamed (OccurenceOrderPlugin in webpack 1).
Thus make sure to remove the plugin from your configuration:
plugins: [
// webpack 1
- new webpack.optimize.OccurenceOrderPlugin()
// webpack 2
- new webpack.optimize.OccurrenceOrderPlugin()
]ExtractTextWebpackPlugin - breaking change
ExtractTextPlugin requires version 2 to work with webpack 2.
npm install --save-dev extract-text-webpack-plugin
The configuration changes for this plugin are mainly syntactical.
ExtractTextPlugin.extract
module: {
rules: [
{
test: /.css$/,
- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" })
+ use: ExtractTextPlugin.extract({
+ fallback: "style-loader",
+ use: "css-loader",
+ publicPath: "/dist"
+ })
}
]
}new ExtractTextPlugin({options})
plugins: [
- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false })
+ new ExtractTextPlugin({
+ filename: "bundle.css",
+ disable: false,
+ allChunks: true
+ })
]Full dynamic requires now fail by default
A dependency with only an expression (i. e. require(expr)) will now create an empty context instead of the context of the complete directory.
Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the ContextReplacementPlugin to hint the compiler towards the correct resolving.
Using custom arguments in CLI and configuration
If you abused the CLI to pass custom arguments to the configuration like so:
webpack --custom-stuff
// webpack.config.js
const customStuff = process.argv.includes("--custom-stuff");
/* ... */
module.exports = config;You may notice that this is no longer allowed. The CLI is more strict now.
Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this.
webpack --env.customStuff
module.exports = function (env) {
const { customStuff } = env;
/* ... */
return config;
};See CLI.
require.ensure and AMD require are asynchronous
These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded.
require.ensure now depends upon native Promises. If using require.ensure in an environment that lacks them then you will need a polyfill.
Loader configuration is through options
You can no longer configure a loader with a custom property in the webpack.config.js. It must be done through the options. The following configuration with the ts property is no longer valid with webpack 2:
module.exports = {
// ...
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
},
],
},
// does not work with webpack 2
ts: { transpileOnly: false },
};What are options?
Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically options was called query and was a string which could be appended to the name of the loader. Much like a query string but actually with greater powers:
module.exports = {
// ...
module: {
rules: [
{
test: /\.tsx?$/,
loader: `ts-loader?${JSON.stringify({ transpileOnly: false })}`,
},
],
},
};But it can also be a separately specified object that's supplied alongside a loader:
module.exports = {
// ...
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
options: { transpileOnly: false },
},
],
},
};LoaderOptionsPlugin context
Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options.
To keep compatibility with old loaders, this information can be passed via plugin:
plugins: [
+ new webpack.LoaderOptionsPlugin({
+ options: {
+ context: __dirname
+ }
+ })
]debug
The debug option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options.
The debug mode for loaders will be removed in webpack 3 or later.
To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin:
- debug: true,
plugins: [
+ new webpack.LoaderOptionsPlugin({
+ debug: true
+ })
]Code Splitting with ES2015
In webpack 1, you could use require.ensure() as a method to lazily-load chunks for your application:
require.ensure([], (require) => {
const foo = require("./module");
});The ES2015 Loader spec defines import() as method to load ES2015 Modules dynamically on runtime. Webpack treats import() as a split-point and puts the requested module in a separate chunk. import() takes the module name as argument and returns a Promise.
function onClick() {
import("./module")
.then((module) => module.default)
.catch((err) => {
console.log("Chunk loading failed");
});
}Good news: Failure to load a chunk can now be handled because they are Promise based.
Dynamic expressions
It's possible to pass a partial expression to import(). This is handled similar to expressions in CommonJS (webpack creates a context with all possible files).
import() creates a separate chunk for each possible module.
function route(path, query) {
return import(`./routes/${path}/route`).then(
(route) => new route.Route(query),
);
}
// This creates a separate chunk for each possible routeMixing ES2015 with AMD and CommonJS
As for AMD and CommonJS you can freely mix all three module types (even within the same file). Webpack behaves similar to babel and node-eps in this case:
// CommonJS consuming ES2015 Module
const book = require("./book");
book.currentPage;
book.readPage();
book.default === "This is a book";// ES2015 Module consuming CommonJS
import fs from "node:fs"; // module.exports map to default
typeof fs.readFileSync === "function";// ES2015 Module consuming CommonJS
import { readFileSync } from "node:fs"; // named exports are read from returned object+
typeof readFileSync === "function";It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your .babelrc or babel-loader options.
.babelrc
{
"presets": [["es2015", { "modules": false }]]
}Hints
No need to change something, but opportunities
Template strings
Webpack now supports template strings in expressions. This means you can start using them in webpack constructs:
- require("./templates/" + name);
+ require(`./templates/${name}`);Configuration Promise
Webpack now supports returning a Promise from the configuration file. This allows async processing in your configuration file.
webpack.config.js
module.exports = function () {
return fetchLangs().then((lang) => ({
entry: "...",
// ...
plugins: [new DefinePlugin({ LANGUAGE: lang })],
}));
};Advanced loader matching
Webpack now supports more things to match on for loaders.
module.exports = {
// ...
module: {
rules: [
{
resource: /filename/, // matches "/path/filename.js"
resourceQuery: /^\?querystring$/, // matches "?querystring"
issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js"
},
],
},
};More CLI options
There are some new CLI options for you to use:
--define process.env.NODE_ENV="production" See DefinePlugin.
--display-depth displays the distance to the entry point for each module.
--display-used-exports display info about which exports are used in a module.
--display-max-modules sets the number for modules displayed in the output (defaults to 15).
-p also defines process.env.NODE_ENV to "production" now.
Loader changes
Changes only relevant for loader authors.
Cacheable
Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable.
// Cacheable loader
module.exports = function(source) {
- this.cacheable();
return source;
} // Not cacheable loader
module.exports = function(source) {
+ this.cacheable(false);
return source;
}Complex options
webpack 1 only supports JSON.stringify-able options for loaders.
webpack 2 now supports any JS object as loader options.
Before webpack 2.2.1 (i.e. from 2.0.0 through 2.2.0), using complex options required using ident for the options object to allow its reference from other loaders. This was removed in 2.2.1 and thus current migrations do not require any use of the ident key.
{
test: /\.ext/
use: {
loader: '...',
options: {
- ident: 'id',
fn: () => require('./foo.js')
}
}
}
