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?
- Official webpack site.
- Webpack how to
- A simple setup with webpack (run from gulp) that supports angular (from bower), with some common settings. Webpack + Angular + Bower + Gulp
- I would highly recommend watching Pete Hunt’s OSCON talk, which does a great job of explaining the why the Instagram team use webpack.
- A great selection of example
I’ve checked it. It looks really nice but everyone even those lazy ones should read the guide before use.
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.
Hey Vadim,
I’ll do my best to upload and open source the examples in the coming month as it’s a great idea.
didn’t work for me until I replaced
require(“./third.coffee”);
with
require(“coffee!./third.coffee”);
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: [ ... ]
}
}
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) 🙁
I think the benefit is in the fact that you can specify when resources should load.
Awesome. Just what I needed to get started with webpack. The official page should point a link here.
how to load multi static files under directory !
like for :- entry: ‘.folder/*.js’
awesome
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.
Never mind. Found the answer.
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\`
Thanks for that Sami!