Introduction to webpack

by Andrey Okonetchnikov, @okonetchnikov

Introduction to webpack

Andrey Okonetchnikov
http://okonet.ru
@okonetchnikov

What is webpack?

Webpack is a module bundler

What is webpack?

  1. It’s like browserify, but better

Starting up


> npm install webpack
> webpack main.js bundle.js
		

... but better with config


// webpack.config.js
module.exports = {
	entry: './main.js',
	output: {
		filename: 'bundle.js'
	}
};
		

... now you can do

Require NPM modules


_ = require('lodash');
_.each([1,2,3], function(item){
	console.log(item);
});
		

Require bower modules


// webpack.config.js
var webpack = require('webpack');
module.exports = {
	...
	plugins: [
		new webpack.ResolverPlugin(
		  new webpack.ResolverPlugin.DirectoryDescription↵
		  FilePlugin("bower.json", ["main"])
		)
	]
};
		

Require all kinds of modules


// dependencies can be written in CommonJs
var commonjs = require("./commonjs");
// or in AMD
define(["amd-module", "../file"], function(amdModule, file) {
    // do stuff
});
// using variables
var template = require("jst!./templates/" + name + ".jst");
// using context API
require.context("..", true, /^grunt-[^\/]+\/tasks/[^\/]+$/)
// all grunt task that are in a modules directory of the parent folder

		

Smart modules resolving


module.exports = {
  resolve: {
    // you can now require('file') instead of require('file.coffee')
    extensions: ['', '.js', '.json', '.coffee'],

    // define where your modules will be resolved
    moduleDirectories: ['node_modules', 'bower_components'],

	// add aliases for commonly used modules
    alias: {
    	component: 'absolute/path/to/component'
  	}
  }
};
		

Using loaders for static assets


// Returns the image as base64
require('url!./image.png');

// Multiple loaders can be chained together
// CSS is loaded in as text
// Style loader injects it using style tag
require('style!css!./styles.css');

// Fixes broken module system for JS libraries
// require it in and assign it to a local variable
require('imports?foo=lib!lib.js');
		

Pre- and post-processing with loaders


// webpack.config.js
module.exports = {
  module: {
    loaders: [
	    { test: /\.coffee$/, loader: 'coffee-loader' },
	    { test: /\.yml$/, loader: 'yaml-loader' },
	    { test: /\.scss$/, loaders: [
          "style-loader",
          "css-loader",
          "autoprefixer-loader?browsers=last 2 version",
          "sass-loader?imagePath=~stylesheets/blocks&includePaths[]=./"
        ]
      }
    ]
  }
};
		

Pre- and post-processing with loaders


// now you can do...

// require *.scss files compiled to css using scss
// post-processed with autoprefixer
require('./styles/my-styles');

// require CoffeeScript compiled to JavaScript
require('./coffescripts/module');

// require yaml files compiled to JavaScript object
require('./ymls/my_yaml')
		

Async Loading & Code Splitting


require('./initial_module');
require.ensure([], function() {
	// A second file will be created automatically here
	require('./second_module');
});
		

Async Loading & Code Splitting

  1. Works with any kind of modules

Dependency injection


// webpack.config.js
var webpack = require("webpack");
module.exports = {
	plugins: [
		// plugin injects free variables into your code
		// without using global scope
		new webpack.DefinePlugin({
		    VERSION: JSON.stringify("5fa3b9"),
		    BROWSER_SUPPORTS_HTML5: true,
		    TWO: "1+1",
		    "typeof window": JSON.stringify("object")
		})
	]
};
		

Dependency injection


if(DEBUG)
    console.log('Debug info')
if(PRODUCTION)
    console.log('Production log')
		

if(false)
    console.log('Debug info')
if(true)
    console.log('Production log')
		

console.log('Production log')
		

Multi-compiler


// webpack.config.js
module.exports = [{
		name: "mobile",
		entry: "./example",
		output: "mobile.js",
		plugins: [
			new webpack.DefinePlugin({
				ENV: JSON.stringify("mobile")
			})
		]
	},
	{
		name: "desktop",
		entry: "./example",
		output: "desktop.js",
		plugins: [
			new webpack.DefinePlugin({
				ENV: JSON.stringify("desktop")
			})
		]
	}];
		

Multi-compiler


// in your code
$ = if (ENV === "desktop") {
	require('jquery');
} else {
	require('zepto');
}
		

Will produce 2 separate bundles with different dependencies...

Developer Tools

Hot Module Replacement

Hot Module Replacement (HMR) is a way of exchanging modules in a running application (and adding/removing modules). You basically can update changed modules without a full page reload.

http://webpack.github.io/docs/hot-module-replacement-with-webpack.html

Demo!

Webpack on GitHub

Some nice resources to start with

  1. http://webpack.github.io
  2. https://github.com/petehunt/webpack-howto

Thanks!

Andrey Okonetchnikov, @okonetchnikov