Webpack 4: обзор обновлений
На днях вышла новая версия популярной системы сборки Webpack 4.0. Команда опубликовала большой Changelog и восторженный пост на Medium с описанием обновлений системы.
К текущему моменту не все изменения описаны в официальной документации. В этой заметке — обзор новых возможностей и проблем, с которыми вы можете столкнуться при обновлении.

Режимы сборки
Добавлен обязательный параметр —mode, определяющий один их трех режимов сборки: production, development и none, от которых зависят различные оптимизации и внешний вид бандла. Режим production оптимизирован под уменьшение размера сборки, а development — уменьшение времени сборки. В режиме none все оптимизации отключены.
А еще можно сконфигурировать собственный режим, отключив или включив определенные оптимизации с помощью опций optimization.* в конфиге. Доступные настройки отсутствуют в документации, зато их описал основатель Webpack Тобиас Копперс в блоге на Medium.

import() CommonJS-модулей
Больше нельзя подключать CommonJS-модули через import(). То есть либо используйте require, либо пишите модули по стандарту ES6 modules.
CommonJS
const a = require(«./a») module.exports = < a, b: 2 >
ESM
import a from «./a» export default < a, b: 2 >
Удаленные плагины
- NoEmitOnErrorsPlugin или NoErrorsPlugin (не создает сборку при ошибках). Доступен из коробки как optimization.noEmitOnErrors. Включен по умолчанию в production mode
- ModuleConcatenationPlugin (объединяет несколько модулей в одном замыкании, чем уменьшает бандл и ускоряет выполнение). Теперь это делается из коробки в production mode, либо включается настройкой optimization.concatenateModules
- NamedModulesPlugin (улучшает внешний вид имени модуля при Hot Module Replacement, который обновляет только изменившиеся части сборки). Теперь это опция optimization.namedModules, которая включена по умолчанию в режиме development
- NewWatchingPlugin (улучшает пересборку при изменениях) — больше не требуется
- CommonsChunkPlugin (выделяет общие части нескольких точек входа в отдельную сборку) — заменен на набор API `optimize.splitChunks`. Авторы даже написали пост, сделали ролик и опубликовали gist на эту тему.
Минификация
Отдельным пунктом про UglifyJsPlugin. Он, наконец, научился поддерживать ES6 модули, но в базовой конфигурации он больше не нужен — для минификации сборки используется опция optimization.minimize = true, которая по умолчанию включена в режиме production. Не используемый код (dead code) Webpack теперь тоже вырезает без помощи UglifyJs.
Плагин или функцию, которая будет заниматься минификацией, можно переопределить в optimization.minimizer.
Типы модулей
Изначально Webpack был ориентирован именно на сборку JavaScript-файлов. Но впоследствии его стали применять для сборки всего на свете: CSS, HTML, картинок и тд, в процессе испытывая боль с конфигурацией точек входа, лоадерами и плагинами. Теперь появились Module Types:
- javascript/auto — JavaScript-модуль в формате CommonJS, AMD или ESM
- javascript/esm — строго ES-модуль. По умолчанию применяется для .mjs файлов.
- javascript/dynamic — либо CommonJs, либо AMD
- json — JSON-файл, которые теперь можно подключать напрямую через require или import. По умолчанию включен для .json файлов
- webassembly/experimental — модуль WebAssembly, по умолчанию для .wasm файлов
Типы модулей определяются либо автоматически по расширению файла, либо задаются с помощью свойства module.rules[].type в конфиге.
По словам разработчиков, введение типов позволит им в следующих обновлениях Webpack добавить возможность создавать CSS, HTML и другие сборки, без точки входа на JavaScript.
Webpack-cli вынесен в отдельный проект
Это значит, что чтобы запускать сборку из командной строки или через менеджер пакетов, нужно установить webpack-cli вручную.
npm install —save-dev webpack-cli
yarn add —dev webpack-cli
Поддержка WebAssembly
Появилась возможность подключать WebAssembly-модули через import или require. Другими словами, в сборку можно подключать бинарные скрипты C++, C, Rust и другие, но для этого потребуются соответствующие лоадеры.
Сами модули WebAssembly тоже могут «реквайрить» другие .js и .wasm модули.
Поддержка sideEffects: false в package.json
Свойство sideEffects в файле package.json в значении false сообщает, что пакет не содержит действий, изменяющих состояние внешних переменных, DOM-узлов и тд.
Он упрощает встроенный Tree Shaking и оптимизирует сборку переиспользуемых частей кода.
sideEffects можно переопределить для каждого модуля в свойстве module.rules
Магические комментарии к динамическим импортам
В Webpack конструкции вида
modulesList.forEach( module => require(‘src/’ + module) );
по умолчанию не поддерживаются, так как система на этапе сборки не знает значение переменных.
Возможность создавать динамические импорты реализуется с помощью ContextReplacementPlugin, который заранее включает в сборку файлы по заданным паттернам. Еще один вариант динамических импортов — асинхронная подгрузка модулей через Code Splitting.
Суть обновления в том, что теперь вы можете фильтровать файлы в динамических импортах с помощью магических комментариев webpackInclude и webpackExclude. В документации описания этой возможности нет, но делается примерно так:
import( /* webpackExclude: «system.js» */ ‘module’ );
Больше информации при сборке
- Добавлена валидиция настроек плагинов. Поддерживаются не все, но какие — не уточняется.
- ProgressPlugin, включаемый опцией —progress, теперь выводит названия плагинов рядом с процентами прогресса сборки
- Опция Stats теперь выводит названия вложенных модулей
- Некорректное значение options.dependencies приводит к ошибке сборки
- Больше информации при ошибках подгрузки chunk-модулей.
- Более понятное сообщение о том, что какой-то плагин был удален
Работа с переменными окружения
Если раньше вы передавали чувствительные данные, хранящиеся в переменных окружения с помощью DefinePlugin, то теперь это можно сделать «из коробки» с помощью optimization.nodeEnv: true, тогда они автоматически попадут в proccess.env.NODE_ENV.*
Этой возможности нет в Changelog, но она есть в исходниках. И, видимо, в определенный момент появится в документации.
Source Maps
Опция devtools теперь поддерживает свойства include, test и exclude.
В режиме development по умолчанию генерируются source maps типа eval. Для более детальной настройки source maps разработчики рекомендуют использовать SourceMapDevToolPlugin.
Дефолтная конфигурация
Для простейшей сборки больше не требуется webpack.config.js, тк ряд обязательных параметров получил значения по умолчанию.
- Точка входа по умолчанию — ./src/index.js
- Output-директория, в которой окажется сборка — ./dist
- Режим сборки по умолчанию — production
Если вы занимаетесь разработкой лоадеров или плагинов для Webpack, обратите внимание на список изменений в API без обратной совместимости.
Troubleshooting
Если вы решили обновить версию Webpack, то начать лучше с удаления всех модулей и плагинов (а лучше — всей локальной папки node_modules), после чего установить новый Webpack и затем — поставить плагины заново. Это сэкономит время на решении проблем с совместимостью и обновлением зависимостей.
Дальше разбор некоторых частых ошибок.
The CLI moved into a separate package: webpack-cli. Please install ‘webpack-cli’ in addition to webpack itself to use the CLI. -> When using npm: npm install webpack-cli -D -> When using yarn: yarn add webpack-cli -D
Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead.
— отключить плагин, заменить на optimization.minimize: true
WARNING in configuration The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.
— передать —mode production (или development) при запуске скрипта webpack
npm WARN extract-text-webpack-plugin@2.1.2 requires a peer of webpack@^2.2.0 but none was installed.
— избавиться от ExtractTextWebpackPlugin (разработчики за полтора месяца тестирования беты Webpack 4 не предоставили обновления), либо, потратив N-времени в гугле, найти и установить нестабильную альфу.
npm i —save-dev [email protected]
Зачем это все
Шон Ларкин, технарь Microsoft Edge и один из ведущих разработчиков Webpack и Angular Cli, провел опрос в твиттере с предложением сравнить скорость сборки до и после обновления на 4 версию. По его словам, прирост составил до 98%

