Unpacking Webpack - Part One

Posted in: Javascript

Dec 5, 2015

If you’ve been paying any sort of attention to front end developer for the past few years you’ll be well aware of module systems. Modern workflows will see developers now splitting their assets into logical modules to help keep code clean, organised and maintainable.

For Javascript we would write out our components into separate files, and then send them through a module bundler such as Browserify, which is what I use in many cases. The bundler will not just concatenate these (Browserify is much more elegant than that!) but rather bundle them together according to dependencies that you’ve specified, so files are only pulled in where and when they have to be, and have their variables exposed to only those dependent components that require them.  

This all sounds well and good but you’ll soon find you spend much of your time now trying to get these tools to actually bundle correctly, with a glut of configuration files, incompatible packages, and sparsely documented transforms you’ll be hair pulling in no time.

Webpack is another module bundler which has been gaining some traction lately, with the promise that it will alleviate some of these problems. Sounds good to me, so let’s dig in shall we?

Feature overview:

Perhaps the biggest bullet point next to Webpack’s name is its all-on-one solution. While module bundlers such as Browserify and Require will typically handle your Javascript, if you want to handle concatenation or compilation of pre-processed CSS or HTML, you’ll use yet another tool such as Gulp or Grunt. Webpack however can replace workflow tools such as Gulp as it will also handle these duties via its loaders library.

The way Webpack handles CSS is worth further consideration. With a simple require statement Webpack will consider the file size and if it’s small enough even inline those styles, which is ideal for those looking for critical path rendering.

Similiarly Webpack will do the same for images, that is, will base64 encode them if they are small enough.

Finally, Webpack isn’t as stringent as something like Browserify in what types of modules it will expect. CommonJS and AMD are both welcome here.

Installation and basic configuration

Ok, now to the good stuff. Webpack can be installed as a command line tool via NPM so can can simply enter into the terminal:

npm install webpack -g

Remember you may need to run this as sudo. Next, webpack expects a configuration file, which is where you set entry files, output directories and more. The file be called webpack.config.js

So create a project directory, I'm calling mine webpackdemo. CD into it and create the config file. 

mkdir webpackdemo
cd webpackdemo
touch webpack.config.js

At the minimum the config file will expect an input / entry file and output file:

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
};  

As you can see the config file follows the standard Node module style with an exports property on the module object. The entry property will contain your entry file, and the output will contain your output file. 

The output property object can also accept a path property to specify a different folder for the file.

{
    output: {
        path: path.join(_dirname, "js"),
        filename: "bundle.js"
    }
}

You can also set multiple entry points if you need multiple bundles. Pass in an object as the property for the entry option, and then to ensure that webpack writes to separate output files, prefix your output file name with [name]. [name] will be replaced with your entry object keys. 

entry: {
    public: "./public",
    admin: "./admin"
},
output: {
    filename: "[name].bundle.js"
}

There are of course many, many more options available to use, but today we're just interested in just the very basics. 

In our first code example we set a main.js file to be the entry file, so in the project directory, create that.

touch main.js

To exemplify webpack's bundling mechanism, I'm going to create two more Javascript files.

touch one.js
touch two.js

I'm going to use the CommonJS syntax here:

// two.js
module.exports = {
    hello : "Hello",
    world : "World!"
};
//one.js
var strings = require('./two);
module.exports = function(){
    alert(strings.hello + " " + strings.world);
};

And for main.js

var helloWorld = require('./one);
helloWorld();

With that complete, we can just run the webpack command in terminal.

webpack

That will produce our bundle.js file. To see if it worked, we can create a simple index.html file and add the script to the page.

touch index.html
//index.html
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Webpack Hello World Demo</title>
</head>
<body>
    <h1>Webpack Hello World Demo</h1>
    <script type="text/javascript" src="bundle.js"></script>
</body>
</html>

If all goes correctly you should have a simple Hello World alert dialog.

While the example here may seem contrived hopefully it is enough that you can see the bundling Javascript with webpack is pretty straight forward. In the next article we'll delve deeper into some of webpack's more advanced features that help make it stand out from the pack (see what I did there!)

Thanks for reading, and happy coding!