1 of 200

academy

2 of 200

Program Manager

Microsoft Web Platform, Developer Experience, Ecosystem

Maintainer & Advocate

Webpack

Core Team

Angular / angular-cli

Evangelist

Open Source Sustainability

3 of 200

Where most people think Nebraska is...

4 of 200

Background

Former Tech Support Rep. gone rogue turned Software Engineer / Web Developer who got tired of never being able to really help the customer he served.

Languages: Ruby, Objective-C, Swift, Javascript.

Other: Woodworker, 🐓 farmer, IoT

5 of 200

Sustainable Open Source Practices

JavaScript

Building Contributors, Community, and Ecosystem

6 of 200

@TheLarkInn

7 of 200

ASK ME ANYTHING

http://github.com/thelarkinn/ama

8 of 200

Expectations

Why webpack? - History of Web Performance & JavaScript

Getting Started - Setup, Installation, Scripts, and CLI

The Core Concepts

Starting out Right

The Essentials

Putting it to practice

Triage and Debug

9 of 200

Introductions

  • Name
  • Country
  • Company
  • FRONT-END FW YOU USE
  • #1 thing you want to walk away knowing by the end of this course

10 of 200

Chapter 1: Why?

11 of 200

Origins

12 of 200

JavaScript - It’s just scripts!

13 of 200

14 of 200

2 ways to load

15 of 200

16 of 200

17 of 200

Problems

18 of 200

Doesn’t Scale

19 of 200

Too many Scripts

20 of 200

Too Many Scripts

21 of 200

Unmaintainable Scripts

22 of 200

Scope

Size

Readability

Fragility

Monolith Files

23 of 200

solution?

24 of 200

IIFE’S

25 of 200

Immediately

Invoked

Function

Expression

26 of 200

Revealing Module pattern

27 of 200

28 of 200

Treat each file as IIFE (Revealing Module)

29 of 200

Many Similar Patterns

30 of 200

Concatenate!

We can “safely” combine files without concern of scope collision!*

31 of 200

Make, Grunt, Gulp, Broccoli, Brunch, StealJS

32 of 200

Full Rebuilds Everytime!

33 of 200

Dead Code

Concat doesn’t help tie usages across files

34 of 200

Lots of IIFE’s

Are slow

35 of 200

Dynamic loading?

36 of 200

Birth of JavaScript Modules

37 of 200

38 of 200

CommonJS

( Modules 1.0 )

39 of 200

40 of 200

Problems

41 of 200

Static Analysis

42 of 200

Npm+Node+Modules

Mass Distribution

43 of 200

Problems

44 of 200

No Browser Support

45 of 200

No Live Bindings

Problems with circular references

46 of 200

Sync Module Reso, Loader (slow)

47 of 200

NO BROWSER SUPPORT

48 of 200

solution?

49 of 200

Bundlers / Linkers

50 of 200

Browserify (static) RequireJS (loader) SystemJS (Loader)

51 of 200

Problems

52 of 200

CommonJS

//loading module

var _ = require(‘lodash’);

//declaring module

module.exports = someValue;

53 of 200

No static Async / Lazy Loading (all bundles up front)

54 of 200

CommonJS Bloat

Too Dynamic

55 of 200

Not everyone was shipping CommonJS.

56 of 200

AMD

define(‘myAwesomeLib’, [‘lodash’, ‘someDep’],

function (_, someDep) {

return { … }

}

);

57 of 200

AMD + CommonJS

define( function(require, exports, module) {

var _ = require(‘lodash’);

//..do things

module.exports = someLib;

});

58 of 200

Problems

59 of 200

Too Dynamic of Lazy Loading (MomentJS)

60 of 200

Awkward Non Standard Syntax (no real module system)

61 of 200

Solution?

62 of 200

ESM

import {uniq, forOf, bar} fromlodash-es

import * as utils fromutils’;

export const uniqConst = uniq([1,2,2,4]);

63 of 200

JavaScript Modules

Reusable

Encapsulated

Organized

Convenient

64 of 200

Problems

65 of 200

ESM for Node?

66 of 200

HOW DO THEY WORK IN THE BROWSER?

67 of 200

ESM for Browser is very very very slow

68 of 200

Every library is different...

Library authors use the module types that they like and choose

69 of 200

And this is just for JavaScript...

Each and every other filetype until now has had to have specific ways to process it.

70 of 200

Wouldn’t it be nice...

