Webpack
This article is part of my personal wiki where I write personal notes while I am learning new technologies. You are welcome to use it for your own learning!
The Case for Webpack
Modern JavaScript projects aren’t what they used to be. In order to have an awesome development environment and produce world class applications you need a front-end build pipeline that helps you with all these goodness:
- bundling
- minification
- transpilation
- dependency management and module loading
- linting
- other optimizations (tree shaking, remove unused css, etc)
- framework specific improvements
Webpack offers a solution to all these needs! Behold!
Webpack Basics
The easiest way to get started with webpack is by using the cli. You can install webpack using npm:
$ npm i -g webpack
You can use webpack directly on a bunch of javascript files and package them together in a bundle:
$ webpack app/main.js bundle.js
Or you can use a configuration which is far more common in real world projects. We usually name the configuration webpack.config.js
:
module.exports = {
entry: 'app/main.js', // it can also be an array
output: {
filename: 'bundle.js'
}
};
As you can appreciate from the example above, a webpack configuration file is just a vanilla commonJS module. This configuration is the equivalent to webpack app/**/*.js bundle.js
. In order to run webpack with a configuration file you just type:
$ webpack
Just like other common task runners, webpack has a watch mode. This means that you can tell webpack to watch a series of files for changes and run again every time one of these files changes. You can enable watch mode like this:
module.exports = {
entry: 'app/main.js', // it can also be an array
output: {
filename: 'bundle.js'
},
watch: true
};
$ webpack --watch app/**/*.js bundle.js
A cool thing that differences webpack from other task runners is that webpack includes a web server called dev server. It is distributed as a separate npm package called webpack-dev-server
. Again you can install it globally via npm
:
$ npm i -g webpack-dev-server
You can use it in a similar way than the webpack
cli:
# show status bar
$ webpack-dev-server
# don't show status bar
$ webpack-dev-server --inline
This will start an http server and serve your webpack packaged application.
Power Up Webpack with Loaders
You can add more functionality to your webpack pipeline through loaders. For instance, you can have a loader to transpile your SASS style sheets, or to transpile your ES6 code or to lint your code. Loaders are distributed as npm packages, you can install them like thisÖ
$ npm i --save-dev babel-loader babel-core eslint-loader eslint webpack
And add them to your webpack configuration
module.exports = {
entry: 'app/main.js', // it can also be an array
output: {
filename: 'bundle.js'
},
watch: true,
module: {
// pre-loaders run before loaders
preLoaders: [
{
test: /\.js$/, // files to process (all js files are es6 files)
loader: "eslint-loader", // loader
exclude: /node_modules/ // files to exclude
}
],
// loaders
loaders: [
{
test: /\.js$/, // files to process (all js files are es6 files)
loader: 'babel-loader' // loader to use
exclude: /node_modules/, // files to exclude
}
]
},
resolve: {
extensions: ['', '.js'] // valid extensions in modules
}
};
Improve the Dev Experience of Running Webpack with npm scripts
Running webpack-dev-server
can get tedious, particularly when you start adding parameters to it. A useful thing to do is to take advantage of npm scripts to launch webpack. For instance:
{
"name": "barbarian-meets-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"run": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.14.0",
"eslint": "^3.5.0",
"eslint-loader": "^1.5.0",
"webpack": "^1.13.2"
}
}
Now you can write npm run
and npm will kick off your webpack dev server.
Create Environment Specific Webpack Configurations
You can create multiple webpack config files for different environments. For instance create a new file webpack.prod.config.js
and extend your dev configuration:
var devConfig = require('webpack.config');
var StripLoader = require('strip-loader');
/* prod configuration */
devConfig.loaders.push({
test: [/\.js$/],
exclude : /node_modules/,
loader: StripLoader.loader('console.log') // remove logging
};
module.exports = devConfig;
To run this configuration you specify it as a parameter to webpack:
$ webpack --config webpack.prod.config.js
You can minify your code by calling webpack -p
, to use the production configuration plus minification you can create an npm script that executes webpack -p --config webpack.prod.config.js
.
More Advanced Configurations
With a folder structure like this:
---- app: source es6 files
| |--- main.js, etc
|
|-- wwwroot: website public root
| |--- index.html
| |--- app/.... public path for built files
|
|-- build: build files
We can use the following configuration with context
, output.path
, output.publickPath
and devServer.wwwroot
:
var path = require('path');
module.exports = {
context: path.resolve('app'), // context where files to transform are located
entry: ['./main'], // could be an array of files
output: {
path: path.resolve('build/app/'), // build path (during development)
publicPath: 'app/', // public build path (how it will be requested by the browser in production)
filename: 'bundle.js'
},
devServer: {
contentBase: 'wwwroot' // content base for dev server
},
watch: true,
module: {
// pre-loaders run before loaders
preLoaders: [
{
test: /\.js$/, // files to process (all js files are es6 files)
loader: "eslint-loader", // loader
exclude: /node_modules/ // files to exclude
}
],
loaders: [
{
test: /\.js$/, // files to process (all js files are es6 files)
exclude: /node_modules/, // files to exclude
loader: 'babel-loader' // loader to use
}
]
},
resolve: {
extensions: ['', '.js'] // valid extensions in modules
}
}
Generate Source Maps
Using the -d
option will automatically generate source maps:
$ webpack -d
$ webpack-dev-server -d
You can also combine it with minification
$ webpack -d -p
$ webpack-dev-server -d -p
Multiple Bundles
TODO/REVIEW
References
Written by Jaime González García , dad, husband, software engineer, ux designer, amateur pixel artist, tinkerer and master of the arcane arts. You can also find him on Twitter jabbering about random stuff.