Webpack – The Module Bundler



Webpack – The Module Bundler

1 8


webpack-experiment-slides

Slides for an experiment with Webpack, which is a step by step introduction with demo source code.

On Github alp82 / webpack-experiment-slides

Webpack

The Module Bundler

A presentation by Alper Ortac

@alperortac

#me

  • Frontend Developer @ Cisco
  • Fullstack Webdev Enthusiast

Webpack?

Yes, their logo is awesome.

Webpack!

It is

require/import sources (e.g. CommonJS, AMD)
convert and preprocess (e.g. minify, sass, babel)
create bundles that contain everything

It is not

a package manager
made for server-side

Our mission today

Now, we will build this search page step by step.

app.js

var template = '' +
'

Find. Anything.

' + '' + ' ' + ''; document.getElementById("app").innerHTML = template;

index.html

<html>
<head>
    <title>Find. Anything. - A Webpack Experiment</title>
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>
					

Where does bundle.js come from?

webpack.conf.js

module.exports = {
    entry: {
        app: "source/script/app.js"
    },

    output: {
        path: "dist",
        filename: "bundle.js"
    }
}
					

webpack [--color] [--watch]

Show me the demo already

Link: Step 1

Our First Bundle

Let's create a module and import it.

Modules & Imports

search.js

var template = "...";
module.exports = {
    template: template
};
					

app.js

var search = require("search.js");
// do something with search.template
					

Note: overloading require!

Everything is local, no IIFE

IIFE: Immediately-Invoked Function Expression

Link: Step 2

Our FirstModule Import

Nothing changed visually. Now for the real stuff.

Loaders

  • Webpack works with vanilla Javascript out of the box
  • Loaders extend that functionality
  • They are transformations applied on files

Let's enable Babel

$ _

npm install babel-loader
					

webpack.config.js

module: {
    loaders: [
        { test: /\.js$/, loader: 'babel' }
    ]
}
					

Now we can use ES6 style imports

//var search = require("search.js");
					
import search from "search.js";
					

Link: Step 3

Babel'ed

Let's see how we can improve templating and stylesheets.

Loaders can do alot more than transforming Javascript files

There is a loader for everything™

basic

  • json: Loads file as JSON
  • hson: Loads HanSON file (JSON for Humans) as JSON object
  • raw: Loads raw content of a file (as utf-8)
  • val: Executes code as module and consider exports as JavaScript code
  • to-string: Executes code as a module, casts output to a string and exports it
  • imports: Imports stuff to the module
  • exports: Exports stuff from the module
  • expose: Expose exports from a module to the global context
  • script: Executes a JavaScript file once in global context (like in script tag), requires are not parsed.
  • source-map: Extract sourceMappingURL comments from modules and offer it to webpack
  • checksum: Computes the checksum of a file
  • null: Emits an empty module.
  • cowsay: Emits a module with a cowsay header.
  • dsv: Loads csv/tsv files.
  • glsl: Loads glsl files and support glsl-chunks.
  • render-placement: Adds React.render to your component for you (not very practical in most cases)
  • xml: Loads XML as JSON.
  • svg-react: Load SVG files as JSX-ified React.createClass declarations.
  • base64: Loads file content as base64 string

packaging

  • file: Emits the file into the output folder and returns the (relative) url.
  • url: The url loader works like the file loader, but can return a Data Url if the file is smaller than a limit.
  • worker: The worker loader creates a WebWorker for the provided file. The bundling of dependencies of the Worker is transparent.
  • shared-worker: Like the worker loader, but for Shared Workers.
  • serviceworker: Like the worker loader, but designed for Service Workers.
  • bundle: Wraps request in a require.ensure block (callback)
  • promise: Wraps request in a require.ensure block (promise)
  • react-proxy: Code Splitting for react components.
  • react-hot: Allows to live-edit React components while keeping them mounted and preserving their state.
  • image: Compresses your images. Ideal to use together with file or url.
  • img: Load and compress images with imagemin.
  • svgo-loader: Compresses SVG images using svgo library
  • baggage: Automatically require any resources related to the required one
  • polymer-loader: Process HTML & CSS with preprocessor of choice and require() Web Components like first-class modules.
  • uglify-loader: Uglify contents of a module. Unlike uglify plugin you can minify with mangling only your application files and not the libraries
  • html-minify-loader: Minifies HTML using minimize
  • vue-loader: Load single-file Vue.js components as modules, with loader-support for preprocessors.
  • tojson-loader Serialize module exports as JSON. Cache generated static data as JSON at build time.
  • zip-it-loader Convert files and directories to zip. Great with file.

dialects

