build-time optimizations in frontend engineering · 2019-06-05 · build-time optimizations in...

50
Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Upload: others

Post on 23-May-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Build-time Optimizationsin Frontend Engineering

Evan YouJSConf China 2017

Page 2: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Frontend used to have no build steps...

Page 3: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

ModuleBuild Systems

CompilationInfrastructure

Compile-to-JSLanguages

CSS Processors

Today

Page 4: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Make Code Smaller

Page 5: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Minifiers: essentially Compilers

Page 6: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Source Code Target Codecompiler

Page 7: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Target Code

ParserAST

Codegen

Source Code

Page 8: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Target Code

ParserAST

Codegen

Source Code

Transforms!Analysis!

Optimizations!

Page 10: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Closure CompilerUglifyJS

BabiliButternut

Says it’s a compilerin its name Implements its own

parser / AST / codegen

Built on top of BabelSimilar architectureto Buble (a lightweight ES2015 compiler)

Page 11: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Early days: concat + minify

Page 12: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Early days: concat + minifyProblem: global scope sucks

Page 13: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Bundlers: let’s use modules

Page 14: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Bundlers: let’s use modulesProblem: modules make things harder to minify

Page 15: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

registerModules([ function (module, exports) { // module 1 }, function (module, exports) { // module 2 }, // ...])

Each module is wrapped inside a separate function scope

Page 16: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Rollup: use ES modules!

Page 17: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Module Scope Hoisting

main.js foo.js

bar.js

export function foo () { // ...}

export const bar = 123

import { foo } from './foo.js'import { bar } from './bar.js'

foo(bar)

Page 18: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

// foo.jsfunction foo () { // ...}

// bar.jsconst bar = 123

// main.jsfoo(bar)

Module Scope Hoisting

bundle.js

Page 19: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

// foo.jsfunction foo () { // ...}

// bar.jsconst bar = 123

// main.js// foo(bar)

Treeshaking

bundle.js

Page 20: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

// foo.jsfunction foo () { // ...}

// bar.jsconst bar = 123

// main.js// foo(bar)

Treeshaking

bundle.js

unused

unused

Page 21: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Treeshaking

bundle.js

// nothing left!

Page 22: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Treeshaking

Now also in webpack 3.x via webpack.optimize.ModuleConcatenationPlugin

Page 23: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

if (process.env.NODE_ENV !== 'production') { // code to drop in production build }

Conditional Block Trick

source.js

Page 24: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

if ('production' !== 'production') { // code to drop in production build }

Conditional Block Trick

source.js

Replaced during build

Page 25: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

if (false) { // unreachable }

Conditional Block Trick

source.js

Page 26: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

// nothing left!

Conditional Block Trick

source.js

Page 27: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Make Code Faster

Page 28: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

AOT vs. JITDo more at build time

Do less at runtime

Page 29: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Angular / Vue / GlimmerPre-compile templates to JavaScript

to avoid runtime compilation cost

Page 30: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

ReactOptimization via Babel plugins

https://github.com/thejameskyle/babel-react-optimize

Page 31: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

class MyComponent extends React.Component {

render() {

return (

<div className={this.props.className}>

<span>Hello World</span>

</div>

);

}

}

var _ref = <span>Hello World</span>;

class MyComponent extends React.Component {

render() {

return (

<div className={this.props.className}>

{_ref}

</div>

);

}

}

input output

Hoisting Static Elements

Page 32: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

SvelteCompile everything to vanilla JS with no runtime lib

Page 33: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

<h1>Hello {{name}}!</h1>

// only showing initial render code

h1 = createElement( 'h1' );

text = createText(

text_value = state.msg

);

insertNode( h1, target, anchor );

appendNode( text, h1 );

template

output

Initial Render

Page 34: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

// only showing update code

if (text_value !== (text_value =

state.msg)) {

text.data = text_value;

}

output

Updates

<h1>Hello {{name}}!</h1>

template

Page 36: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

graphql` fragment MyComponent on Type { field }`

GraphQL QueryRuntime Artifacts & Types

Getting rid of expensive runtime query construction via static build step

Page 37: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

PrepackOptimize performance via partial evaluation

Page 38: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

(function () {

function fib(x) {

return x <= 1

? x

: fib(x - 1) + fib(x - 2);

}

global.x = fib(23);

})();

(function () {

x = 28657;

})();

input output

Partial Evaluation(moving more computation to build time)

Page 39: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

RaktApplication-level optimizations via compilation

(proof of concept)

Page 40: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

Compile-time Optimizations in Vue

Page 41: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

<div>

<p class="foo">

this is static

</p>

</div>

function render() {

return this._renderStatic(0)

}

templateoutput

Hoisting Static Trees

Page 42: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

<div>

<p class="foo">

{{ msg }}

</p>

</div>

return h("div", [

h(

"p",

{ staticClass: "foo" },

[...]

)

])

templateoutput

Skipping Static Bindings

Page 43: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

<ul>

<li v-for="i in 10">

{{ i }}

</li>

</ul>

return h("ul", [

renderList(10, i => {

return h("li", i)

})

], 0) // ← optimization hint

templateoutput

Skipping Children Array Normalization

Page 44: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

SSR: optimizing Virtual DOMrender functions into string concat

<div>

<p class="foo">

{{ msg }}

</p>

<comp></comp>

</div>

function render() {

return h("div", [

this._ssrString(

"<p class=\"foo\">" +

this.msg +

"</p>"

),

h("comp") // mix w/ vdom

])

}

template

output

Page 45: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

SSR: inferring async chunks

main.js 0.js 1.js 1.js

Client Build

Manifest

Server Build

Manifest

Server Renderer

Serverbundle.js

Server build

Client build

Code-split Chunks

Page 46: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

SSR: inlining Critical CSS

Single File Vue Component

StyleInject via

Lifecycle hook

vue-server-renderer

InlinedCriticalCSS

vue-loadercompilation

Page 47: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017
Page 48: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

IDEA: compile away parts of Vue that’s not used in your app

Dead code elimination

AnalyzeUnused features Feature Flags

e.g.No

<transition> used

webpack + DefinePlugin

Template

Page 49: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

IDEA: Styletron-style Atomic CSS generation at build time

Page 50: Build-time Optimizations in Frontend Engineering · 2019-06-05 · Build-time Optimizations in Frontend Engineering Evan You JSConf China 2017

The build step affordsmany more possibilities!

We’ve only scratched the surface