71 of 200

72 of 200

webpack is a module bundler

73 of 200

lets you write ANY module format (mixed!), compiles them for the browser

74 of 200

Supports Static Async Bundling

75 of 200

Rich, Vast, Ecosystem

The most performant way to ship JavaScript today

76 of 200

webpack - How to use it?

Config

(webpack.config.js) Yes, it’s a module too!!!

module.exports = {

entry: {

vendor: './src/vendors.ts',

main: './src/main.browser.ts'

},

output: {

path: 'dist/',

filename: '[name].bundle.js'

}

}

77 of 200

webpack - How to use it?

Webpack CLI

$> webpack <entry.js> <result.js> --colors --progress

$> webpack-dev-server --port=9000

78 of 200

webpack - How to use it?

Node API

var webpack = require("webpack");�� // returns a Compiler instance� webpack({� // configuration object here!� }, function(err, stats) {� // …

// compilerCallback

console.error(err);� });

79 of 200

Questions?

80 of 200

Break!

81 of 200

Chapter 2 - From Scratch

82 of 200

github.com/thelarkinn/webpack-workshop-2018

83 of 200

The Core Concepts

84 of 200

Entry

85 of 200

some.component.js

bootstrap.js

app.component.ts

external.lib.js

some.component.ts

external.lib.dep.js

external.lib.dep.css

some.component.sass

The first javascript file to load to “kick-off” your app.

webpack uses this as the starting point

The Core Concepts: Entry

ENTRY_FILE.js

86 of 200

app.js

ng2-material.lib.js

some.component.js

ng-core.class.js

browser.main.ts

app.component.ts

external.lib.js

some.component.ts

external.lib.dep.js

external.lib.dep.css

some.component.sass

The Core Concepts: Entry

//webpack.config.js

module.exports = {

entry: ‘./browser.main.ts’,

//...

}

//browser.main.ts

import {

Component

} from ‘@angular/core’;

import {

App

} from ‘./app.component’;

bootstrap(App,[]);

//app.component.ts

@Component({...})

export class App {};

87 of 200

app.js

ng2-material.lib.js

some.component.js

ng-core.class.js

browser.main.ts

app.component.ts

external.lib.js

some.component.ts

external.lib.dep.js

external.lib.dep.css

some.component.sass

The Core Concepts: Entry

//webpack.config.js

module.exports = {

entry: ‘./browser.main.ts’,

//...

}

//browser.main.ts

import {Component} from ‘@angular/core’;

import {App} from ‘./app.component’;

bootstrap(App,[]);

//app.component.ts

@Component({...})

export class App {};

88 of 200

The Core Concepts

Entry

Tells webpack WHAT (files) to load for the browser; Compliments the Output property.

89 of 200

Output

90 of 200

browser.main.ts

app.component.ts

external.lib.js

some.component.ts

external.lib.dep.js

external.lib.dep.css

some.component.sass

The Core Concepts: Output

//webpack.config.js

module.exports = {

entry: ‘./browser.main.ts’,

output: {

path: ‘./dist’,

filename: ‘./bundle.js’,

},

//...

}

//Generates bundle.js

./dist/

bundle.js

91 of 200

The Core Concepts

Entry

Output

Tells Webpack WHERE and HOW to distribute bundles (compilations). Works with Entry.

92 of 200

Loaders & Rules

93 of 200

module: {

rules: [

{test: /\.ts$/, use: ‘ts-loader’},

{test: /\.js$/, use: ‘babel-loader’},

{test: /\.css$/, use: ‘css-loader’}

],

}

app.component.ts

Tells webpack how to modify files before its added to dependency graph

Loaders are also javascript modules (functions) that takes the source file, and returns it in a [modified] state.

The Core Concepts: Loaders

entry.js

external.lib.js

external.es6.dep.js

external.lib.dep.css

94 of 200

module: {

rules: [

{

test: regex,

use: (Array|String|Function)

include: RegExp[],

exclude: RegExp[],

issuer: (RegExp|String)[],

enforce: “pre”|”post”

},

],

}

The Core Concepts: Loaders

test

A regular expression that instructs the compiler which files to run the loader against.

use

An array/string/function that returns loader objects.

enforce

Can be “pre” or “post”, tells webpack to run this rule before or after all other rules

95 of 200

