Webpack for a better development workflow
Frontend United Ghent / #fuGent / @blakenewman
Front-end please stop!
Frameworks...
Task Runner tools...
Build tools...
All the things™...
Frontend United Ghent / #fuGent / @blakenewman
What’s currently available
One massive single file
Task Runners (Gulp/Grunt/Broccoli)
Module Bundlers (Require.js/Browserify/Webpack/JSPM)
Frontend United Ghent / #fuGent / @blakenewman
Is it good enough
Current tools have their own issues
JavaScript (ES6) Modules not yet standard
Library’s/Frameworks don’t always play nicely
Frontend United Ghent / #fuGent / @blakenewman
Why we need these tools
Frontend United Ghent / #fuGent / @blakenewman
Imperative JavaScript
Declarative CSS
HTML
Modularisation is important
Frontend United Ghent / #fuGent / @blakenewman
Maintainability is important
Frontend United Ghent / #fuGent / @blakenewman
Performance is important
Frontend United Ghent / #fuGent / @blakenewman
Scalability is important
Frontend United Ghent / #fuGent / @blakenewman
https://addyosmani.com/scalablejs/
LIFT
Locate
Identify
Flat
T-DRY (Try to Stick to DRY)
Frontend United Ghent / #fuGent / @blakenewman
Introduction to Webpack
What is Webpack?
Task Runner (ish)
Module/Asset Bundler
Asset Transformation
Frontend United Ghent / #fuGent / @blakenewman
Key features
Modules to bundles
Compress assets
Inline assets
Code splitting (Async Loading)
Dead Code Removal
Source Maps
Application Cache
Hot module replacement
…
Frontend United Ghent / #fuGent / @blakenewman
Comparing Webpack
Frontend United Ghent / #fuGent / @blakenewman
Grunt/Gulp/Broccoli ...
Lots of plugins
Task runner (not a module loader per se)
Glue together manually
Can become unmaintainable
Frontend United Ghent / #fuGent / @blakenewman
http://blog.keithcirkel.co.uk/why-we-should-stop-using-grunt/
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
Frontend United Ghent / #fuGent / @blakenewman
Browserify
Webpack-like and similar concepts
Simple configuration
Can be quite slow
No Static Assets
Inferior Bundle Splitting
Limited in flexibility
Frontend United Ghent / #fuGent / @blakenewman
JSPM
Package registry with dependency management
ES6 Compliant
Immature
Little support for preprocessors
Requires partner tool for precompilation
Frontend United Ghent / #fuGent / @blakenewman
Webpack
Modules, Loaders, Bundles & Splits
Many Plugins for special requirements
Plays nicely with other tools
Performance
Extremely flexible
Docs are a bit messy
Frontend United Ghent / #fuGent / @blakenewman
How it works
Frontend United Ghent / #fuGent / @blakenewman
Bundling and entries
Consistency with deployment environments
Clear bundling strategies
Common bundles
Multiple entry points for Multi Page applications
Brilliant for Single Page Applications
Frontend United Ghent / #fuGent / @blakenewman
Outputs
Output versioning
Content hashing
Output names flexible to deployment strategies
bundle.sd2dds34.js
bundle.js?sd2dds34
Frontend United Ghent / #fuGent / @blakenewman
Loaders
Webpack works with vanilla Javascript
Loaders extend that functionality
They are transformations applied on files
Frontend United Ghent / #fuGent / @blakenewman
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.
apply: Executes a exported JavaScript function, optionally with arguments, and exports its return value.
callback: Parses your JS, calls specified functions (which you implement in webpack context) and replaces them with the results
if-loader: This is a preprocesser for the webpack module bundler. It support the if directive,similar to C #ifdef .
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
ng-annotate: A loader to annotate dependency injections in Angular.js applications.
node: Loads .node files that are produced using node-gyp.
required: Require a whole directory of trees in bulk. Require JS, Import CSS and imports stuff in it.
icons Generates iconfont from .svg files (uses gulp-iconfont)
block-loader Generic loader for rewriting only parts of files, based on content start/end delimiters.
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)
async-module: Same as bundle, but provides a way to handle script loading errors. Wraps request in a require.ensure block (callback, errback)
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.
responsive: Create multiple resized images for use with srcset and CSS media queries
svgo: Compresses SVG images using svgo library
svg-sprite: Like style-loader but for SVG: it creates a single SVG sprite from a set of images, appends it to DOM and returns relative symbol url to be used with svg’s <use>.
line-art: Inlines SVG files, converting all of its nodes to paths. Useful for line art animations in React components.
baggage: Automatically require any resources related to the required one
polymer: Process HTML & CSS with preprocessor of choice and require() Web Components like first-class modules.
uglify: Uglify contents of a module. Unlike uglify plugin you can minify with mangling only your application files and not the libraries
html-minify: Minifies HTML using minimize
vue: Load single-file Vue.js components as modules, with loader-support for preprocessors.
tojson Serialize module exports as JSON. Cache generated static data as JSON at build time.
zip-it Convert files and directories to zip. Great with file.
lzstring Compresses large strings inline using lz-string, and decompresses them at runtime
modernizr Get your modernizr build bundled with webpack
coffee: Loads coffee-script like JavaScript
coffee-jsx: Loads coffee-script with JSX like JavaScript
coffee-redux: Loads coffee-script like JavaScript
json5: Like json, but not so strict.
es6: Loads ES6 modules. (old)
esnext: Transpile ES6 code using esnext.
babel: Turn ES6 code into vanilla ES5 using Babel.
regenerator: Use ES6 generators via Facebook’s Regenerator module.
livescript: Loads LiveScript like JavaScript
sweetjs: Use sweetjs macros.
traceur: Use future JavaScript features with Traceur.
ts: Loads TypeScript like JavaScript.
typescript: Loads TypeScript like JavaScript.
awesome-typescript: Loads TypeScript like JavaScript with watching support. Works with TypeScript 1.5-alfa
webpack-typescript: Loads TypeScript like JavaScript. Supports watch mode and source maps. Works with TypeScript 1.5, 1.6, and nightly builds of TypeScript 1.7 and 1.8.
purs: Loads PureScript like JavaScript.
oj: Loads OJ (an Objective-C like language) files and compiles them to plain JavaScript.
elm-webpack: Loads Elm files and compiles them to plain JavaScript.
miel: Loads Miel syntax and compiles to JavaScript.
wisp: Loads Wisp modules and compiles them to JavaScript.
sibilant: Loads Sibilant files and compiles them to JavaScript.
html: Exports HTML as string, require references to static resources.
dom: Exports HTML in a DOM element container.
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
jade-react: Uses jade templates for React rendering instead of JSX
template-html: Loads any template with consolidate.js and returns generated HTML
handlebars: Loads handlebars template and returns a function
handlebars-template-loader: Loads handlebars template and returns a function (alternative)
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
front-matter: Extracts YAML frontmatter
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
nunjucks: Precompiles nunjucks 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
tmodjs: Load art-template , a template-engine that is widely used in China.
layout: You can use require directly in html now!
swig: Webpack Swig loader
twig: Webpack Twig.js loader
bootstrap-webpack: Loads a configuration file for Twitter Bootstrap integration using Less. Allows complete customisation via Less.
font-awesome-webpack: Loads a configuration file for Font Awesome integration using Less. Allows complete customisation via Less.
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.
classnames: Automatically bind css-modules to classnames.
modernizr: Get your modernizr build bundled with webpack
po: Loads a PO gettext file and returns JSON
format-message: Compiles translations to ICU Message Format strings in formatMessage calls
jsxlate: Transform React source code for use with jsxlate
angular-gettext Compiles .po files as Angular.js module or json to be used with angular-gettext.
webpack-angular-translate: Extracts angular-translate translation id’s and default text’s
angular-gettext-extract Extracts strings for translation into a nominated .pot file.
gettext: Compiles a Gettext PO file from code source.
preprocessor: The preprocessor-loader provides the ability to preprocess source files through user defined regular expressions, macros, and callback routines. All user defined logic can be applied to line scope or source scope.
mocha: do tests with mocha in browser or node.js
coverjs: PostLoader to code coverage with CoverJs
istanbul-instrumenter: Istanbul postLoader to code coverage with karma-webpack and karma-coverage
isparta-instrumenter: Isparta preLoader to code coverage with karma-webpack and douglasduteil/karma-coverage#next
ibrik-instrumenter: Ibrik preLoader to CoffeeScript code coverage with karma-webpack and douglasduteil/karma-coverage
eslint: PreLoader for linting code using ESLint.
jshint: PreLoader for linting code.
jscs: PreLoader for style checking.
standard: Conform to standard code style.
inject: A Webpack loader for injecting code into modules via their dependencies
injectable: Allow to inject dependencies into modules
transform: Use browserify transforms as loader.
falafel: Use falafel AST transforms as a loader.
image-size: Loads an image and returns its dimensions and type
csslint: PreLoader for linting code using CSSLint
coffeelint: PreLoader for linting CoffeeScript.
tslint: PreLoader for linting TypeScript using TSLint
parker: Output a stylesheet analysis report using parker.
sjsp: Inject some codes for profiling using node-sjsp.
amdcheck: Uses AST to find and remove unused dependencies in AMD modules using amdextract.
manifest: A loader to generate JSON asset manifests to pass to preloading systems.
gulp-rev: Use in tandem with gulp-rev to replace assets from rev-manifest.
html-test Test your html templates (for example) for analytics.
stylelint Preloader for linting SASS and SCSS with stylelint
Plugins
Frontend United Ghent / #fuGent / @blakenewman
Code splitting
Initialisation performance
Designate entry points
Asynchronous code
Fixes: “Monolithic bundle” and “Unmaintainable manual imports”
Frontend United Ghent / #fuGent / @blakenewman
require.ensure([ './basket.vue' ], (require) => {
require([ './basket.vue' ], resolve);
}, 'basket');
HMR (Hot Module Replacement)
Webpack tracks the modules dependency tree, which enables:
Patch part of dependency tree with the new code
Changes appear live without page reloading
Frontend United Ghent / #fuGent / @blakenewman
Compiler
HMR Server
Bundle Server
Compile
Change
code
HMR runtime
bundle
Putting it all together
Frontend United Ghent / #fuGent / @blakenewman
Base config
Frontend United Ghent / #fuGent / @blakenewman
const path = require('path');
const ROOT_PATH = path.resolve(__dirname, '../');
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: `${ROOT_PATH}/dist`,
publicPath: '/',
filename: '[name].js'
},
module: {
loaders: [
/* ... */
]
}
}
Adding loaders to base config
Frontend United Ghent / #fuGent / @blakenewman
const path = require('path');
const ROOT_PATH = path.resolve(__dirname, '../');
module.exports = {
/* ... */
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url',
query: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
}
]
}
};
Extending base config
Frontend United Ghent / #fuGent / @blakenewman
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
/* ... */
});
Creating dev config
Frontend United Ghent / #fuGent / @blakenewman
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.conf');
const webpack = require('webpack');
module.exports = merge(baseConfig, {
debug: true,
devtool: '#eval-source-map',
devServer: {
historyApiFallback: true,
noInfo: true
}
});
Creating production config
Frontend United Ghent / #fuGent / @blakenewman
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
devtool: '#source-map',
output: {
filename: 'js/[name].[chunkhash].js',
chunkFilename: 'js/[name].[chunkhash].js'
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.optimize.OccurenceOrderPlugin()
]
};
Example package.json scripts
Frontend United Ghent / #fuGent / @blakenewman
{
...
"scripts": {
"dev": "webpack-dev-server --inline --hot --config ./build/webpack.dev.config.js",
"build": "webpack --progress --hide-modules --config ./build/webpack.prod.config.js"
},
...
}
express and webpack-dev-middleware
Custom implementations
Assets in-memory
Proxy tables
Static asset hosting
Actionable events
Flexible
Frontend United Ghent / #fuGent / @blakenewman
Hot module replacement in action
Frontend United Ghent / #fuGent / @blakenewman
Too much?
Frontend United Ghent / #fuGent / @blakenewman
Thanks
Frontend United Ghent / #fuGent / @blakenewman
Webpack for a better development workflow
By Blake Newman
Webpack for a better development workflow
Front-end United Ghent 2016
- 5,742