Step-by-Step Webpack 2 Setup for Personal Projects

Webpack 2, es6, scss, uglification and sourcemaps

A few days ago I decided to put together a new side project. The first thing I did was put together a basic setup with Webpack 2 using es6, scss, and uglification with sourcemaps. There are definitely fancier things you can do, but this will get you going with the basics.

You can check out the finished product here: https://github.com/jonathan-potter/basic-webpack-2-setup

Get some Javascript running:

terminal

Here I just get a bunch of files ready to go.

mkdir basic-webpack-2-setup
cd basic-webpack-2-setup
git init
touch index.html
mkdir javascript
mkdir css
touch javascript/index.js
touch css/app.scss
touch package.json
touch webpack.config.js
touch .babelrc
echo node_modules > .gitignore

index.html

All we’re doing here is setting up a skeleton for an HTML page. We set the title and add a script tag pointing to the bundled javascript file we will be building.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Basic Webpack 2 Setup</title>
</head>
<body>
    <script src="build/bundle.js"></script>
</body>
</html>

package.json

This needs to be here for our npm packages. The interesting point here is the start script. The start entry in the scripts section means all we’ll need to do to start the server is call npm start in the terminal.

{
"name": "basic-webpack-2-setup",
"version": "0.0.1",
"description": "",
"scripts": {
"start": "webpack-dev-server"
},
"author": "your-name",
"license": ""
}

webpack.config.js

There is quite a bit going on here so i’ll just hit the high points. entry points to the top level javascript file we will be using. output sets where our bundled javascript file will be placed. Proper source-mapping is also set up.

const path = require('path')
module.exports = {
entry: './javascript/index',
output: {
path: __dirname,
filename: 'build/bundle.js',
sourceMapFilename: 'sourcemap'
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
css: path.resolve(__dirname, 'css'),
javascript: path.resolve(__dirname, 'javascript')
}
},
module: {},
devtool: '#inline-source-map',
plugins: []
}

javascript/index.js

At this point all we want to do is make sure our javascript is working. console.log will do fine for that purpose.

console.log("it's alive!")

Terminal

Install webpack and its dev server and start the server.

npm i webpack webpack-dev-server --save-dev
npm start

Open the browser to http://localhost:8080

You should see “it’s alive!” in the dev console (cmd-option-i for mac users).

our javascript is running!

Get some css (scss) working:

Awesome! Javascript is up and running so it’s time to get our styles in too.

css/app.scss

This is just enough to show that our scss is building correctly.

$reddish-color: #fcc;
body {
background: $reddish-color;
}

javascript/index.js

Add a css import to the javascript file.

import 'css/app.scss'
console.log("it's alive!")

index.html

Add a link tag to pull in our new css build file.

<!DOCTYPE html>
<html>
<head>
...
<link rel="stylesheet" href="build/style.css">
</head>
...
</html>

webpack.config.js

Add the ExtractTextPlugin and some loaders to make sure our css is built separately from our javascript.

const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = {
...,
module: {
rules: [
{
test: /\.css|.scss$/,
use: ExtractTextPlugin.extract({
loader: [
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } }
]
})
}
]
},
...,
plugins: [
new ExtractTextPlugin({
filename: 'build/style.css',
allChunks: true
})
]
}

terminal

Kill the server, install the required dependencies, and start the server up again.

# kill the server (ctrl-c)
npm install extract-text-webpack-plugin@beta --save-dev
npm install sass-loader node-sass css-loader --save-dev
npm start # start the server again

open browser to http://localhost:8080

Now you should see our nice reddish color in the background of the page.

The reddish color is showing up!

Next well uglify the code:

The last step I’ll cover is uglifing the code. The main benefits are reducing the size of our javascript file and making it harder for people to read our code.

webpack.config.js

Use the UglifyJsPlugin and add the babel-loader for javascript files.

...
const webpack = require('webpack')
...
module.exports = {
module: {
rules: [
{
test: /\.js$|.jsx$/,
exclude: /node_modules/,
use: 'babel-loader'
},
...
]
},
plugins: [
...,
new webpack.optimize.UglifyJsPlugin({
sourceMap: true
})
]
}

.babelrc

This just makes sure babel is doing all the things we may want it to do.

{
"presets": ["es2015", "stage-2"]
}

terminal

# kill the server (ctrl-c)
npm i babel-core babel-loader --save-dev
npm i babel-preset-es2015 babel-preset-stage-2 --save-dev
npm start

open browser to http://localhost:8080/build/bundle.js

If you open the built javascript file directly you’ll be able to see that it has been compacted.

bundle.js with minified code!

note: uglifying is not recommended while attempting to debug! It is easy to turn off: just comment out the plugin in webpack.config.js and restart the server.

Good luck

I hope this helps someone wade through the morass of docs and get up and running a bit faster. Let me know: https://twitter.com/PotterRawr :)