$30 off During Our Annual Pro Sale. View Details »

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. Next Vue.js 2.0
    Gotanda.js #4
    2016-06-03
    @kazupon

    View Slide

  2. Who?
    • GitHub: kazupon
    • Twitter: kazu_pon
    • Company: CUUSOO SYSTEM
    • Position: CTO (Full-Stack)

    View Slide

  3. OSS Contributions
    • Vue.js core team member
    • Vue.js official site for Japanese
    • Maintenance and Translate Vue.js
    official repositories

    View Slide

  4. Introduction
    • 2016 Apl 27 Announce Vue.js 2.0

    https://medium.com/the-vue-point/announcing-vue-js-2-0-8af1bde7ab9#.7acpkrkhh

    View Slide

  5. To Speak Today
    • Today, I speak about the Vue.js 2.0

    View Slide

  6. 2.0 Architecture

    View Slide

  7. Adopt virtual-dom
    • snabbdom based

    https://github.com/paldepind/snabbdom
    • Customize for Vue.js

    (component, directive, hydration)

    View Slide

  8. 1.x rendering flow

    {{a.b}}


    {{a.b}}

    compile
    template
    document fragment

    View Slide

  9. 1.x rendering flow

    {{a.b}}


    {{a.b}}

    { a: { b: "hello" } }
    watcher
    a.b
    compile observe
    getter
    setter
    dep/observer
    a
    dep/observer
    b
    collect
    dependencies
    data
    template
    document fragment

    View Slide

  10. 1.x rendering flow

    {{a.b}}


    {{a.b}}

    { a: { b: "hello" } }
    watcher
    a.b
    compile observe render
    getter
    setter
    dep/observer
    a
    dep/observer
    b


    hello


    collect
    dependencies
    append to target element
    data
    template
    document fragment
    target element

    View Slide

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

    View Slide

  12. 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

    View Slide

  13. 1.x rendering flow
    vm.a.b = 'world'
    { a: { b: "world" } }
    update notify
    re-
    render
    dep/observer
    a


    world


    watcher
    a.b
    getter
    setter
    dep/observer
    a
    dep/observer
    b
    batcher
    directive
    v-text="a.b"
    notify
    euqueue
    run
    callback update
    notify

    View Slide

  14. 2.0 rendering flow

    {{a.b}}

    {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

    View Slide

  15. 2.0 rendering flow

    {{a.b}}

    {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

    View Slide

  16. 2.0 rendering flow

    {{a.b}}

    {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


    hello


    target element
    call
    exec
    vnode render
    _vnode = vnode
    text
    p

    View Slide

  17. 2.0 rendering flow
    update
    vm.a.b = 'world'
    { a: { b: "world" } }
    getter
    setter
    dep/observer
    a
    dep/observer
    b

    View Slide

  18. 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

    View Slide

  19. 2.0 rendering flow
    update patch
    re-
    render


    world


    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

    View Slide

  20. 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

    View Slide

  21. Support
    Server-Side-Rendering

    View Slide

  22. support SSR
    • Without third vendor library, be able to
    server-side rendering
    • In server-side, render by using the blow
    the APIs
    • renderToString
    • renderToStream

    View Slide

  23. 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: '{{ foo }} side {{ bar }}'
    data: { foo: 'server', bar: 'rendering' }
    }))))
    // output:
    // server side rendering

    View Slide

  24. 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:
    // server side rendering

    View Slide

  25. renderToString
    • component
    const child = Vue.extend(compileTemplate({
    template: '{{msg}} {{name}}’,
    props: ['msg'],
    data () {
    return { name: 'bar' }
    }
    }))
    // render
    console.log(renderToString(new Vue(compileTemplate({
    template: '',
    data: { msg: 'hello' },
    components: { child }
    }))))
    // output:
    // hello bar

    View Slide

  26. renderToString
    • hooks
    const child = Vue.extend(compileTemplate({
    template: '{{msg}} {{name}}: {{count}}’,
    props: [‘msg'],
    data () {
    return { name: ‘bar’, count: 0 }
    },
    init () {
    this.count++
    },
    created () {
    this.count++
    }
    }))
    // render
    console.log(renderToString(new Vue(compileTemplate({
    template: '',
    data: { msg: 'hello' },
    components: { child }
    }))))
    // output:
    // hello bar: 2

    View Slide

  27. renderToStream
    • renderToString issues
    • Sync rendering !!
    • Blocking the event loop !!
    • renderToStream support the async
    rendering
    • Improve the performance by using the
    Node.js Stream

    View Slide

  28. renderToStream
    • Usage: basic
    // … imports

    const { renderToStream } = createRenderer() // import!!
    // define template compilation
    let compileTemplate = (options) => {
    // ...
    }
    // render stream
    const stream = renderToStream(new Vue(compileTemplate({
    template: '{{ foo }} side {{ bar }}'
    data: { foo: 'server', bar: 'rendering' }
    }))))
    let res = ''
    stream.on('data', chunk => {
    res += chunk
    })
    stream.on('end', () => {
    console.log(res)
    // output:
    // server side rendering
    })

    View Slide

  29. renderToStream
    • Usage: Pipe
    const http from ‘http'
    // ...
    const server = http.createServer((req, res) => {
    // ...


    // render stream
    const stream = renderToStream(new Vue(compileTemplate({
    template: '{{ foo }} side {{ bar }}'
    data: { foo: 'server', bar: 'rendering' }
    }))))

    // pipe!!
    stream.pipe(res)
    })
    server.listen(8000)

    View Slide

  30. SSR benchmark
    • Try to run the below command


    $ npm run bench:ssr

    View Slide

  31. 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

    View Slide

  32. Rendering

    Optimization

    View Slide

  33. It just works
    • No need the below from vue.js compiler to
    optimize the rendering
    • `shouldComponentUpdate`
    • Immutable data structures

    View Slide

  34. 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" } },
    ...
    }],
    ...
    }],
    ...
    }

    {{title}}




    View Slide

  35. • Static subtree skip the diffing in patch
    Optimization

    header
    {{a.b}}
    footer

    {
    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

    View Slide

  36. Control

    of
    rendering

    View Slide

  37. 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

    View Slide

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

    View Slide

  39. 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()

    View Slide

  40. More leaner

    View Slide

  41. 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)

    View Slide

  42. Remove the unneccessary codes
    • Build-in filters
    • Not used APIs and bad practice APIs
    • Unnecessary 1.x codes

    View Slide

  43. Comparing dist files
    • 1.x

    25.79K (min+zip)
    • 2.0
    • runtime only: 12.81K (min+zip)
    • runtime + compiler: 19.09K (min+zip)

    View Slide

  44. Breaking changes

    View Slide

  45. 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

    View Slide

  46. Development
    environments

    View Slide

  47. Added type checking with Flow
    NEW!!

    View Slide

  48. Roadmap

    View Slide

  49. 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)

    View Slide

  50. 1.x LTS (long-term support)
    • Security updates (9-months)
    • Critical bug fixes (6-months)

    View Slide

  51. Conclusion

    View Slide

  52. Conclusion
    • Adopt virtual-dom
    • The below has become possible
    • Improve rendering performance
    • SSR
    • Rendering optimization
    • Control of rendering
    • More learner

    View Slide

  53. “Progressive Framework”
    adaptable to different complexity levels

    View Slide

  54. vuejs-jp slack
    • Direct URL Access

    https://vuejs-jp-slackin.herokuapp.com
    • Vuejs official site for japanese

    http://jp.vuejs.org


    View Slide

  55. Thanks!!

    View Slide