Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next Vue.js 2.0

kazupon
June 03, 2016

Next Vue.js 2.0

about vue.js 2.0 (2016-06-03)
at gotanda.js #4

kazupon

June 03, 2016
Tweet

More Decks by kazupon

Other Decks in Technology

Transcript

  1. OSS Contributions • Vue.js core team member • Vue.js official

    site for Japanese • Maintenance and Translate Vue.js official repositories
  2. 1.x rendering flow <template> <p>{{a.b}}</p> </template> <document-fragment> <p>{{a.b}}</p> </document-fragment> {

    a: { b: "hello" } } watcher a.b compile observe getter setter dep/observer a dep/observer b collect dependencies data template document fragment
  3. 1.x rendering flow <template> <p>{{a.b}}</p> </template> <document-fragment> <p>{{a.b}}</p> </document-fragment> {

    a: { b: "hello" } } watcher a.b compile observe render getter setter dep/observer a dep/observer b <html>… <body> <p>hello</p> </body> </html> collect dependencies append to target element data template document fragment target element
  4. 1.x rendering flow vm.a.b = 'world' { a: { b:

    "world" } } update dep/observer a getter setter dep/observer a dep/observer b
  5. 1.x rendering flow vm.a.b = 'world' { a: { b:

    "world" } } update notify dep/observer a watcher a.b getter setter dep/observer a dep/observer b batcher notify euqueue
  6. 1.x rendering flow vm.a.b = 'world' { a: { b:

    "world" } } update notify re- render dep/observer a <html>… <body> <p>world</p> </body> </html> watcher a.b getter setter dep/observer a dep/observer b batcher directive v-text="a.b" notify euqueue run callback update notify
  7. 2.0 rendering flow <template> <p>{{a.b}}</p> </template> {render:function(){with(this){ return _h(_e('p'),[(_s(a.b))])} }},

    staticRenderFns:[] } compile template render functions AST {type:1,tag:"p",attrsList:[], attrsMap:{},children:[{type: 2,expression:"_s(a.b)" }],plain:true} parse optimize & to function
  8. 2.0 rendering flow <template> <p>{{a.b}}</p> </template> {render:function(){with(this){ return _h(_e('p'),[(_s(a.b))])} }},

    staticRenderFns:[] } compile observe template render functions AST {type:1,tag:"p",attrsList:[], attrsMap:{},children:[{type: 2,expression:"_s(a.b)" }],plain:true} parse optimize & to function { a: { b: "hello" } } watcher ()=>{vm._update( vm._render())} getter setter dep/observer a dep/observer b collect dependencies data
  9. 2.0 rendering flow <template> <p>{{a.b}}</p> </template> {render:function(){with(this){ return _h(_e('p'),[(_s(a.b))])} }},

    staticRenderFns:[] } compile observe render template render functions AST {type:1,tag:"p",attrsList:[], attrsMap:{},children:[{type: 2,expression:"_s(a.b)" }],plain:true} parse optimize & to function { a: { b: "hello" } } watcher ()=>{vm._update( vm._render())} getter setter dep/observer a dep/observer b collect dependencies data patch <html>… <body> <p>hello</p> </body> </html> target element call exec vnode render _vnode = vnode text p
  10. 2.0 rendering flow update vm.a.b = 'world' { a: {

    b: "world" } } getter setter dep/observer a dep/observer b
  11. 2.0 rendering flow update patch watcher ()=>{vm._update( vm._render())} patch exec

    vnode vm.a.b = 'world' { a: { b: "world" } } getter setter dep/observer a dep/observer b notify render functions text p text p _vnode {render:function(){with(this){ return _h(_e('p'),[(_s(a.b))])} }}, staticRenderFns:[] } scheduler euqueue run callback
  12. 2.0 rendering flow update patch re- render <html>… <body> <p>world</p>

    </body> </html> target element set $el _vnode = vnode watcher ()=>{vm._update( vm._render())} patch exec vnode vm.a.b = 'world' { a: { b: "world" } } getter setter dep/observer a dep/observer b notify render functions text p text p _vnode {render:function(){with(this){ return _h(_e('p'),[(_s(a.b))])} }}, staticRenderFns:[] } scheduler euqueue run callback
  13. rendering performance • Improves initial rendering speed and memory consumption

    by up to 2~4x in most scenarios • benchmark
 Try to run the below URL
 https://github.com/vuejs/vue/tree/next/benchmarks
  14. support SSR • Without third vendor library, be able to

    server-side rendering • In server-side, render by using the blow the APIs • renderToString • renderToStream
  15. renderToString • Usage: with use compiler import Vue from '../../dist/vue.common.js'

    import { compileToFunctions } from '../../dist/compiler.js' import createRenderer from '../../dist/server-renderer.js' const { renderToString } = createRenderer() // define template compilation let compileTemplate = (options) => { const res = compileToFunctions(options.template, { preserveWhitespace: false }) Object.assign(options, res) console.assert(typeof options.render === 'function') delete options.template return options } // render console.log(renderToString(new Vue(compileTemplate({ template: '<div id="foo">{{ foo }} side {{ bar }}</div>' data: { foo: 'server', bar: 'rendering' } })))) // output: // <div id="foo" server-rendered="true">server side rendering</div>
  16. renderToString • Usage: with use ‘render’ option import Vue from

    '../../dist/vue.common.js' import createRenderer from '../../dist/server-renderer.js' const { renderToString } = createRenderer() // render console.log(renderToString(new Vue({ data: { foo: 'server', bar: 'rendering' }, render () { const h = this.$createElement return h('div', { attrs: { id: 'foo' } }, [`${this.foo} side ${this.bar}`]) } }))) // output: // <div id="foo" server-rendered="true">server side rendering</div>
  17. renderToString • component const child = Vue.extend(compileTemplate({ template: '<div class="bar">{{msg}}

    {{name}}</div>’, props: ['msg'], data () { return { name: 'bar' } } })) // render console.log(renderToString(new Vue(compileTemplate({ template: '<child class="foo" :msg="msg"></child>', data: { msg: 'hello' }, components: { child } })))) // output: // <div server-rendered="true" class="foo bar">hello bar</div>
  18. renderToString • hooks const child = Vue.extend(compileTemplate({ template: '<div class="bar">{{msg}}

    {{name}}: {{count}}</div>’, props: [‘msg'], data () { return { name: ‘bar’, count: 0 } }, init () { this.count++ }, created () { this.count++ } })) // render console.log(renderToString(new Vue(compileTemplate({ template: '<child class="foo" :msg="msg"></child>', data: { msg: 'hello' }, components: { child } })))) // output: // <div server-rendered="true" class="foo bar">hello bar: 2</div>
  19. renderToStream • renderToString issues • Sync rendering !! • Blocking

    the event loop !! • renderToStream support the async rendering • Improve the performance by using the Node.js Stream
  20. renderToStream • Usage: basic // … imports
 const { renderToStream

    } = createRenderer() // import!! // define template compilation let compileTemplate = (options) => { // ... } // render stream const stream = renderToStream(new Vue(compileTemplate({ template: '<div id="foo">{{ foo }} side {{ bar }}</div>' data: { foo: 'server', bar: 'rendering' } })))) let res = '' stream.on('data', chunk => { res += chunk }) stream.on('end', () => { console.log(res) // output: // <div id="foo" server-rendered="true">server side rendering</div> })
  21. renderToStream • Usage: Pipe const http from ‘http' // ...

    const server = http.createServer((req, res) => { // ...
 
 // render stream const stream = renderToStream(new Vue(compileTemplate({ template: '<div id="foo">{{ foo }} side {{ bar }}</div>' data: { foo: 'server', bar: 'rendering' } })))) 
 // pipe!! stream.pipe(res) }) server.listen(8000)
  22. hydration • When render at server-side, marke with ”server-rendered” to

    HTML • After that, In client-side, run the hydrate function at the patch • guard duplication rendering • skip the diffing, and DOM building
  23. It just works • No need the below from vue.js

    compiler to optimize the rendering • `shouldComponentUpdate` • Immutable data structures
  24. Optimization • Static attributes and classes skip the diffing in

    the patch template virtual-dom (vnode) { tag: "div", data: { staticClass: "image-box" }, children: [{ tag: "h1", children: [...], ... }, { tag: "a", data: { attrs: { href: url }, staticAttrs: { target: "_blank" } }, children: [{ tag: "img", data: { attrs: { src: resource, alt: hint }, staticClass: "image" } }, ... }], ... }], ... } <div class="image-box"> <h1>{{title}}</h1> <a :href="url" target="_blank"> <img :src="resource" class="image" :alt="hint"> </a> </div>
  25. • Static subtree skip the diffing in patch Optimization <div

    :class="class1"> <header>header</header> <p>{{a.b}}</p> <footer>footer</footer> </div> { render: function(){with(this){ return _h(_e('div', {class:class1}), [_m(0), _h(_e('p'), [(_s(a.b))]), _m(1)]) }}, staticRenderFns: [function(){with(this){ // _m(0) return _h(_e('header'), [_t("logo")])} }, function(){with(this){ // _m(1) return _h(_e('footer', [_t("foo")])} }] } template render functions compile When first rendering completed, results of staticRenderFns is cached in Vue instance. in later, use the this cached in the patch header div p footer text text text
  26. render tag / render option • Provide the feature that

    control of rendering with JavaScript • Cannot get no satisfaction to vue.js compiler • Cannot get no satisfaction to template DSL syntax • However, need to understand about the virtual-dom
  27. render tag • Example import Vue from 'vue' const vm

    = new Vue({ template: `<div><render :method="onRender" :args="message"></render></div>`, data: { message: 'hello world' }, methods: { onRender (args) { const h = this.$createElement return h('div', { class: 'message' }, [ h('p', {}, [args]) ]) } } }).$mount()
  28. render option • Example import Vue from 'vue' const vm

    = new Vue({ data: { message: 'hello world' }, render () { const h = this.$createElement return h('div', { class: 'message' }, [ h('p', {}, [this.message]) ]) } }).$mount()
  29. Re-implementaion • Re-design from zero-base, and full-scrach • Split the

    below files where to dist • compiler (dist/compiler.js) • runtime (dist/vue-common.js) • compiler + runtime (dist/vue.js) • server-render (dist/server-renderer.js)
  30. Remove the unneccessary codes • Build-in filters • Not used

    APIs and bad practice APIs • Unnecessary 1.x codes
  31. Comparing dist files • 1.x
 25.79K (min+zip) • 2.0 •

    runtime only: 12.81K (min+zip) • runtime + compiler: 19.09K (min+zip)
  32. Breaking changes • Some deprecated APIs
 ($dispatch, $broadcast, … etc)

    • Custom directive API I/F • Filter System • Transition System
 
 … and others
 see more detail the below URL https://github.com/vuejs/vue/issues/2873
  33. 2.0 • Current: pre-alphe • Achieved test coverage 100% •

    Alpha or beta: soon? • Release • Documentation • Major plugin compatiblity
 (vue-router, vuex, vue-loader, vuerify, … etc)
  34. Conclusion • Adopt virtual-dom • The below has become possible

    • Improve rendering performance • SSR • Rendering optimization • Control of rendering • More learner