Tree Shaking, a modern dead code elimination algorithm for ECMAScript 2015+ is one of the most anticipated features in the upcoming Webpack 2. By eliminating unused ES6 exports, Webpack can further help the minification process to get your bundle much smaller than ever before.
Tree shaking, ultimately, bundles only the modules you import into your scripts. Any exports that were not imported will not be in the final JavaScript build.
In the sample code below, I will show how my new Webpack 2 configuration helped cut out 28% of my already optimized Webpack 1 project.
Update 04/25/2017: Sample code has been updated to a fully functional and reusable React application that uses Webpack 2, React Router 4 and import() syntax, set up in a highly performant PRPL pattern. Links in this article point to the old version so make sure you check out version 2.
Update 11/14/2016: Webpack 2 sample application code has been updated to match the most recent updates in Webpack (v2.2), React (v15.4) and Babel.
CommonJS Out, Native Imports In
Webpack 2 now knows how to work out the imports natively, without having to convert them to CommonJS modules. This is very important because CommonJS exports leaves references alive, meaning everything you declared in exports will have to be included in your final build.
To cut a long story short, you need to slightly adjust your .babelrc configuration. Instead of es2015
preset, you’ll need a new one named babel-preset-es2015-native-modules
. This preset tells Babel to skip CommonJS module conversion during the transpilation process.
Your new .babelrc
will look like this:
{ "presets": ["es2015-native-modules"] } Or, if you use React { "presets": ["es2015-native-modules", "react"] }
Your Babel configuration is now ready. Essentially, this was all it takes for tree shaking to work in Webpack 2.
Now, let’s shift focus on some of the important updates in Webpack 2 configuration for those who want to convert from v1.x.
Migrating from Webpack 1 to Webpack 2
Tree shaking works out of the box in Webpack 2. If you have an existing project, chances are you will want to upgrade your old configuration. Alternatively, some of you might use seed projects that were meant to work with Webpack 1.x. Let’s review just a few of the breaking changes that will likely require you to update some of the settings.
- Loaders configuration
- Resolvers
- Uglify Plugin Changes
- Other changes
There have been minor improvements in how you define loader configuration. The previous GET-like syntax has been replaced with JSON-style notation.
Let’s observe this Webpack 1.x example:
loaders: [ { test: /\.html$/, loader: 'file?name=[name].[ext]' } ]
The Webpack 2.x version of the same would look like this:
loaders: [ { test: /\.html$/, loader: 'file', query: { name: '[name].[ext]' } } ]
Notice how query parameters are now neatly stacked as key-value pairs.
In Webpack 2, resolvers from root
, modulesDirectories
, and fallback
settings will merge into a single property – modules
. Here is how we can resolve file and module locations in Webpack 2:
resolve: { modules: [ path.resolve('./client'), 'node_modules' ] },
You can specify a number of directories in modules
, but make sure not to forget node_modules
or npm package dependencies will fail to load.
The UglifyJsPlugin will no longer put loaders into minimize mode, and the debug option has been deprecated. These options are simply moved into a new plugin, LoaderOptionsPlugin, for separation of concerns reasons. Use it as such:
new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }),
Tobias Koppers aka Sokra published a very useful What’s new in Webpack 2 gist, which I highly recommend looking at.
Working Example
Take a look at this sample React + Redux + Webpack 2 sample app that leverages all of the important configuration settings that will make your production build smaller than ever. Comparing to the original Webpack 1.x version of the same app, the size went down by a whopping 28%.
Take a look yourself and share this with your network. Someone will surely want to optimize their webpack build using the new tree shaking technology.
Grgur Grisogono
Related Posts
-
ES6 Import Statement Without Relative Paths Using Webpack
The ES2015 module system is probably familiar to you by now. If you’ve used it,…
-
Optimizing React + ES6 + Webpack Production Build
Writing a web application in React using the ES6 awesomeness and spiced up with Webpack…