Webpack
What it is and why you should care
What is Webpack?
- JavaScript build tool?
- CSS Build tool?
- Front-end build tool?
Really, bundle build tool.
Overview
Basic Concept
- Entry point is a JS file
- Finds & follows dependencies
- Wraps them similar to AMD
- Bundles into one or more files
function(require, exports, module) {
var dep1 = require('./dep1');
export.foo = dep1.whatever('yus');
module.exports = 'overwritten';
}
var dep1 = require('./dep1');
export.foo = dep1.whatever('yus');
module.exports = 'overwritten';
× 100
Non-JS Files
- Loaders transform files
- Generally produce JavaScript
- Specified via config or prefix
- Loaders can be chained
require('./style.css');
.foo {
color: red;
}
var d = document,
s = d.createElement('style');
s.appendChild(
d.createTextNode(
'.foo {\n color: red;\n}'
)
);
d.head.appendChild(s);
index.js
style.css
Chained Loaders
require('./style.less');
.foo {
.bar {
color: red;
}
}
var s = document.createElement('style');
s.appendChild(d.createTextNode(
'.foo .bar {\n color: red;\n}'
));
document.head.appendChild(s);
index.js
style.less
.foo .bar { color: red; }
Input
- CommonJS modules
- Files that require() files
- Arbitrary file types
Output
- Inline AMD-style modules
- Functions calling functions
- Converted JS*
* in the main bundle
Detour:
Hot Module
Replacement
From the Docs:
Hot Module Replacement (HMR)
exchanges, adds, or removes modules
while an application is running
without a page reload.
Live-reload
for modules
It's basically
Process
- Start webpack-dev-server
- Open in app browser
- Loads socket + injector
- Edit and save a file
- Changed modules pushed
- Modules get updated code
> webpack-dev-server
Accepting Updates
function init() {
var app = require('./app');
app.render(document.body);
}
// initial render:
init();
// if dev server & HMR enabled:
if (module.hot) {
// on update, re-init:
module.hot.accept('./app', init);
}
It's Automatic
For Stylesheets
Thanks, style-loader
Notes
- Diff-based UI works best
- React / Preact / etc
- Re-render from the root
- Even if grandchild changed
It's All
About
Plugins
Plugins & Loaders
make webpack great
babel-loader
ES2015 today
css-loader
CSS Modules
style-loader
HMR for CSS
url-loader
Data URIs
extract-text-plugin
bundle.js & bundle.css
file-loader
Static Assets
worker-loader
Worker chunks
Babel-Loader
- Transpiles ES2015+ to ES5
- Transpiles JSX to plain JS
- ES Modules ➞ CommonJS
- General transform pipeline
import h from 'vhtml';
/** @jsx h */
const UI = (
<ul class="things">
<li>One</li>
<li>Two</li>
</ul>
);
document.body.innerHTML = UI;
var h = require('vhtml');
var UI =
h( 'ul', {
'class': 'things'
},
h('li', null, 'One'),
h('li', null, 'Two')
);
document.body.innerHTML = UI;
File-Loader
- Imports linked assets
- Copied to output dir
- Templated output names
- Hashes for caching!
.foo {
background: url('cat.gif');
}
.foo {
background: url(
'cat.abc1234.gif'
);
}
build/cat.abc1234.gif
URL-Loader
- Inlines linked assets
- Uses Data URIs
- Supports max size
- Falls back to file-loader
.foo {
background: url('cat.gif');
}
.foo {
background: url(
'data:image/gif;base64,..'
);
}
extract-text-plugin
- Pulls CSS into separate bundle
- Can disable for development
- Use style-loader for HMR
@import url('./bar.css');
.foo {
background: url(cat.gif);
}
.foo {
background: url(cat.gif);
}
.bar {
color: red;
}
.bar {
color: red;
}
bar.css
bundle.css
Worker-Loader
- Load module in a Web Worker
- Bundles dependencies too
- import returns Worker instance
- postMessage in/out
import Burner from 'worker!./burner';
let burner = new Burner();
burner.onmessage = out => {
console.log(out);
};
burner.postMessage('burn');
onmessage = action => {
if (action==='burn') {
burn();
postMessage('done');
}
};
function burn() {
let s = Date.now();
while(Date.now()-s < 5000);
}
index.js
burner.js
Steep
Learning
Curve
20+ Modules
a Typical Project
Might Include
Boilerplates Abound
- Boilerplates are a hack
- Fragmentation after clone
- Nobody seems to care
- Expect solutions in 2016
For now, use a boilerplate.
Config
Your
Eh, Sean
"configuration"
import webpack from 'webpack';
module.exports = {
entry: './src/index.js',
output: {
path: './build',
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel'
},
// etc
]
},
plugins: [
new webpack.DefinePlugin({
DEBUG: true
}),
],
devtool: 'source-map'
};
webpack.config.babel.js
Initial module to load
Destination for bundle(s)
Match modules to loaders
String or Regex filters
Loader to apply to filtered modules
Plugins
(affect the whole build)
Configure source map type
devServer: {
port: process.env.PORT || 8080,
host: '0.0.0.0',
contentBase: './src',
historyApiFallback: true,
proxy: [
{
path: '/foo/**',
target: 'http://target.com'
}
]
}
webpack.config.babel.js
(webpack-dev-server section)
Address to listen on
Fall-through static dir
(for non-bundle requests)
Configure built-in http-proxy
(for upstreams, rewrites, CORS)
Serve index.html for all URLs
(for pushState routing)
Two Commands
Development:
Production:
webpack-dev-server --inline --hot
Use Websocket-based live-reload
Enable Hot Module Replacement
webpack -p
Minify, optimize & de-dupe
Starts in-memory dev web server.
Changes trigger fast partial rebuilds.
Builds to config.output.path
Perks
Perks
Perks
Webpack is popular
So Everything works with it
Integrations
Test Runners
- Karma
- Protractor
- Mocha*
*mocha doesn't really need it
Tooling
- Babel
- PostCSS
- UglifyJS
FE Tech
- Web Workers
- Service Worker
- Source Maps
What Webpack Isn't
Hint: Bash
Not generic
- A tool built for a purpose
- Limited to plugins & loaders
- Mainly configuration-driven
- Fits into generic pipeline
Solution
npm-scripts
... so just shell scripts
npm-scripts
- Orchestration
- pre/post-scripts
- Pipes, exit codes
{
"name": "my-great-module",
"scripts": {
"dev": "webpack-dev-server --inline --hot",
"prebuild": "mkdir -p build && cp -r src/assets build",
"build": "NODE_ENV=production webpack -p",
"prestart": "npm run build",
"start": "http-server build"
}
}
Usage:
npm run build
PORT=1337 npm run dev
Resources
Interested?
I'm working on removing
all that boilerplate.
Help me make this presentation an
implementation detail.
Quest
Jans
Webpack Overview
By developit
Webpack Overview
- 4,828