Diving into Webpack

Of late there has been a little bit of hype around this “webpack” thing. Hopefully this post gives you an overview of what it is, how to use it and if it’s worth all the hype.

First thing first. The official webpack docs are a little hard to digest so give it time.


What is it?

webpack is a module bundler

webpack takes modules with dependencies and generates static assets representing those modules.

As websites are evolving into web apps they are relying more and more on JavaScipt. This results in larger amounts of code on the client side. Generally speaking, utilising a module system should enhance not only the development but also the user experience.

If you happen to be working with a large codebase or just researching, you will no doubt understand it is critical to keep your code organised. One of the best ways to handle the organisation of JavaScript it to break your code into modules.

When it comes to module systems there are a few popular ones which you might of either used or heard about like Browserify or RequireJS. Both of these are extremely helpful and do a great job but webpack does some extra radness. Lets dig in!


Why webpack?

With webpack you can easily split your application into multiple files.

Your codebase can be split into multiple chunks and those chunks can be loaded on demand reducing the initial loading time of your application. It can also make your chunks cache friendly by using hashes. Which, to be honest is a little over my head in how it achieves this, but optimisation FTW!

It can build and bundle CSS, preprocessed CSS, compile-to-JS languages (like CoffeeScript), images and more by utilising webpack loaders. Kinda like gulp or grunt but “webpackified”.

Another great feature is webpack plugins. Webpack plugins have the ability to inject themselves into the build process to do all sorts of crazy stuff.

Enough of the features! Time to see it in action.


Webpack in action!

Install webpack through npm:

Note: you may have to use sudo for some of the following commands.


npm install webpack -g

Add a package.json file to the root of your projects directory with the following npm init command or copy and save the snippet below as your package.json.


{
  "name": "WebpackDemo",
  "author": "Web Design Weekly",
  "version": "0.0.1",
  "description": "The start of good things!",
  "private": true,
  "scripts": {},
  "dependencies": {},
  "devDependencies": {}
}

Now we want to add webpack to the newly created package.json file.


npm install webpack --save-dev

Now the webpack command is available via the CLI. You can find a detailed list of options on the official site or via webpack -h.

Some handy configuration options to remember

webpack – for building once for development
webpack -p – for building once for production (minification)
webpack --watch – for continuous incremental build
webpack -d – to include source maps
webpack --colors – for making things pretty


Next thing we want to do is create a webpack.config.js in the root of our projects directory to keep things organised.


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

Create a simple JavaScript file called main.js with the following contents:


document.write("Webpack for the win!");

Now by running the webpack command via the CLI you should have a bundle.js file “webpackified”! What happened is the webpack command found your webpack.config.js file and worked its magic.

To make sure all is working we can also create a simple index.html page with the following contents:


<html>
  <head>
    <script type="text/javascript" src="bundle.js"></script>
  </head>
  <body>
    <h1>Webpack Demo</h1>
  </body>
</html>

Multiple modules into one

So the above example is pretty trivial, but trust me. Webpack is super powerful as you will see in a minute. To ease into things a little more we will run through adding multiple modules to your final script.

Create a new file called second.js with the following contents:


module.exports = document.write("Oh yeah another file");

And make a reference to that file in your main.js like so:


require("./second.js");

Run the webpack command from the CLI and open up your bundle.js file. You should now see that both files are happily living together.

While you are at it you could also try running webpack -p. Now your bundle.js is minified.


Adding a loader to the mix

We touched on webpack loaders briefly above but it’s time to set one up!

There is a list of loaders on the webpack site if you are curious. For this demo we are going to set up the CoffeeScript loader.

Add the loader to your package.json like so:


npm install coffee-loader --save-dev

And this new section to your webpack.config.js

module: {
    loaders: [
        { test: /\.coffee$/, loader: "coffee-loader" }
    ]
}

To test the loader we will need to add a simple CoffeeScript file. Lets call it third.coffee and add the following contents:


alert "webpack is boss!"

require this in your main.js like so:


require("./third.coffee");

Run the webpack command on the CLI and you should now be seeing an alert.

Again, this is only scratching the surface of what loaders can do, but hopefully it gives you an understanding of setting them up.


Adding CSS and images

First we will need to add a couple more loaders to our package.json.


npm install style-loader css-loader url-loader --save-dev

Add the new modules to the loaders section in your webpack.config.js like so:


{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}

Note: the parameter in the url-loader is for inlining images if they are equal or under 8kb.

With these new loaders there are a few tweaks we have to do for webpack to do its magic.

Inside the webpack.config.js adjust the output parameter to look something like this:


output: {
    path: '\`${__dirname}/build\`, // This is where images AND js will go
    publicPath: 'http://yoururl.com/', // This is used to generate URLs
    filename: 'bundle.js'
}

We added the path and publicPath.

Note: If you have been following along you will also need to update your script reference in your HTML as your bundle.js is now in the build directory.

To test these new loaders work, lets add a new CoffeeScript file called image.coffee and require that (require("./image.coffee");) in the main.js.

Add the following to your image.coffee with the inclusion of two images (one under 8kb if you want to see inline base64 URL being built).


img1 = document.createElement("img")
img1.src = require("./your-small-image.png")
document.body.appendChild img1

img2 = document.createElement("img")
img2.src = require("./your-big-image.png")
document.body.appendChild img2

Also lets create a new CSS file called styles.css with the following contents:


body {
  background: tomato;
}

Require that (require("./styles.css");) in the main.js.

Re-run webpack from the command line and “ta-da”!

Welcome to webpack!


Wrapping things up

The above is a basic introduction into webpack. Hopefully you have gathered an understanding and can go forth and “webpackify”. Massive thanks to Pete Hunt for his awesome guide that helped me with this post.

If you are confused or stuck, be sure to download the above examples from GitHub which is complete.

Happy webpacking!


Keen to dive deeper?

15 thoughts on “Diving into Webpack”

  1. It would be fantastic if you’ve spare your priceless time and drop your working example on git hub. If that would have some steps in it than I can even predict how You’ll be appreciated.
    Thanks for the post. Very helpful.

    • Yes, and also
      require(“style!css!./styles.css”);
      and
      require(“url?mimetype=image/png!./your-small-image.png”)

      too bad I had to figure out myself before reading the comments…

    • I had the same issue, and that fix works, but it’s not using the automatic assignment of loaders. What I did wrong (and you could have had the same issue) was that I added the module: { loaders: [] } section in webpack.config.js as if “loaders” was another property of “module”.

      To fix it, and have loaders working correctly I had this in my config file:

      module.exports = {
      ...
      module: {
      loaders: [ ... ]
      }
      }

  2. I still can’t wrap my head around Webpack. It does look interesting but I don’t see how to use it yet. I mean I understand what it does and how the configuration works but I fail to see the benefit over something like a good Gulp build chain (e.g., take scripts, bundle them, minify them, etc) 🙁

  3. Awesome. Just what I needed to get started with webpack. The official page should point a link here.

  4. I’m getting this error:

    Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
    – configuration.output.path: The provided value “./build” is not an absolute path!

    Very new to this. Any help would be amazing.

  5. Just a note: Webpack has introduced a breaking change from the time since this tutorial was written. ./build will break things, as webpack wants an absolute path now. Instead, you can use __dirname + '/build', or as I prefer to see it written with template strings: \`${__dirname}/build\`

Comments are closed.