webpack 5 is coming!

Amy M
7 min readJun 12, 2019

--

Extra, extra! webpack 5 is coming…

Tobias Koppers mentioned in his talk at JSNation Amsterdam this past week that webpack developers tend to dislike breaking changes.

He held a poll on his twitter account in the summer of 2017 where respondents said they’d like a major release every 4 to 6 months.

So, why now?

webpack 4 shipped a whopping 33 minor and 43 patch releases.

Technical debt

With so many ‘hacks’ and ‘todos’ mounting in the codebase whilst trying to avoid a major release for as long as possible to keep the community happy, technical debt can start to get out of hand and is bad for the project in the long run.

User demand

Right now, on the webpack voting page the two most requested webpack features are as follows:

Votes cast for Persistent Caching and Consistent Hashing totalling over 313,514 and 286,638 respectively

Persistent Cache

What’s the issue?

Incremental builds in watch mode are fast, but restarting webpack can be super slow.

Persistent cache promises to:

  • improve build start up performance.
  • cache on disk (or other persistent mediums)

Consistent Hashing

What’s the issue?

  • People have difficulties using hashing for long term caching.
  • webpack changes file content more often than expected

Consistent hashing promises to:

  • Make hashing easier and more reliable.

Both of these features have been added to webpack v5!

npm install —save-dev webpack@next

What’s going to break?

Say goodbye to deprecated features from v4

All features that were deprecated in v4 of webpack will be removed from v5. So when you start migrating to v5 make sure that you don’t have any deprecation warnings.

The CommonsChunkPlugin was removed.

module.loaders were deprecated since webpack 2 and were removed in favour of module.rules.

The IgnorePlugin and BannerPlugin have also been removed and must be passed as an options object.

Automatic Node.js polyfills are history

Using polyfills makes it easy to use modules written for Node.js, however this also increases the bundle size as core module polyfills are often very large.

Developers are often unaware of the fact that they are using node core module polyfills as it is too easy to accidentally include them.

Polyfills are often outdated and the native web platform doesn’t support them. Polyfills differ from node core modules due to these browser limitations.

To prevent this, webpack 5 removes this automatic polyfilling and focuses on frontend focused modules.

Users will now have better control of the versions of polyfills used and the install size of webpack will decrease.

Migration:

Use frontend compatible modules whenever possible.

Users can still opt-in to use polyfills by installing them manually and setting an alias in their config files.

Modernization

webpack 5 sees a bump in the minimum node.js version from version 6 to version 8.

You should update your node.js version to the latest version.

In addition to this, we will also avail of new data structures like Sets for Array like objects and Maps for objects.

Compilation.modules and Compilation.chunks are now Setsand as such, you should use Set methods instead of Array methods.

Deterministic by default

New algorithms were added for long term caching. These are enabled by default in production mode.

When migrating from webpack 4 to webpack 5, you should run tests on your bundle sizes and calculate the difference to see if long term caching is relevant for you. It most likely is.

However, if your bundle size is of a higher priority to you than long term caching you might want to opt in for size optimization.

It’s worth noting that this is only a breaking change in production environments/build configurations.

New algorithms were also added to mangle export names. It is enabled by default and will mangle export names in a deterministic way when possible.

Migration:

It is recommended to use the default values for chunkIds and moduleIds.

chunkIds: “deterministic”, 
moduleIds: “deterministic”

You can also opt-in to the old defaults:

chunkIds: “size”, 
moduleIds: “size”

The old defaults will generate smaller bundles, but it will invalidate them more often for caching.

There are no steps necessary for migrating to more deterministic mangle export names.

Async caching

The caching interface is synchronous and very limited because it was created for a single use case: in-memory caching.

In webpack 5, the interface has changed to be async and extensive via plugins.

Changes to the way the caching interface will affect plugins authors and therefore some of the plugins you use may break as a result of the changes to the interface.

Cost of caching

Persistent caching is more expensive due to serialisation and disk allocation. Persistent caching should be run when the compiler is idle or closing.

The issue: the public compiler API has no notation about closing or disposing of the persistent cache.

The solution: a close method has been added that you should call.

New filenames by default

A new named chunk ID algorithm enabled by default in development mode gives chunks and filenames human-readable names.

— A module ID is determined by its path, relative to its context.

— A chunk ID is determined by the chunk’s content.

For example, instead of getting useless bundle names like:

1.bundle.js, 2.bundle.js

The new algorithm will generate more useful names like:

import(‘./lazy-loaded’) would generate a bundle with a name like:

src_lazy-loaded_js.bundle.js

A split chunk for react-dom would generate a bundle with a name like:

react_react-dom.bundle.js

In most cases, there is nothing to do. If you wish, you can omit:

webpackChunkName: “name”

It’s worth noting that this is only a breaking change in development environments/build configurations.

It’s possible to use chunkIds: "named" in production. However, be cautious and make sure you do not accidentically expose sensitive information about module names.

Migration:

You no longer need to use import(/* webpackChunkName: "name" */ "module") for debugging. But it would still make sense, if you want to control the filenames for production environments.

If you don’t want your filenames to be changed whilst in development, you can set the following value, in order to use the old numberic mode:

chunkIds: “natural”

Serialization

What’s the issue?

In JavaScript it is easy to handle serialization of simple objects. Module objects have not been serializable in webpack due subclasses, non primitive nested objects like Dependencies, Sources and Source Maps.

Now what?

A serialization mechanism has been added to allow for serialization of complex objects. Classes that should be serialized need to be explicitly flagged.

Migration:

When using custom modules or dependencies, it is recommended to make them serializable to benefit from persistent caching.

Changes to SplitChunks and Module Sizes values

Modules now express size differently. Rather than displaying a single number, there are different measures of size.

The SplitChunksPlugin now knows how to handle these different values and uses them for minSize and maxSize.

By default, only JavaScript is handled. But you can now pass mutiple values to manage size limits:

minSize: {
javascript: 30000,
style: 50000,
}

Migration:

Check which types of sizes are used in your builds and configure the values in the splitChunks.minSize and optionally in splitChunks.maxSize

Hot Module Replacement

Hot module replacement will now be extensible via plugins in webpack v5.

Previously, hot module replacement had only been available for JavaScript modules but it will now support style modules for CSS.

Tobias has said that in a future minor release, they could possibly support WASM and html hot module replacement too.

Changes to default values

optimization.moduleIds

Defaults to deterministic in production mode, instead of size

optimization.moduleIds

Defaults to deterministic in production mode, instead of size

optimization.chunkIds

Defaults to deterministic in production mode, instead of total-size

optimization.nodeEnv

Defaults to false in none mode

optimization.splitChunks minRemainingSize

Defaults to minSize (since alpha.13). This will lead to less split chunks created in cases where the remaining part would be too small

resolve(Loader).cache

Defaults to true when cache is used

resolve(Loader).cacheWithContext

Defaults to false

node.global

Defaults to false (since alpha.4 removed)

resolveLoader.extensions

remove .json (since alpha.8)

node.global node.__filename and node.__dirname

Defaults to false in node-targets (since alpha.14)

NOTE

I put this article together by assembling all of the valuable information found in the resources mentioned below.

I was inspired to do so after having seen Tobias’ talk at Amsterdam JSNation last week. My hope is to help inspire other developers to be excited and prepared for the new changes and features coming to webpack v5.

If you use webpack, please consider making a donation here: https://opencollective.com/webpack

Sources:

--

--

Amy M

Software developer specialist working on delivering at scale across a global enterprise.