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

Webpack Documentation:

webpack.github.io

 

Complete Starter Project:

git.io/preact-boilerplate

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,616