Что дальше
А дальше последуют патч-версии (читай, багфиксы), одна из которых вышла пока писался этот материал. Существенный прирост в скорости сборки во многом был обусловлен рефакторингом ядра, который позволит реализовать старые featue-реквесты и свежие идеи на обновленном API. Шон уже озвучил ряд нововведений, которые появятся либо в минорных обновлениях четвертой версии, либо, вероятнее всего, в Webpack 5.
- ESM Module Target
- Persistant-кэширование (видимо, не будет сбрасываться при остановке watch)
- Поддержка WebAssembly-модулей станет stable, добавление Tree Shaking
- Расширение 0CJS — то есть сборки без конфигурации. По сути — расширение пула дефолтных значений.
- «Многопоточная» сборка.
- CSS Module Type. Можно будет создавать отдельные CSS сборки со своей точкой входа. Шон попрощался с ExtractTextWebpackPlugin (и со всеми контрибьютерами этой разработки)
- То же самое с HTML Module Type
- URL/File Module Type. То есть в качестве точки входа скоро сможет выступить даже изображение.
- [Create-Your-Own] Module Type. Вот что назвается, рефакторинг.
Шон завершает публикацию словами о Ренессансе JavaScript и «переосмыслении» миссии Webpack.
А мы продолжаем работать.
If you like this article, share a link with your friends
Read more
We talk about interesting technologies and share our experience of using them.
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 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. 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.
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
As 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: true
- optimization.occurrenceOrder: true → optimization:
- optimization.splitChunks.cacheGroups.vendors → optimization.splitChunks.cacheGroups.defaultVendors
- optimization.splitChunks.cacheGroups.test(module, chunks) → optimization.splitChunks.cacheGroups.test(module, < chunkGraph, moduleGraph >)
- Compilation.entries → Compilation.entryDependencies
- serve → serve is removed in favor of DevServer
- Rule.query (deprecated since v3) → Rule.options / UseEntry.options
- Rule.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.
tip
webpack 5 removes these options from the configuration schema and will always use false .
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.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 are using something like node.fs: ’empty’ replace it with resolve.fallback.fs: false .
- If you are using watch: true in webpack Node.js API, remove it. There’s no need to set it as it’s indicated by the compiler method you call, either true for watch() or false for run() .
- If you have rules defined for loading assets using raw-loader , url-loader , or file-loader , please use Asset Modules instead as they’re going to be deprecated in near future.
- If you have target set to a function, update it to false and apply that function within plugins option. See example below:
// for webpack 4 target: WebExtensionTarget(nodeConfig) > // for webpack 5 target: false, plugins: [ WebExtensionTarget(nodeConfig) ] >
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 experiments value to experiments: < asyncWebAssembly: true >to use the up-to-date spec for WASM integration.
- It’s recommended to use either the defaults or optimization.splitChunks: < chunks: 'all' >.
- When using a custom configuration, drop name: false and replace name: string | function with idHint: 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 browserslist config to decide which code style to emit for the runtime code. Make sure to:
- set target to browserslist or remove target letting webpack set browserslist automatically for you.
- add a IE 11 to your browserslist configuration.
- Without a browserslist webpack’s runtime code uses ES2015 syntax (e.g., arrow function) to build smaller bundles. Hence you’ll need to set target: [‘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 target option 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 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'; console.log(version);
import pkg from './package.json'; console.log(pkg.version);
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.
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:
- process is 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 exports or imports package.json field to use different code depending on the environment.
- Also use the browser field to support older bundlers.
- Alternative: Wrap code blocks with the typeof process checks. Note that this will have a negative impact on the bundle size.
- Consider using VARIABLE instead and make sure to check typeof VARIABLE !== ‘undefined’ too. process.env is Node.js specific and should be avoided in frontend code.
- Not all ecosystem tooling is ready for the new default automatic publicPath via output.publicPath: «auto»
- Use a static output.publicPath: «» instead.
- 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 advice in the deprecation messages to improve the code.
- Profile where the time is spent.
- —profile —progress displays a simple performance profile now
- node —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-inlining flag for better stack traces in some cases.
- module.unsafeCache: true
- But this might affect the ability to handle some of the changes to the code base
- 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 devtool option 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.
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: ? → ? . Using JSON5 should be considered and documented as deprecated in favor of JSON in the 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.
Как обновить npm и пакеты npm ?
Как всегда, есть нюанс. Update обновляет пакеты в соответствии с записями из package.json , поэтому надо учитавать знаки больше/меньше, тильды, крышки и равно. Если пакет задан как = 1.0.67, то npm update его не обновит.
Если нужно поставить версии пакетов, отличные от записей в package.json, то следует воспользоваться командой npm install
Пара примеров, обновим глабально Angular CLI и Storybook CLI
Обновим npm через npm в рамках минорной версии
Обновим npm через npm с переходом на последнюю мажорную версию
Обновление npm на windows 10
На windows есть определённые проблемы с обновлением, если npm установлен вместе с nodejs. В этом случае лучше воспользоваться npm-windows-upgrade. Правая кнопка мыши по меню «Пуск» -> запуск консоли от имени администратора.
Далее следует ввести 3 команды и следовать инструкциям
Дополнительная информация
Посмотреть версию установленного пакета
Посмотреть устаревшие пакеты
Посмотреть последнюю версию пакета в репозитарии npm (которая устанавливается по npm i )
versionНапример, посмотреть версию последней альфы Storybook CLI
How to Upgrade to React 17 and Webpack 5 Step by Step
To be able to use Micro-Frontends in my org, I had to upgrade legacy apps to React 17 and Webpack 5. Of course, as with every upgrade, we always need to fix dependencies. The following article explains the steps I followed to upgrade and fix issues I faced. I hope it is going to be helpful and save you some time searching for solutions 🙂
- Make sure your Node version is above 10.13.0
> node -v v12.21.0
- Install Webpack 5
> yarn add webpack@latest yarn add v1.22.10 .
- Upgrade to React 17
> yarn upgrade react-scripts@4.0.0 react@17.0.0 react-dom@17.0.0
After Installing the latest Webpack, follow the following steps:
1. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
rm -rf yarn.lock or rm -rf package-lock.json
2. Delete node_modules in your project folder.
rm -rf node_modules
3. Remove «Webpack» from dependencies and/or devDependencies in the package.json file in your project folder.
4. Run npm install or yarn, depending on the package manager you use.
> yarn install --frozen-lockfile
Try to run the project and fix dependencies:
> yarn run start
If you receive a mismatch similar to the following, update your Package.json with this version and repeat the previous steps, again.
1. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
rm -rf yarn.lock
2. Delete node_modules in your project folder.
rm -rf node_modules
3. Remove «babel-eslint» (or whatever the error message has) from dependencies and/or devDependencies in the package.json file in your project folder OR update the version as mentioned in the error as shown in the image below:
4. Run npm install or yarn, depending on the package manager you use.
Most probably you will keep repeating those steps for multiple dependencies. I have done them for Webpack, babel-eslint (^10.1.0), babel-jest(^26.6.0), babel-loader(8.1.0), «eslint»: «^7.11.0», «jest»: «26.6.0», «webpack-dev-server»: «3.11.0»
If you still see errors, create an env file «a.env» and add the following to it
SKIP_PREFLIGHT_CHECK=true
Apps created with create-react-app (CRA)
Since CRA does not support Webpack 5, yet (follow the issue at https://github.com/facebook/create-react-app/issues/9994 ), you might try the following workaround methods:
1. CRACO
You may Use CRACO. Follow the following article for more details:
2. Eject
The tradeoff is that these tools are preconfigured to work in a specific way. If your project needs more customization, you can «eject» and customize it, but then you will need to maintain this configuration.
3. Dynamic Module Federation
There is one more possible solution by using Dynamic Module Federations https://medium.com/@christopherhorobin9/dynamic-module-federation-a6627b3c8eba that allows links from Non-Webpack projects
Here is the latest GitHub branch for CRA supporting Webpack 5 https://github.com/facebook/create-react-app/tree/wp5
4. react-app-rewired
5. Side-Car Project:
You might try the sidecar project as explained in this article
- process is not defined.