« Previous Tutorial Next Tutorial »

We’re back to Webpack management, which, let’s be honest … I could probably write a seventy-eight-tutorial series just on that topic, if I really wanted to. I’m not here to claim that we’re going to produce the world’s most-optimized Webpack bundle, but I will claim the following:

We’re going to reduce our dev bundle, which is now up to over 4.7 ridiculous megabytes of JavaScript and CSS, to well under one meg. We’re going to do that with a combination of Webpack modifications and setting Express to deliver compressed files.

So let’s dive in. We’re not going to have to make too many changes to Webpack because we already did the biggest things in tutorial 43 and tutorial 44. Still, we can make some improvements that’ll shave a few more bytes off the file, which is always valuable.

First, we need two new modules, so head for a terminal or command prompt, cd to your musiclist directory, and type the following:

yarn add compression-webpack-plugin@1.0.1 compression@1.7.1

Let that do its thing, and you’re good to go. Head for Sublime, open up webpack.config.js, and let’s get started. Below line 2, let’s import the module we just added, like this:

const CompressionPlugin = require('compression-webpack-plugin');

Now we’re going to throw a whole bunch of specific options at UglifyJS. I’d be remiss not to mention that I sourced some of my information for this tutorial from an excellent article by David Lazic over on Medium.

Find line 82 and change it to this big mass of code!

  module.exports.plugins.push(new webpack.optimize.UglifyJsPlugin({
    compress: {
      warnings: false,
      screw_ie8: true,
      conditionals: true,
      unused: true,
      comparisons: true,
      sequences: true,
      dead_code: true,
      evaluate: true,
      if_return: true,
      join_vars: true,
    },
    output: {
      comments: false,
    },
  }));

Now we’re going to add a built-in plugin that shortens module IDs slightly. It can shave a few bytes so, hey, what the hell, right? Below line 98, which closes our big UglifyJS plugin, add this line:

  module.exports.plugins.push(new webpack.HashedModuleIdsPlugin());

Then, below that, add this line:

  module.exports.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());

This is a Webpack 3 feature that enables scope hoisting. Without getting too into detail here, what this does is give preference to imports when loading JavaScript, which can speed up display times.

Now we want to tell Webpack that we’re always in production mode, which will cause it to eliminate a few extra things it would otherwise output. We do that by defining a custom plugin, so under line 100, add the following code:

  module.exports.plugins.push(
    new webpack.DefinePlugin(
      { 'process.env.NODE_ENV': JSON.stringify('production') },
    ),
  );

Last thing we want to do in this section is use the compression plugin we added earlier. So below line 105, add this code:

  module.exports.plugins.push(
    new CompressionPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
      threshold: 10240,
      minRatio: 0.8,
    }),
  );

This is going to output gzipped versions of our JS and CSS files, which means we can get an idea for how large the bundle size is actually going to be when it’s sent by our webserver.

Speaking of our webserver, we need to make a few minor changes there. Save this file, and open app.js. Below line 3, add the following:

const compression = require('compression');

And below line 46, add this code:

app.use(compression());

That’s all you have to do here, so save the file and let’s rock and roll. By which I mean: let’s take a look at bundle sizes. Head for a terminal window or command prompt. First off, if you fire up your dev server as normal, with

yarn start

and wait for the webpack output to run, then scroll up a bit, and you can see the file sizes. I get 4.59 MB for build.js and 194 KB for style.css. That’s … that’s unfortunate. Real unfortunate. Let’s see how the production build’s doing. ctrl-c out of your dev server and type:

yarn run build-prod

Let that do its thing, and then scroll up a bit. TAKE A LOOK AT THOSE NUMBERS! Even without compression, we’ve got build.js down to 1.09 MB, which is over a 400% reduction, and 149 KB for style.css, which is, well, a mild reduction anyway. But it’s the gzipped numbers that really stand out. style.css drops down to 20.5 KB, and build.js falls all the way to an astounding 263 KB. That’s a reduction of 1750%, which is fantastic. We’ve reduced our bundle size by more than 17 times, and brought it down to a number that’ll be pretty speedy even on a 3G connection.

So … awesome! I’m comfortable calling this production-ready. Obviously we’ll need to make sure our server is properly transmitting gzipped files, but that’s another tutorial.

Next up, we’re going to talk about locking our app down for production by running it through a vulnerability tester and then making the appropriate fixes. Catch you there!

« Previous Tutorial Next Tutorial »