Maximizing Efficiency with Webpack: Asynchronous Bundle Loading Techniques

Webpack is great. If bundle splitting and feature flags didn't convince you yet, then hopefully async bundle loading will!

What is async bundle loading?

Async bundle loading is the act of loading a bundle asynchronously as the name suggests. It's very useful when you have pieces of code that are not necessary in every part of your application.

Imagine that you have a picture hosting site like Imgur. There are probably more people visiting your albums to just view pictures than to upload them. It would not make sense to have your users download the code for uploading images if they're not going to use it. On the other hand, you don't want your users to navigate to a new page just to upload a few pictures.

This is where async bundles shine.

Setting up async bundles

I use the webpack.config.js from my webpack-basic project. However, you don't need any extra configuration. It works out of the bundle box (no more bad jokes I promise).

Using async bundles

Let's set up our index.js:

document.querySelector('button')
  .addEventListener('click', () => {
    require.ensure([], => () {
      var upload = require('./image-upload');
      upload.showModal();
    });
  }, false);

It's just a simple event listener that listens to a click on a button. After that you'll see the weird require.ensure([] ...). This is necessary for async bundle loading.

Our image-upload.js is a really simple alert box, just to show that it works:

module.exports = {
  showModal: () => {
    alert('Image uploading modal');
  }
}

Just those few lines produce the following result:

As you can see in the gif, when I click the "Upload your own image" button, a new request gets made to 1.bundle.js. This is an asynchronous call. That's how easy it is really!

Syntactic sugar

What I use for my project is this very... very simple snippet:

function asyncRequire (cb) {
  require.ensure([], cb);
}

Our new code looks a bit cleaner now:

document.querySelector('button')
  .addEventListener('click', function (ev) {
    asyncRequire(() => {
      var upload = require('./image-upload');
      upload.showModal();
    });
  }, false);

That's a wrap

I hope this post was useful to you. Don't make your users download a 72mb app.js if you can split it up in bundles and load dependencies asynchronously.

If you liked it don't hesitate to message me on Twitter @Jilles.