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

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

May 23, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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