Optimize your bundle’s weight with webpack

webpack-logo

The usage of a package manager for the dependencies in front-end JavaScript development has become mainstream for some time now. One of the downsides is that since it’s now very easy to install and require external modules in your application, if you’re not careful, you’ll end up with a big main.js file in production …

To avoid that, you can use multiple strategies of optimization:

  • uglify
  • deduplicate code
  • split your bundle in multiple ones and only load them on demand

But the very first thing to do is to drop the unnecessary code. For that, webpack provides the Webpack.DefinePlugin which lets you inject your own variables at build time, so that if they are set to false in a conditional, the minification step will drop the dead code.

But if you are using ES6 modules import statement, there is a catch …

webpack.config.js

module.exports = {
  //...
  plugins:[
    new webpack.DefinePlugin({
      '__DEVTOOLS__': false //set it to true in dev mode
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress:{
        warnings: true
      }
    })
  ]
  //...
}

test.js

import { DevTools, logger } from 'some-devtools';

if(__DEVTOOLS__){
  DevTools();
  logger();
}

With this configuration, the code inside the if statement will be dropped at minification since it will be inlined as if(false). But you’ll still be importing those packages that you won’t be using (aka dead code).

In this case you shouldn’t be using ES6 static imports but CommonJS require syntax:

if(__DEVTOOLS__){
  const { DevTools, logger } = require('some-devtools');
  DevTools();
  logger();
}

That way, if __DEVTOOLS__ === false, not only the calls inside this if statements will be dropped but the modules DevTools and logger wont even be part of the bundle, which will make it lighter.

Note: I made this example with webpack, but this kind of feature is available on other module bundlers such as browserify. An other way to resolve that kind of problem would be to specify a list of modules to exclude at build time in production mode …

Update: If you’re doing universal JavaScript (running your code on both client and server side), a good practice would be to use process.env.DEVTOOLS instead of __DEVTOOLS__. A good example is the React setup where you make your own production version of React.

Resources:

2 thoughts on “Optimize your bundle’s weight with webpack

  1. I changed how redux-logger was included in my project from using ES6 import to a require() statement inside the if statement, as recommended. It made little difference to the bundle filesize:

    import:
    3,047,992 index_bundle.js

    conditional require():
    3,047,885 index_bundle.js

    107 bytes.

    I thought it would be a more significant saving for exclusion of several hundred lines of JavaScript. Using require() is recommended by the redux-logger documentation:
    https://github.com/evgenyrodionov/redux-logger#log-only-in-development

Leave a Reply

Your email address will not be published. Required fields are marked *