Check out myAngular article series with live demos

Code Splitting in Webpack

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Wed Mar 08 2017

In this post I will show how to do code splitting in Webpack.

Bundling

I have already written several posts about JavaScript bundling. People might think I'm crazy for taking such an interest in application bundling, but I can't help it, I find it very interesting :-).

The focus of several of my articles have been on achieving the smallest possible bundle. I have mostly focused on single file bundles and tried to push the size to an absolute minimum. One example of this is my Angular bundle post.

Code Splitting

This is all well and good, but you eventually reach a point where it's no longer practical to download your entire application as a single file. At some point you have to start breaking your application into multiple bundles.

This is where code splitting comes into play. By breaking the application into multiple pieces, you are in a better position to serve just the part of your application that is relevant to the user's current operation.

In comparisons involving smallest single bundle, Webpack is usually dead last in terms of size, but this is often irrelevant. Rollup does far better here, but lacks support for code splitting.

Depending on your application it might not matter that the sum of your Webpack chunk sizes exceeds the size of a single Rollup bundle.

If you lazy load the different Webpack bundles on demand, your users may end up downloading just a fraction of the full Rollup bundle.

In the end, smaller, more targeted bundles often benefit the user more than a single bundle. This is of course not the case if your application offers little or no opportunity for lazy loading.

Enabling Code Splitting

In the following section I will show how to configure code splitting in its simplest form. I will split my code into two application bundles, plus a shared lib bundle with common code.

Here is the original code:

car-service.js
import { LoggerService } from './logger-service'; export class CarService { constructor() { this.logger = new LoggerService(); } getCar() { this.logger.logMessage('getting car'); return 'BMW'; } }
person-service.js
import { LoggerService } from './logger-service'; export class PersonService { constructor() { this.logger = new LoggerService(); } getPerson() { this.logger.logMessage('getting person'); return 'Joe Smith'; } }
logger-service.js
export class LoggerService { logMessage(msg) { console.log(msg); } }

CarService and PersonService will be split out into two distinct application bundles. The shared LoggerService will be extracted into a shared bundle.

Configuration

I've heard from several developers that Webpack configuration can be hard. I think this is more a symptom of people not being used to bundling in general, rather than a problem with Webpack. All the new terminology and talk about module formats may be a barrier to entry, but I suspect people will catch up quickly. Especially once they realize the benefits of optimized bundling.

In fact it's actually pretty easy to get a basic config going in Webpack. My sample is very basic, but you could easily extend this to a more advanced setup.

webpack-config.js
var path = require('path'); const webpack = require('webpack'); module.exports = { entry : { person: './src/code-splitting-webpack/person-service.js', car: './src/code-splitting-webpack/car-service.js' }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, '../../dist') }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'lib', minChunks: 2, filename: '[name].js', }) ] }

In my config I start by defining entry.person and entry.car as split points for my bundles. This is all we need to generate two distinct application bundles. The bundles are named based on a [name].bundle.js convention where [name] is a placeholder for “car” and “person”.

If I stopped now, I would have had a fully working application with two bundles. The only issue would be some duplication between the two bundles because of the shared LoggerService. By default LoggerService will be added to both bundles.

This is where the CommonsChunkPlugin can help us out. By telling Webpack to split common code out into a third, shared bundle I can get rid of the duplication in my bundles.

In this example the shared bundle is pretty straightforward, but you may not want to include all repeated code in a shared bundle. Notice the minChunks setting. This setting allows us to specify the minimum number of times code must be repeated before it's include it in the shared bundle.

I have deployed the code on Github in case you are interested in checking it out.

You can run the sample by executing the following Webpack command:

webpack --config webpack.config.js --progress

If you liked this article, it to your friends.

I also invite you to follow me on twitter