Webpack 4 — Mysterious SplitChunks Plugin

Hemal Patel
Jun 4, 2018 · 5 min read
Image for post
Image for post

The official release of Webpack-4 boasts about the proven faster build time (around 98%) and reduced chunk sizes.

However, Webpack authors dropped a bomb in developer community by making one major announcement about the plugin responsible for the Code-Splitting across multiple entries. The documentation on CommonsChunkPlugin has the below notice.

This is my humble attempt to understand and help you with SplitChunksPlugin chunks option by taking a common example.

Image for post
Image for post

As an early enthusiast I tried to understand the sorcery behind Code-Splitting. The docs says that splitChunks.chunks accepts ‘initial’, ‘async’ and ‘all’. I was kinda confused, and it raised my curiosity even more!

I dug deeper into the documentation Github history and WebpackOptions Schema and found out that,

Image for post
Image for post
Image for post
Image for post

The idea here is to have 2 entry files a.js and b.js with same node_modules imported. Some of them will be imported dynamically, just to check the behavior of the Code-Splitting.

We’ll use the Webpack Bundle Analyzer Plugin to understand how our modules(node_modules) are being split actually.

a.js :

Only lodash is imported dynamically.

Image for post
Image for post

b.js :

React and lodash both are imported dynamically.

Image for post
Image for post

The primary reason I chose this configuration was to understand how Webpack config behaves when there is a common lib,

  1. Imported dynamically in one entry and imported non-dynamically - React
  2. Imported dynamically in both entries - lodash
  3. Imported non-dynamically in both entries - jquery

We’ll keep these files untouched and change Webpack config over chunks value.

1. chunks : “async” — Optimization over async module

Image for post
Image for post
webpack.config.js
Image for post
Image for post
BundleAnalyzer Plugin graph

chunks : ‘async’ tells webpack that,

Now, let’s see what happened step by step:

  • Webpack takes react from b.js and move it in new file, but keeps react from a.js as it is. As optimizations happens only on the dynamic modules, import("react") statement will cause separate file, while import "react" will not.
  • Webpack takes lodash from a.js and move it in a new file, which is referred by b.js as well.
  • There will be no optimizations for jquery even though it is referenced in both a.js and b.js. Why? (Hint : ‘Async’)

2. chunks : “initial” — Optimization over Sync Module

Image for post
Image for post
webpack.config.js
Image for post
Image for post
BundleAnalyzer Plugin graph

chunks : ‘initial’ tells webpack that,

Now, let’s see what happened step by step:

  • react from a.js will be moved to node_vendors~a.bundle.js while react from b.js will be moved to its separate bundle 0.bundle.js.
  • lodash from both a.js and b.js will be moved to 1.bundle.js . Why ? It is a dynamically imported module.
  • jquery being a common module which is being imported non-dynamically will be shared between a.js and b.js in node_vendors~a~b.bundle.js.

3. chunks : ‘all’ — Optimization over Async and Sync Module

Image for post
Image for post
webpack.config.js
Image for post
Image for post
BundleAnalyzer Plugin graph

chunks : ‘all’ tells webpack that,

Now, let’s see what happened step by step:

  • react is non-dynamically imported module in a.js and dynamically imported module in b.js. So, it goes to single file 0.bundle.js,which will be referred by both.
  • lodash is dynamically imported in both, so it obviously gets a separate file 1.bundle.js.
  • jquery is non-dynamically imported in both, so it goes to common shared module node_vendors~a~b.bundle.js,and will be referred by both.

Finally,

Image for post
Image for post
Image for post
Image for post

Many thanks to various discussions and blog posts of Tobias Koppers and Sean T. Larkin on Github, Medium and other channels to help me writing this.

Thank you Jamund Ferguson for writing this awesome post explaining your journey from RequireJS to Webpack. I would not be able to reach here without that.

DailyJS

JavaScript news and opinion.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store