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]
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
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";
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
})
};
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.
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.
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?
- 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.
- 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)
-
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
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
Join Squiek
The Community Of Communities
Webpack
The Module Bundler
A presentation by Alper Ortac
@alperortac