module: {

rules: [

{

test: /\.ts$/,

use: [

‘awesome-typescript-loader’,

‘ng2-asset-loader`

],

include: /some_dir_name/,

exclude: [/\.(spec|e2e)\.ts$/],

},

],

}

The Core Concepts: Loaders

include

An array of regular expression that instruct the compiler which folders/files to include. Will only search paths provided with the include.

exclude

An array of regular expression that instructs the compiler which folders/files to ignore.

96 of 200

inlineStyleInBrowser.js

*.js

style.css

style.less

The Core Concepts: Loaders

Chaining Loaders

less-loader

css-loader

style-loader

rules: [

{

test: /\.less$/,

use:[’style-loader’,’css-loader’,’less-loader’]

}

]

97 of 200

The Core Concepts: Loaders

json, hson, raw, val, to-string, imports, exports, expose, script, apply, callback, ifdef-loader, source-map, sourceMappingURL, checksum, cowsay, dsv, glsl, glsl-template, render-placement, xml, svg-react, svg-url, svg-as-symbol, symbol, base64, ng-annotate, node, required, icons, markup-inline, block-loader, bundler-configuration, console, solc, .sol, web3, includes, combine, regexp-replace, file, url, extract, worker, shared-worker, serviceworker, bundle, require.ensure, promise, async-module, bundle, require.ensure, react-proxy, react-hot, image, file, url, img, base64-image, responsive, srcset, svgo, svg-sprite, symbol, svg-fill, fill, line-art, baggage, polymer, uglify, html-minify, vue, tojson, zip-it, file, lzstring, modernizr, s3, path-replace, react-intl, require.ensure, font-subset, w3c-manifest, web-app-manifest, manifest-scope, coffee, coffee-jsx, coffee-redux, json5, es6, esnext, babel, regenerator, livescript, sweetjs, traceur, ts, typescript, awesome-typescript, webpack-typescript, purs, oj, elm-webpack, miel, wisp, sibilant, ion, html, dom, riot, pug, jade-html, jade-react, virtual-jade, virtual-dom, template-html, handlebars, handlebars-template-loader, dust, ractive, jsx, react-templates, em, ejs, ejs-html, mustache, yaml, yml, react-markdown, front-matter, markdown, remarkable, markdown-it, markdownattrs, ng-cache, ngtemplate, hamlc, haml, jinja, nunjucks, soy, smarty, swagger, template-string, ect, tmodjs, layout, swig, twig, mjml-, bootstrap-webpack, font-awesome-webpack, bootstrap-sass, bootstrap, bootstrap, font-awesome, style, isomorphic-style, style-loader, css, cess, less, sass, stylus, csso, rework, postcss, autoprefixer, namespace-css, fontgen, classnames, theo, bulma, css-to-string, css-loader, po, po2mo, format-message, jsxlate, angular-gettext, json, angular-gettext, webpack-angular-translate, angular-gettext-extract, .pot, gettext, preprocessor, amdi18n-loader, .json, .js, .coffee, sprockets-preloader, properties, transifex, mocha, coverjs, istanbul-instrumenter, ibrik-instrumenter, eslint, jshint, jscs, standard, inject, transform, falafel, image-size, csslint, coffeelint, tslint, parker, sjsp, amdcheck, manifest, gulp-rev, html-test, stylelint, stylefmt, scsslint, htmlhint, documentation, sassdoc, performance-loader

98 of 200

99 of 200

The Core Concepts

Entry

Output

Loaders

Tells Webpack HOW to interpret and translate files. Transformed on a per-file basis before adding to the dependency graph

100 of 200

Plugins

101 of 200

The Core Concepts: Plugins

Objects (with an `apply` property)

Allow you to hook into the entire compilation lifecycle

webpack has a variety of built in plugins

102 of 200

function BellOnBundlerErrorPlugin () { }��BellOnBundlerErrorPlugin.prototype.apply = function(compiler) {� if (typeof(process) !== 'undefined') {�

// Compiler events that are emitted and handled

compiler.plugin('done', function(stats) {

if (stats.hasErrors()) {

process.stderr.write('\x07');

}

});�

compiler.plugin('failed', function(err) {

process.stderr.write('\x07');

});�

}�}��module.exports = BellOnBundlerErrorPlugin;

The Core Concepts: Plugins

Basic Plugin Example

A plugin is an ES5 ‘class’ which implements an apply function.

The compiler uses it to emit events.

103 of 200

The Core Concepts: Plugins

// require() from node_modules or webpack or local file

var BellOnBundlerErrorPlugin = require(‘bell-on-error’);

var webpack = require(‘webpack’);

module.exports = {

//...

plugins: [

new BellOnBundlerErrorPlugin(),

// Just a few of the built in plugins

new webpack.optimize.CommonsChunkPlugin(‘vendors’),

new webpack.optimize.UglifyJsPlugin()

]

//...

}

How to use Plugins

require() plugin from node_modules into config.

add new instance of plugin to plugins key in config object.

provide additional info for arguments

104 of 200

The Core Concepts: Plugins

80% of webpack is made up of its own plugin system

105 of 200

106 of 200

Web Performance

107 of 200

The Core Concepts

Entry

Output

Loaders

Plugins

Adds additional functionality to Compilations(optimized bundled modules). More powerful w/ more access to CompilerAPI. Does everything else you’d ever want to in webpack.

108 of 200

wat

109 of 200

Exercise Time

110 of 200

Chapter 3 - Starting Out Right

111 of 200

Academy

Instant Loading

https://github.com/thelarkinn/webpack-workshop-2018

112 of 200

Top 3 Web Page Load Time Causes:

Amount of JavaScript For Initial Download

Amount of CSS For Initial Download

AMount of Network Requests on Initial Download

113 of 200

Goals:

<=200kb (UNCOMPRESSED) Initial JavaScript [total]

<=100kb (UNCOMPRESSED) Initial CSS [total]

HTTP: <= 6 Initial Network Calls

HTTP/2: <= 20 Initial Network Calls

90% Code Coverage (only 10% code unused)

114 of 200

Code Splitting

115 of 200

Code Splitting

116 of 200

117 of 200

118 of 200

119 of 200

Code Splitting

Process of splitting pieces of your code into async chunks [at build time]

120 of 200

How Does it Work?

121 of 200

How...

122 of 200

Why should I care?

123 of 200

Why...

The future of web is mobile

The average mobile website takes 14 seconds to get interactive

load less code => interactive faster.

124 of 200

125 of 200

126 of 200

127 of 200

Two Types

128 of 200

Two Types

static

“dynamic”

129 of 200

Static

130 of 200

When to use:

“HEavy” JavaScript

Anything temporal

Routes

131 of 200

132 of 200

Always returns a Promise

133 of 200

app.js

listeners.js

modal.js

Async:

Sync:

134 of 200

app.js

listeners.js

modal.js

Async:

Sync:

135 of 200

app.js

listeners.js

modal.js

Async:

Sync:

bundle.js

0.chunk.js

136 of 200

“Dynamic”

137 of 200

138 of 200

Loading an async bundle based on runtime conditions

139 of 200

wat

140 of 200

Breakdown

141 of 200

expression

partial path

directory

resolvable

Context

Module

ContextModule!!!

142 of 200

0.chunk.js

1.chunk.js

2.chunk.js

3.chunk.js

4.chunk.js

“Hey webpack! Find me all modules in this partial path”

143 of 200

When to use:

AB Testing

Theming

Convenience

144 of 200

Exercise Time

145 of 200

NOte: Always focus on splitting before caching

146 of 200

Perf Scenarios

147 of 200

HTTP/2

148 of 200

Service Worker

149 of 200

Progressive Web Applications

150 of 200

Performance Hints

151 of 200

Building For Node?

152 of 200

Should you?

153 of 200

Building For Node?

154 of 200

Should you?

155 of 200

Building For Electron?

156 of 200

Should you?

157 of 200

Building For Libs?

158 of 200

Should you?

159 of 200

160 of 200

161 of 200

162 of 200

163 of 200

164 of 200

165 of 200

166 of 200

167 of 200

168 of 200

169 of 200

170 of 200

171 of 200

172 of 200

173 of 200

174 of 200

175 of 200

176 of 200

177 of 200

178 of 200

179 of 200

180 of 200

181 of 200

182 of 200

183 of 200

184 of 200

185 of 200

186 of 200

187 of 200

188 of 200

189 of 200

190 of 200

191 of 200

192 of 200

193 of 200

194 of 200

195 of 200

196 of 200

197 of 200

198 of 200

199 of 200

You just learned how webpack works entirely under the hood.

200 of 200

Chapter 6: Custom Plugins

Additional Resources: https://github.com/TheLarkInn/everything-is-a-plugin

Additional Workshop Video https://www.youtube.com/watch?v=4tQiJaFzuJ8