templating

  • html: Exports HTML as string, require references to static resources.
  • riot: Load RiotJS tags and convert them to javascript.
  • jade: Loads jade template and returns a function
  • jade-html: Loads jade template and returns generated HTML
  • template-html: Loads any template with consolidate.js and returns generated HTML
  • handlebars: Loads handlebars template and returns a function
  • dust: Loads dust template and returns a function
  • ractive: Pre-compiles Ractive templates for interactive DOM manipulation
  • jsx: Transform jsx code for React to js code.
  • react-templates: Loads react-template and returns a function
  • em: Compiles Emblem to Handlebars.js
  • ejs: Loads EJS (underscore( templating engine) template and returns a pre-compiled function
  • mustache: Pre-compiles Mustache templates with Hogan.js and returns a function
  • yaml: Converts YAML to JSON
  • markdown: Compiles Markdown to HTML
  • remarkable: Compiles Markdown to HTML using the Remarkable parser
  • markdown-it: Compiles Markdown to HTML using the markdown-it parser
  • ng-cache: Puts HTML partials in the Angular’s $templateCache
  • ngtemplate: Bundles your AngularJS templates and Pre-loads the template cache.
  • hamlc: Compiles haml-coffee templates (.hamlc) and returns a function.
  • haml: Renders haml-coffee templates (.html.hamlc) and returns a string.
  • jinja: Precompiles nunjucks and jinja2 templates
  • soy: Compiles Google Closure templates and returns the namespace with render functions
  • smarty: Pre-compiles php smarty templates and returns a function
  • template-string: Use ES6 template strings for html templates

styling

  • bootstrap-sass: Loads a configuration file for Twitter Bootstrap integration using Sass. Allows complete customization via Sass.
  • style: Add exports of a module as style to DOM
  • css: Loads css file with resolved imports and returns css code
  • less: Loads and compiles a less file
  • sass: Loads and compiles a scss file
  • stylus: Loads and compiles a stylus file
  • rework: Post-process CSS with Rework and returns CSS code
  • postcss: Post-process CSS with Autoprefixer and other PostCSS plugins
  • autoprefixer: Add vendor prefixes to CSS rules using values from Can I Use
  • namespace-css: Namespace your css with a given selector (for encapsulating all rules in one subset of your site)
  • fontgen: Create your own webfont with proper CSS on-the-fly and include it into WebPack.

translation

support

Loaders for HTML and CSS

Load file contents as string literal
npm install html-loader css-loader
					
Template function with variable replacement
npm install template-string-loader
					
Style injection in document
npm install style-loader
					

Loader Configuration

webpack.config.js

module: {
    loaders: [
        { test: /\.html/, loader: "babel!template-string" },
        { test: /\.css$/i, loader: "style!css?modules" }
    ]
}
					
  • Loaders can be chained with ! (read the chain from right to left)
  • ? indicates loader parameters (modules is for unique class names)

Unmodularized

index.html

<head>
	<link rel="stylesheet" href="style/app.css" />
	<link rel="stylesheet" href="style/search.css" />
</head>
					

search.css

.search {
	width: 100%;
	vertical-align: middle;
	white-space: nowrap;
	position: relative;
}

// ...
					

Modules & Templates

search.html


    
    	
	
    

search.js

import template from 'template/search.html';
import styles from 'style/search.css';

module.exports = {
    template: template({
        styles: styles
    })
};
					

Link: Step 4

Everything is in one Bundle

What about images? And fonts?

Url Loader

webpack.config.js

module: {
    loaders: [
        { test: /\.(png|jpe?g|gif)$/, loader: 'url-loader?limit=8192' }
    ]
}
					

app.js

import logo from 'image/logo.png';
					
What means limit=8192?

If file size is below, create an inlineBase64 string instead of copying the file

External Files

index.html

<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
					

app.css

@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,900);
					

Note: Webpack does not provide a wayto modularize externally hosted files

Ok, there is a trick, but it's not possible to use multiple domains.

Link: Step 5

Static Assets Inside

Let's include a Javascript library.

jQuery, because lazy

$ _

npm install jquery
					

webpack.config.js

module: {
    loaders: [
        { test: /\.js$/, loader: 'babel', exclude: 'node_modules') }
    ]
}
					

Exclude node_modules from Babel preprocessorto avoid longer build time and potential problems

Use it

search.js

import $ from 'jquery';

$(document).ready(function() {
	// do something
});
					

Easy.

Link: Step 6

We are done

Gifs fetched from Giphy API

Even More Webpack Features

  • Compress assets (minifying js/css, optimize images)
  • Inlining assets (style attributes, base64 images and fonts)
  • Splitting bundle into several Chunks (Async Loading)
  • Common Chunks and Dead Code Removal
  • Source Maps
  • Application Cache
  • Hot module replacement
  • Many more Plugins...

What about all the other tools?

Require.JS

  • Simple and Well Established
  • Bundling and Async Loading
  • Optimizer (combining, minifying, inlining)
  • Optimizer (Config, Performance)
  • No Static Assets
  • AMD format is outdated and can be quite messy

It's a classic, but lacks many features.

Browserify

  • Webpack-like and thought-of concepts
  • node.js compliant
  • Can be quite slow
  • No Static Assets
  • Inferior Bundle Splitting

Webpack overloads require, so if you want reusable server-side code use browserify

Besides, it's difficult to setup (at least in my experience)

JSPM

  • package registry with dependency management npm + github + custom (like bower)
  • modules and bundling
  • little support for preprocessors

Strong because ES6 compliant, but requires a partner tool for precompiling needs

Gulp

or Grunt

or Broccoli
or …
  • LOADS of plugins
  • Task runner (not a module loader per se)

Task runners are basically without restrictions, but all parts need to be glued together manually

Also possible: plain NPM

Webpack doesn't rely on Gulp but may profit from additional features

Is webpackthe holy grail?

The Good

  • Modules, Loaders, Bundles & Splits work very well
  • Many Plugins for special requirements
  • Plays along well with other tools (e.g. gulp, bower)
  • Nice Performance

The Bad

  • require is overloaded, can't be used for node.js code
  • External script loading is not supported (e.g. CDN)

Takeaway

Webpack is great, but it's not for everyone

This presentation

webpack-experiment-slides

Demo source code for all steps

webpack-experiment-demo

Inspirational Sources

The End

Thanks for your attention!

@alperortac

Join Squiek

The Community Of Communities

http://developer.squiek.com

http://launch.squiek.com

Webpack The Module Bundler A presentation by Alper Ortac @alperortac