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

Vue.js 2.0 Server Side Rendering

kazupon
November 13, 2016

Vue.js 2.0 Server Side Rendering

Nodefest 2016 Nov 13

kazupon

November 13, 2016
Tweet

More Decks by kazupon

Other Decks in Programming

Transcript

  1. Vue.js 2.0
    αʔόαΠυϨϯμϦϯά
    ౦ژNodeֶԂࡇ2016
    2016-11-13
    @kazupon

    View Slide

  2. ࣗݾ঺հ

    View Slide

  3. Vue.js Core Team member
    https://github.com/kazupon

    View Slide

  4. vuejs-jp ༗ࢤͰٕज़ධ࿦༷ࣾʹͯ Web هࣄ࿈ࡌத
    http://gihyo.jp/dev/serial/01/vuejs

    View Slide

  5. We are building
    Open Innovation Platform!!
    https://cuusoo.com

    View Slide

  6. Vue.js ͱ͸ʁ

    View Slide

  7. ࡞ऀ
    Evan You
    ※ ࡞ऀͷΠϯλϏϡʔهࣄ: Between the Wires | Evan You

    https://betweenthewires.org/between-the-wires-evan-you-cb56660bc8a4#.6b0vzpgzw
    ※ ࡞ऀͷαΠτ

    http://evanyou.me

    View Slide

  8. ϓϩάϨογϒϑϨʔϜϫʔΫ

    View Slide

  9. ※ CC BY Evan You

    https://docs.google.com/presentation/d/1WnYsxRMiNEArT3xz7xXHdKeH1C-jT92VxmptghJb5Es/edit#slide=id.p
    ※ ԼهURL࿈ࡌهࣄ

    http://gihyo.jp/dev/serial/01/vuejs/0001?page=1
    vue-router vuex
    vue-loader
    vueify
    vue-cli
    কདྷ
    ఏڙ༧ఆ
    vue.js ຊମ

    View Slide

  10. • 2016೥10݄1೔(೔ຊ࣌ؒ)

    ίʔυωʔϜ: Ghost in the Shell

    ϦϦʔεʂ
    ࠷৽όʔδϣϯ 2.0
    2017
    2014 2015 2016
    spawn
    0.6 0.8 0.9 0.10 0.11 0.12 1.0
    2.0
    2013
    ※ Πϥετஶ࡞ऀ: @hashedrock ࢯ
    https://twitter.com/hashedrock/status/782069763358924800
    Animatrix
    Blade

    Runner Cowboy

    Bebop
    Dragon

    Ball Evangelion
    ghost in the shell

    View Slide

  11. 2.0 Ͱͷେ͖͍มߋ

    View Slide

  12. ϨϯμϦϯάγεςϜ͕࡮৽ʂ
    • Virtual DOM ΞʔΩςΫνϟΛ࠾༻
    • Evan You ࢯʹΑΔϑϧεΫϥον࣮૷
    • 2िؒͨΒͣͰpre-alphaόʔδϣϯΛ࣮૷

    View Slide

  13. Virtual DOM ʹΑΔޮೳ

    View Slide

  14. ϨϯμϦϯάͷߴ଎Խ
    ※ The Vue Point: Vue 2.0 is Here (Vue.js ެࣜϒϩά)

    https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.v9xl2x8f7

    View Slide

  15. αʔόαΠυϨϯμϦϯά
    Request
    Response
    Client
    Server
    render

    View Slide

  16. ॊೈͳϨϯμϦϯάखஈ
    • એݴతϨϯμϦϯά
    • ςϯϓϨʔτ
    • ໋ྩతϨϯμϦϯά
    • Ծ૝ϊʔυΛར༻ͨ͠
    JavaScript ࣮૷
    • hyperscript / JSX

    View Slide

  17. ΫϩεϓϥοτϑΥʔϜରԠ
    • ϚϧνϞόΠϧσόΠε޲͚ͷϑϨʔϜϫʔΫ
    ※ weex

    https://alibaba.github.io/weex/

    View Slide

  18. ΞδΣϯμ

    View Slide

  19. ࠓ೔࿩͢͜ͱ
    • ϨϯμϦϯάγεςϜ
    • αʔόαΠυϨϯμϦϯά

    View Slide

  20. ϨϯμϦϯάγεςϜ

    View Slide

  21. Vue ͷΑ͋͘ΔҰൠతͳίʔυ


    ...



    ...

    <br/>new Vue({<br/>template: `<div><br/><p>message: {{msg}}</p><br/></div>`,<br/>data: {<br/>msg: 'hi evan!!'<br/>}<br/>}).$mount('#app')<br/>

    ...


    View Slide

  22. ಺෦Ͱ͸৭ʑͱΰχϣΰχϣ͢Δ
    ॳظϨϯμϦϯά׬ྃ
    ࠶ϨϯμϦϯά

    View Slide

  23. ҰൠతͳϨϯμϦϯάͷྲྀΕͰ
    ಺෦ʹ͍ͭͯݟ͍͖ͯ·͠ΐ͏ʂ

    View Slide

  24. ҰൠతͳϨϯμϦϯάͷྲྀΕ
    optimize
    diff + patch
    compile
    generate
    rendering
    track dependencies
    AST Optimized AST
    Virtual DOM

    View Slide

  25. ίϯύΠϧ

    View Slide

  26. ςϯϓϨʔτΛ AST ʹม׵
    • ςϯϓϨʔτύʔαΛར༻ͯ͠AST (Abstract Syntax Tree)
    ʹม׵

    title

    msg: {{msg}}


    Template
    {
    tag: 'div',
    type: 1,
    children: [{
    tag: 'h1',
    type: 1,
    children: [{
    type: 3, text: 'title', …
    }],

    }, {
    tag: 'p',
    type: 1,
    children: [{ type: 2, text: 'msg: {{msg}}', … }],

    }]
    }
    compile
    AST

    View Slide

  27. ςϯϓϨʔτύʔα
    • ςϯϓϨʔτύʔα͸ɺJohn Resig ࢯ੡ͷ΋ͷΛ fork ͠
    ͯ Vue ޲͚ʹಠࣗʹΧελϚΠζ
    ※ ςϯϓϨʔτύʔα

    https://github.com/vuejs/vue/blob/dev/src/compiler/parser/html-parser.js
    ES2015 Ͱ re-write & ࠷దԽ

    View Slide

  28. ࠷దԽ

    View Slide

  29. Ұൠతͳ Virtual DOM
    New Virtual Node Tree
    Old Virtual Node Tree
    diff + patch
    Ծ૝ϊʔυπϦʔͷ diff ࢉग़ίετ͕͔͔Δ

    View Slide

  30. • Virtual DOM ʹΑΔϨϯμϦϯάͷύϑΥʔϚϯεΛΑ
    ͘͢ΔͨΊʹɺVue Ͱ͸ AST ʹରͯ͠ҎԼͷ̎ஈ֊ͷॲ
    ཧΛͯ͠࠷దԽ͢Δ


    1. ੩తͳϊʔυͷݕग़

    2. ੩తͳϊʔυπϦʔͷݕग़
    AST ʹର͢Δ࠷దԽॲཧ

    View Slide

  31. 1. ੩తͳϊʔυͷݕग़
    • ҎԼͷΑ͏ͳςϯϓϨʔτͷέʔεͷ৔߹͸

    title: {{title}}

    :class="{ even: isEven(index), odd: isOdd(index) }"
    v-for="(item, index) in items">
    menu{{index}}: {{item}}



    This is content


    divɺpɺͦͯ͠ text ཁૉΛ
    ੩తͳϊʔυͱͯ͠ݕग़

    View Slide

  32. • ݕग़͞Εͨϊʔυ͸ɺAST ʹ static = true ͱͯ͠ϚʔΩ
    ϯά͞ΕΔ
    1. ੩తͳϊʔυͷݕग़
    {
    tag: 'div',
    children: [{
    tag: 'div',

    }, {
    tag: 'ul', children: […], …
    }, {
    tag: 'div',
    static: true,
    children: [{
    tag: 'p',
    static: true,
    children: [{ static: true, text: 'This is content', … }]
    }],

    }]
    }

    View Slide

  33. 2. ੩తͳϊʔυπϦʔͷݕग़
    • ੩తͳϊʔυΛࢠͱͯ࣋ͭ͠ϧʔτ(root)ͱͳΔཁૉ͕
    ͋Δ͔Ͳ͏͔νΣοΫ͢Δ

    title: {{title}}

    :class="{ even: isEven(index), odd: isOdd(index) }"
    v-for="(item, index) in items">
    menu{{index}}: {{item}}



    This is content


    ͜ͷέʔεͰ͸ɺ͜ͷ div ཁૉ͕
    ੩తͳϊʔυπϦʔͱͯ͠ݕग़

    View Slide

  34. 2. ੩తͳϊʔυπϦʔͷݕग़
    • ݕग़͢ΔͱɺAST ʹ staticRoot = true ͱͯ͠ϚʔΩϯά͢Δ
    {
    tag: 'div',
    children: [
    { tag: 'div', … },
    { tag: 'ul', children: […], … },
    { tag: 'div',
    static: true, staticRoot: true,
    children: [
    { tag: 'p',
    static: true,
    children: [{
    text: 'This is content', static: true, …
    }], …
    }
    ], …
    }
    ]
    }

    View Slide

  35. ϨϯμϦϯάؔ਺ͷੜ੒

    View Slide

  36. AST ͔ΒϨϯμϦϯάؔ਺Λੜ੒
    • ҎԼͷؔ਺Λੜ੒͢Δ
    • render ؔ਺
    • staticRenderFns ؔ਺܊ (഑ྻ)
    • ͜ΕΒؔ਺͸ɺVue Πϯελϯ
    εͷ $options ʹ֨ೲ͞ΕΔ
    Optimized AST

    View Slide

  37. render ؔ਺
    • Ծ૝ϊʔυπϦʔΛฦؔ͢਺

    (e.g. ࠷దԽͰઆ໌ͨ͠ASTΛrenderؔ਺Խͨ͠΋ͷ)
    function anonymous () { with (this) {
    return _h('div', { attrs: { 'id': 'app' } }, [
    _h('div', { staticClass: 'header'}, ['title: 'ɹ+ɹ_s(title)]),
    _h('ul', { staticClass: 'menu',
    attrs: { style: 'list-style-type: none' }
    }, [_l((items), function (item, index) {
    return _h('li', {
    ɹɹɹɹɹɹɹɹɹɹkey: item.id,
    class: { even: isEven(index), odd: isOdd(index) },
    attrs: { style:'margin: 0' }
    }, ['menu' + _s(index) + ': ' + _s(item.name)])
    })]
    ),
    _m(0)
    ])
    }
    ࠷దԽʹΑΓݕग़͞Εͨ੩తͳϊʔυπϦʔͷ෦෼͸ɺ
    ಺෦ϝιουʹϚοϐϯά

    View Slide

  38. staticRenderFns ؔ਺܊
    • ࠷దԽʹΑΓ AST Ͱݕग़ͨ͠੩తͳϊʔυπϦʔ͸ɺ
    Ծ૝ϊʔυπϦʔͱͯ͠ฦ͢Α͏ʹੜ੒ͨؔ͠਺Λ഑ྻ
    ʹ֨ೲ͢Δ
    [
    function anonymous () { with (this) {
    return _h('div', { staticClass: 'content' }, [
    _h('p', ['This is content'])
    ])
    }}
    ]

    View Slide

  39. ϨϯμϦϯά

    View Slide

  40. ϦΞΫςΟϒγεςϜʹΑΔϨϯμϦϯά
    diff + patch
    create
    call
    Virtual Node Tree
    notify

    View Slide

  41. Watcher ʹΑΔσʔλมߋͷ؂ࢹ
    • σʔλґଘؔ܎Λ௥੻͠ɺσʔλมߋΛ؂ࢹ͢Δ
    • σʔλมߋݕग़ͷ౎౓ɺ Watcher ͸಺෦ͷ _render ϝ
    ιουΛݺͼग़ͯ͠࠶ϨϯμϦϯά
    const Component = {
    props: ['msg'],
    data () {
    return {
    title: 'hello',
    items: […]
    }
    },

    }
    msg
    data/props
    Watcher
    title
    items
    0
    x

    Collect
    Dependencies

    View Slide

  42. Ծ૝ϊʔυπϦʔͷੜ੒
    • render ؔ਺ͱ staticRenderFns ؔ਺܊ͰԾ૝ϊʔυπϦʔ
    Λੜ੒
    function anonymous () { with (this) {
    return _h('div', { attrs: { 'id': 'app' } }, [
    _h('div', { staticClass: 'header'}, ['title: 'ɹ+ɹ_s(title)]),
    _h('ul', { staticClass: 'menu',
    attrs: { style: 'list-style-type: none' }
    }, [_l((items), function (item, index) {
    return _h('li', {
    ɹɹɹɹɹɹɹɹɹɹkey: item.id,
    class: { even: isEven(index), odd: isOdd(index) },
    attrs: { style: 'margin: 0' }
    }, ['menu” + _s(index) + ": “ + _s(item.name)])
    })]
    ),
    _m(0)
    ])
    }
    [
    function anonymous () { with (this) {
    return _h('div', { staticClass: 'content' }, [
    _h('p', ['This is content'])
    ])
    }}
    ]
    staticRenderFns
    render

    View Slide

  43. Ծ૝ϊʔυπϦʔͷΩϟγϡԽͱϚʔΩϯά
    • staticRenderFns ͷ࣮ߦ݁ՌͰಘΒΕΔ੩తͳԾ૝ϊʔυ
    πϦʔ͸ɺ࠷ॳͷϨϯμϦϯάͷࡍʹ͜ΕΒ݁ՌΛ Vue
    Πϯελϯε಺෦ʹΩϟογϡ͢Δ
    • ͜ͷ࣌ɺԾ૝ϊʔυπϦʔʹ isStatic = true ͰϚʔΩϯ
    ά͢Δ͜ͱͰɺޙͷ Virtual DOM ͷ diff ʹ͓͍ͯεΩο
    ϓ͞ΕΔ
    • ࠶ϨϯμϦϯά࣌ʹ͸ɺΩϟογϡԽ͞Εͨ΋ͷΛར༻

    View Slide

  44. Vue ͷ Virtual DOM
    • Virtual DOM ͸ snabbdom Λ fork ͯ͠ಠࣗʹΧελϚΠ
    ζͨ͠΋ͷ

    https://github.com/snabbdom/snabbdom

    View Slide

  45. Virtual DOM ͷ diff / patch
    • diff / patch ͸جຊ snabbdom ϕʔεͰɺVue ͷ࠷దԽॲ
    ཧʹΑͬͯ diff ΛεΩοϓ͢Δ͜ͱͰɺDOM Λੜ੒͢Δ
    ·ͰॲཧίετΛ࡟ݮ
    https://github.com/vuejs/vue/blob/dev/src/core/vdom/patch.js

    View Slide

  46. Ծ૝ϊʔυπϦʔͷੜ੒͔Β
    Virtual DOM ʹΑΔॲཧ·Ͱͷ
    Πϝʔδ

    View Slide

  47. ॳظͷϨϯμϦϯά
    return
    caching
    &
    marking
    create
    diff + patch
    skip diff of the
    marked tree

    View Slide

  48. ߋ৽࣌ͷ࠶ϨϯμϦϯά
    return
    create
    diff + patch
    skip diff of the
    marked tree

    View Slide

  49. ίϯϙʔωϯτπϦʔ
    ͷ
    ϨϯμϦϯά

    View Slide

  50. • ֤ίϯϙʔωϯτຖʹ Watcher Λհͯ͠τοϓμ΢ϯత
    ʹϨϯμϦϯά
    Ұ൪τοϓ͔Βࢠʹ޲͔ͬͯϨϯμϦϯά
    Watcher
    track
    dependencies
    component
    Root (new Vue)

    View Slide

  51. • ίϯϙʔωϯτ಺ͷ data/props ͕ɺଞʹґଘ͕ͳ͘ɺ
    ͦͷίϯϙʔωϯτ಺ͷΈͳΒɺͦͷίϯϙʔωϯτͩ
    ͚࠶ϨϯμϦϯά
    ίϯϙʔωϯτ಺ʹดͨ͡σʔλͷมߋݕग़
    Root (new Vue)

    View Slide

  52. • ίϯϙʔωϯτ಺ͷ data/props ͕ɺଞͷࢠίϯϙʔω
    ϯτʹόέπϦϨʔ͍ͯ͠Δ৔߹͸ɺόέπϦϨʔઌͷ
    ࢠίϯϙʔωϯτ΋࠶ϨϯμϦϯά
    σʔλͷ୯ํ޲όΠϯσΟϯά
    pass props
    Root (new Vue)

    View Slide

  53. • ࢠίϯϙʔωϯτ͕਌ίϯϙʔωϯτͱv-modelͰ૒ํ
    ޲σʔλόΠϯσΟϯά͍ͯ͠Δ৔߹͸ɺ਌ʹσʔλม
    ߋΛ௨஌ͨ͠৔߹͸ɺࢠ΋࠶ϨϯμϦϯά͢Δ
    v-modelʹΑΔ૒ํ޲όΠϯσΟϯά
    pass props
    emit events
    Root (new Vue)

    View Slide

  54. ଞͷ
    ϨϯμϦϯάγεςϜ
    ͱͷൺֱ

    View Slide

  55. Demystifying Frontend Framework Performance
    • Nodric.js 2016 Ͱൃදͨ͠ Evan You ࢯͷ্هλΠτϧͷࢿ
    ྉ͕Α͘·ͱ·͍ͬͯΔͷͰɺҰݟ͢Δ͜ͱΛ͓קΊ͢
    Δ
    • εϥΠυ

    https://docs.google.com/presentation/d/
    1Ju5NryLLI-2aXm_XwsdF5rU0QpOpeyVW9F8JeeSuj-k/
    edit#slide=id.p
    • ϏσΦ

    https://www.youtube.com/watch?v=Ag-1wmHWwS4

    View Slide

  56. ͞ΒͳΔ࠷దԽʹ޲͚ͯ

    View Slide

  57. ࠷దԽ߲໨
    • ςϯϓϨʔτͷࣄલίϯύΠϧ + ϥϯλΠϜ
    • v-for ʹΑΔϦετϨϯμϦϯά࣌ʹ͓͚Δ key ଐੑ
    • render ؔ਺ʹΑΔύϑΥʔϚϯενϡʔχϯά࣮૷
    • ؔ਺ܕίϯϙʔωϯτ (functional component)

    View Slide

  58. αʔόαΠυϨϯμϦϯά

    View Slide

  59. αʔόαΠυϨϯμϦϯάͷॏཁੑ
    • γϯάϧϖʔδΞϓϦέʔγϣϯʹΑΓϢʔβʔʹ৺஍
    ྑ͍UXΛఏڙͰ͖ΔΑ͏ʹͳͬͨ
    • ͕ɺҎԼͷ໰୊఺͕͋Δ
    • SEOରࡦ
    • ॳظදࣔͷϩʔσΟϯά࣌ؒ

    View Slide

  60. ैདྷͷVueͰ͸೉͔ͬͨ͠
    • Vue 2.0 ҎલͷόʔδϣϯͰ͸ɺυΩϡϝϯτϑϥάϝϯ
    τʹΑΔੜDOMϕʔεʹΑΔϨϯμϦϯάͷͨΊɺίΞ
    ଆͰ͸αϙʔτ͍ͯ͠ͳ͔ͬͨ
    • ରԠ͢Δʹ͸ɺαʔυϕϯμͷϨϯμϥΛར༻͢Δ͔ɺ
    ಠࣗʹରԠ͢Δඞཁ͕͋ͬͨ
    • ͞ΒʹɺϋΠυϨʔγϣϯͷ࢓૊ΈɺΫϥΠΞϯταΠ
    υͷϥΠϒϥϦͷαʔόαΠυରԠͳͲɺશ෦ಠࣗʹର
    Ԡ͢Δඞཁ͕͋ͬͨ

    View Slide

  61. Vue 2.0 Ͱ͸؀ڥ͕େ͖͘վળ
    • Virtual DOM ʹΑΓந৅Խ͞ΕͨϨϯμϦϯά
    • ϋΠυϨʔγϣϯͷ࢓૊Έ
    • ϢχόʔαϧରԠ͞Εͨެࣜʹఏڙ͢ΔϥΠϒϥϦ
    • Node.js ޲͚ʹϨϯμϥ
    • ίϯςΩετʹΑΔႈ౳ੑΛอূ͢ΔϨϯμϦϯά
    • αʔό޲͚ʹ࠷దԽ͞ΕͨϞδϡʔϧͷόϯυϦϯά

    View Slide

  62. • Vue 2.0 Ҏ߱Ͱ͸ɺҎԼͷެࣜϥΠϒϥϦͱόϯυϦϯ
    άπʔϧͰɺαʔόαΠυϨϯμϦϯάΛ༰қʹ࣮ݱ͢
    Δ͜ͱ͕Ͱ͖Δ
    ੔ͬͨαʔόαΠυϨϯμϦϯά؀ڥ
    vue
    vuex
    vue-router
    vue-server-renderer
    Vue library stack
    +
    and other …

    View Slide

  63. Vue 2.0 ʹ͓͚Δ
    αʔόαΠυϨϯμϦϯά
    ͷྲྀΕʹ͍ͭͯݟ͍͖ͯ·͠ΐ͏ʂ

    View Slide

  64. Client
    Server αʔόଆͰ͸ɺVueͰ࡞ΒΕͨ
    ΞϓϦέʔγϣϯίʔυ͕
    αʔόଆͰ΋ಈ࡞͢ΔΑ͏όϯ
    υϧԽ͞Εͨ΋ͷ͕ಡΈࠐ·Ε
    ͯಈ࡞
    ίϯϙʔωϯτΛαʔόଆ
    ͰϨϯμϦϯά͢ΔͨΊͷ
    Ϩϯμϥ΋ΠϯελϯεԽ

    View Slide

  65. Client
    Server
    ϦΫΤετ
    GET /:user_id/profile
    ϢʔβʔʹΑΔΞΫηε
    ɾɾɾ
    ϦΫΤετຖʹ
    αϯυϘοΫεΛ࡞੒ͯ͠
    ίϯςΩετΛࢦఆͯ͠
    ΤϯτϦϙΠϯτͷ Vue Λ࣮ߦͤ͞Δ

    View Slide

  66. Client
    Server
    route ʹରԠ͢Δ
    ίϯϙʔωϯτΛ
    ಈ࡞ͤ͞ɺσʔλ
    ΛϑΣον
    ɾɾɾ
    ΫϥΠΞϯτʹ౉͢ॳظঢ়ଶΛJSONͱ͠
    ͯຒΊࠐΉΑ͏ʹ
    HTMLϨϯμϦϯάͯ͠ϨεϙϯεΛฦ͢

    View Slide

  67. Client
    Server
    Ϩεϙϯε
    Ϛ΢ϯτ&ϋΠυϨʔτ
    ΫϥΠΞϯτ͸αʔό͔ΒϨϯμϦϯά͞Ε
    ͨHTMLͱΫϥΠΞϯτ޲͚ʹόϯυϧԽ͞
    ΕͨΞϓϦέʔγϣϯίʔυ͕഑৴͞ΕΔ
    ϒϥ΢βଆͰHTMLΛϩʔυͨ͠
    ޙɺΤϯτϦϙΠϯτͱͳΔVueΛ
    ಈ࡞ͤ͞ɺϚ΢ϯτ&ϋΠυϨʔτ
    ʹΑ࣮ͬͯࡍʹ಺༰Λදࣔ͢Δ

    View Slide

  68. Client
    Server
    ޙ͸ɺΫϥΠΞϯτଆͰ
    ϧʔςΟϯάΛߦ͍ɺ
    ඞཁʹԠͯ͡σʔλΛϑΣονͯ͠
    ϨϯμϦϯά͢Δ

    View Slide

  69. αʔόαΠυϨϯμϦϯάΛߏ੒͢Δ4ཁૉ
    • 1. Ϩϯμϥ
    • 2. ϋΠυϨʔγϣϯ
    • 3. ίϯςΩετ
    • 4. όϯυϦϯά

    View Slide

  70. 1. Ϩϯμϥ

    View Slide

  71. ఏڙ͢ΔϨϯμϥ
    • Vue ΞϓϦέʔγϣϯΛαʔόαΠυͰϨϯμϦϯά͢
    ΔͨΊͷ Node.js ؀ڥͰಈ࡞͢ΔϨϯμϦϯάϞδϡʔ
    ϧ
    • Ϩϯμϥ͸ɺࢦఆ͞Εͨ Vue ΞϓϦέʔγϣϯͷrender
    ؔ਺ʹΑͬͯऔಘͨ͠Ծ૝ϊʔυπϦʔΛ walk ͯ͠
    HTML จࣈྻͱͯ͠ϨϯμϦϯά

    View Slide

  72. جຊతͳ࢖͍ํ
    • NPMͰΠϯετʔϧ

    $ npm install vue-server-renderer
    • ϨϯμϥΛ࡞੒ͯ͠ɺrenderToString ͰϨϯμϦϯά
    const Vue = require('vue')
    const renderer = require('vue-server-renderer').createRenderer()
    const vm = new Vue({
    render (h) {
    return h('div', 'hello')
    }
    })
    renderer.renderToString(vm, (err, html) => {
    console.log(html) // -> hello
    })

    View Slide

  73. Stream ʹΑΔϨϯμϦϯά
    • Node.js ͷ Stream API ΋αϙʔτɻrenderToStream Ͱ
    stream Λ࡞੒ͯ͠ɺstream ΠϯλʔϑΣΠεʹΑͬͯϊ
    ϯϒϩοΩϯάͳϨϯμϦϯά͕Մೳ
    app.get('/', (req, res) => {
    const vm = new App({ url: req.url })
    const stream = renderer.renderToStream(vm)
    res.write(`...`)
    stream.on('data', chunk => {
    res.write(chunk)
    })
    stream.on('end', () => {
    res.end('')
    })
    })

    View Slide

  74. ΩϟγϡʹΑΔߴ଎Խ
    • Φϓγϣϯʹ cache ΦϒδΣΫτΛࢦఆ͢Δ͜ͱͰɺί
    ϯϙʔωϯτͷඳը݁ՌΛΩϟογϯά͢Δ͜ͱʹΑ
    Γɺ͞ΒͳΔύϑΥʔϚϯεΛ޲্͕Մೳ
    const LRU = require('lru-cache')
    const renderer = createRenderer({
    cache: LRU({ max: 10000 })
    })

    View Slide

  75. Ωϟγϡʹ͓͚ΔඞࢸΠϯλʔϑΣΠε
    • Φϓγϣϯʹ ࢦఆ͢Δ cache ΦϒδΣΫτ͸ɺҎԼͷ
    ΠϯλʔϑΣΠεΛ࣮૷͍ͯ͠Ε͹ΩϟογϡՄೳ
    {
    get: (key: string, [cb: Function]) => string | void,
    set: (key: string, val: string) => void,
    has?: (key: string, [cb: Function]) => boolean | void // optional
    }

    View Slide

  76. ྫ: RedisClient ʹΑΔΩϟογϡ
    const redisClient = require('redis').createClient()
    const renderer = createRenderer({
    cache: {
    get: (key, cb) => {
    redisClient.get(key, (err, res) => {
    // handle error if any
    cb(res)
    })
    },
    set: (key, val) => {
    redisClient.set(key, val)
    }
    }
    })

    View Slide

  77. ίϯϙʔωϯτͷΩϟογϡ
    • ίϯϙʔωϯτΛΩϟογϡʹରԠ͢ΔͨΊʹ͸ɺҎ
    ԼΛ಺༰Λ options ʹؚΊ࣮ͯ૷͢Δඞཁ͕͋Δ
    • name ΦϓγϣϯʹΑΔϢχʔΫͳίϯϙʔωϯτ໊
    • serverCacheKey ؔ਺ʹΑͬͯίϯϙʔωϯτຖʹϢ
    χʔΫͳΩʔΛฦ͢

    View Slide

  78. ྫ: ίϯϙʔωϯτͷΩϟογϡରԠ
    export default {
    name: 'item', // required
    props: ['item'],
    serverCacheKey: props => props.item.id,
    render (h) {
    return h('div', this.item.id)
    }
    }

    View Slide

  79. ΩϟγϡʹΑΔ෭࡞༻
    • ࣍ͷΑ͏ͳؒҧͬͨ࢖͍ํΛ͢ΔͱϨϯμϦϯάपΓͷ
    όάΛੜΈग़͢ͷͰ஫ҙ͕ඞཁ
    • άϩʔόϧঢ়ଶʹґଘ͢ΔࢠίϯϙʔωϯτͷΩϟο
    γϡ
    • εϩοτΛड͚෇͚ΔίϯϙʔωϯτͷΩϟογϡ

    View Slide

  80. ΩϟογϡͷϕετϓϥΫςΟε
    • ಉ͡ props Λड͚औͬͨΒඞͣಉ͡HTMLΛඳը͢Δί
    ϯϙʔωϯτʹରͯ͠Ωϟογϡ͢Δͷ͕ཧ૝
    • ੩తͳHTMLΛඳը͢Δίϯϙʔωϯτ
    • ϦετͷΞΠςϜΛඳը͢Δίϯϙʔωϯτ
    • ϘλϯɺΞϥʔτͳͲͷҰൠతͳ UI ίϯϙʔωϯτ

    View Slide

  81. 2. ϋΠυϨʔγϣϯ

    View Slide

  82. ݱ࣮ੈքͷϋΠυϨʔγϣϯ
    • ϋΠυϨʔγϣϯ͸ӳޠͰ͸hydrationɻݕࡧ͢Δͱ
    ʮϦΞॅͷੈքʯͰ͸ɺओʹҎԼͷΑ͏ͳҙຯ
    • hydration: ਫ෼ิڅ
    • ҎԼิ଍
    • dehydration: ୤ਫ
    • re-hydration: ิਫ

    View Slide

  83. Vue ͷੈքͰ͸ʁ
    • ࡶʹ͍͏ͱʮhydration: ঢ়ଶิڅʯ
    • DOM ͕ঢ়ଶ (JSON) Λิڅͯ͠

    ظ଴͢΂͖࢟ʹͳΔ͜ͱ
    DOM

    View Slide

  84. • αʔόαΠυͰϨϯμϦϯά͞ΕͨDOMπϦʔͱɺΫϥΠΞϯτα
    ΠυͰߏங͞ΕΔԾ૝ϊʔυπϦʔ͕Ұக͢Δ͔Ͳ͏͔ͷݕূͱ
    ࠶ߏங·ͰͷҰ࿈ͷࣄ৅ͷ͜ͱ
    ۩ମతʹϋΠυϨʔγϣϯͬͯʁ
    HTTP
    App (Root vue instance)
    Render
    Functions
    ...

    ...

    ...
    response
    hydrate JSON
    new Vue({ … }).$mount(‘#app’)
    render
    Virtual Node
    Tree
    Rendered DOM
    Tree
    window.__initial__ = { …. }
    checking
    set $el

    View Slide

  85. • αʔόαΠυͰϨϯμϦϯά͞ΕͨDOMπϦʔΛഁغͯ͠ɺΫϥΠ
    ΞϯταΠυͰैདྷͷVirtual DOM ͷॲཧϑϩʔͰϨϯμϦϯά
    αʔόͱΫϥΠΞϯτ͕Ұக͠ͳ͔ͬͨ৔߹
    HTTP
    App (Root vue instance)
    Render
    Functions
    ...

    ...

    ...
    response
    hydrate JSON
    new Vue({ … }).$mount(‘#app’)
    Rendered DOM
    Tree
    window.__initial__ = { …. }
    checking
    render
    Virtual Node
    Tree
    diff +
    patch

    View Slide

  86. ։ൃϞʔυͱϓϩμΫγϣϯϞʔυͷҧ͍
    • ։ൃϞʔυͰ͸ɺΫϥΠΞϯτଆͰੜ੒͞ΕͨԾ૝ϊʔ
    υπϦʔͷɺαʔόͰϨϯμϦϯά͞ΕͨDOMπϦʔͱ
    Ұக͍ͯ͠Δ͔Ͳ͏͔ͷݕূॲཧ͸࣮ߦ͢Δ
    • ϓϩμΫγϣϯϞʔυͰ͸ɺύϑΥʔϚϯεΛ࠷େԽ͢
    ΔͨΊʹ͜ͷݕূΛແޮʹ͍ͯ͠Δ

    View Slide

  87. ϋΠυϨʔγϣϯͷ஫ҙࣄ߲
    • αʔόαΠυϨϯμϦϯάͱΫϥΠΞϯτͷϋΠυϨʔ
    γϣϯʹ͓͍ͯɺValid ͳߏ଄Λͨ͠ HTML Λهࡌ͠ͳ
    ͍ͱෆҰக͕ൃੜ͢Δ

    hi evan!

    ϒϥ΢β͸ࣗಈతʹ
    Λૠೖ͢Δ
    Vue͸ςϯϓϨʔτΛίϯύΠϧ͢Δͱ
    ͦͷߏ଄ͷ·· Virtual-DOM Λੜ੒͢Δ
    ෆਖ਼ͳߏ଄Λ࣋ͬͨ

    ςϯϓϨʔτ

    View Slide

  88. 3. ίϯςΩετ

    View Slide

  89. • VueͰ࡞੒ͨ͠ΞϓϦέʔγϣϯίʔυ͕Πϯελϯε
    Խ͞ΕΔͱɺNode ϓϩηεʹ͓͍ͯΫϥΠΞϯτ͔Β
    དྷͨϦΫΤετؒͰڞ༗͞ΕΔ
    ίϯςΩετͷඞཁੑ
    request1
    request2
    requestX
    άϩʔόϧͳঢ়ଶ͕Ԛછ͞
    Εͯ͠·͍ɺϨϯμϦϯά
    ݁ՌʹѱӨڹΛٴ΅͢

    View Slide

  90. ίϯςΩετʹΑΔԚછͷճආ
    • ֤ϦΫΤετຖʹίϯςΩετΛ࡞੒ͯ͠ɺͦ͜ʹঢ়ଶ
    Λઃఆ͢Δ͜ͱͰɺ֤αϯυϘοΫε಺Ͱঢ়ଶ͕อޢ
    ͞ΕΔ
    request1
    request2
    requestX
    Context
    Context
    Context
    vm. runInNewContext
    vm. runInNewContext
    vm. runInNewContext

    View Slide

  91. ίϯςΩετͷಋೖ
    • αʔό޲͚ͷ Vue ΞϓϦέʔγϣϯΛ࣮ߦͤ͞ΔΤϯτ
    ϦϙΠϯτΛ༻ҙ͢Δ
    // server-entry.js
    import Vue from 'vue'
    import App from './App.vue'
    const app = new Vue(App)
    // όϯυϧϨϯμϥଆͰϨϯμϦϯάͰݺͼग़͢ࡍʹ౉͞ΕΔ
    // ίϯςΩετΛड͚औΔؔ਺Λ export ͢Δ
    // ؔ਺͸ Vue ΠϯελϯεΛฦ͢ඞཁ͕͋Δ
    export default context => {
    // σʔλͷϑΣον
    return app.fetchServerData(context.url).then(() => {
    return app
    })
    }

    View Slide

  92. ίϯςΩετͷಋೖ
    • Vue ͕ఏڙ͢ΔόϯυϧϨϯμϥʹΑΓίϯςΩετʹ
    ରԠͨ͠ϨϯμϥΛ࡞੒
    const createBundleRenderer =
    require('vue-server-renderer').createBundleRenderer
    const bundle = require('./dist/server-bundle.js')
    const rederer = createBundleRenderer(bundle)

    View Slide

  93. ίϯςΩετͷಋೖ
    • ϦΫΤετϋϯυϥ಺ͰίϯςΩετΛ࡞੒͠ɺϨϯμ
    ϥͷϨϯμϦϯάϝιουʹࢦఆ࣮ͯ͠ߦ
    // for express
    app.get('*', (req, res) => {
    const context = { url: req.url }
    const renderStream = renderer.renderToStream(context)
    res.write(html.head)
    renderStream.on('data', chunk => {
    ...
    res.write(chunk)
    })
    renderStream.on('end', () => {
    res.end(html.tail)
    })
    })
    ϨϯμϦϯάͷࡍʹ༻ҙͨ͠Τ
    ϯτϦϙΠϯτ͕ݺ͹Εͯɺί
    ϯςΩετ͕౉͞ΕΔ

    View Slide

  94. 4. όϯυϦϯά

    View Slide

  95. αʔό޲͚΁όϯυϧԽ͢Δඞཁੑ
    • ϦΫΤετຖͷαϯυϘοΫε͸ɺΞϓϦέʔγϣϯ
    ίʔυΛಈ࡞ͤ͞ΔͱશͯͷґଘϞδϡʔϧ΋ҰॹʹҾ
    ͖ࠐΜͰಈ࡞͢Δ
    Node process
    request
    request
    load
    load
    ಡΈࠐ·Εͨ
    ґଘϞδϡʔ
    ϧΛɺ࠶౓ղ
    ੳ͠ɺධՁ͢
    ΔͨΊɺύ
    ϑΥʔϚϯε
    ͸Α͘ͳ͍

    View Slide

  96. ґଘϞδϡʔϧΛ֎෦Խ͢Δ͜ͱͰղܾ
    • ґଘϞδϡʔϧΛ֎෦Խ͢Δ͜ͱʹΑΓɺαϯυϘοΫ
    ε্ʹ͸ɺNodeϓϩηεͰಡΈࠐ·ΕͨґଘϞδϡʔ
    ϧͰࢀরͯ͠ಈ࡞͢ΔΑ͏ʹͳΔ
    Node process
    request
    request
    reference

    View Slide

  97. αʔό޲͚ͷόϯυϧԽ (webpackͷྫ)
    • αʔό޲͚ʹɺґଘϞδϡʔϧΛ֎෦Խ͢ΔΑ͏ʹόϯ
    υϧԽͷઃఆΛ͢Δ
    // webpack ͷઃఆ
    module.exports = {
    entry: './src/server-entry.js',
    target: 'node',
    output: {
    ...,
    libraryTarget: 'commonjs2'
    },
    // webpack ͷ externals Λར༻ͯ͠ɺpackage.json ͷ "dependencies"ͷ ݩʹ
    // ͋ΔϞδϡʔϧΛશͯ֎෦Խ
    externals: Object.keys(require('./package.json').dependencies)
    }

    View Slide

  98. αʔό޲͚ͷόϯυϧԽ
    • αʔόଆͰґଘϞδϡʔϧ͕֎෦Խ͞ΕͨόϯυϧϑΝ
    ΠϧΛҾ͖ࠐΈɺόϯυϧϨϯμϥͰͦΕΛࢦఆͯ͠Ϩ
    ϯμϥΛ࡞੒͢Δ
    const createBundleRenderer =
    require('vue-server-renderer').createBundleRenderer
    const bundle = require('./dist/server-bundle.js')
    const rederer = createBundleRenderer(bundle)

    View Slide

  99. αʔό޲͚όϯυϧԽͷ஫ҙࣄ߲
    • ϦΫΤετؒͰڞ༗͞Ε͍ͯΔͷͰɺґଘϞδϡʔϧ͕
    ႈ౳͔Ͳ͏͔֬ೝ͕ඞཁ
    • ҟͳΔϦΫΤετؒͰৗʹಉ͡ඳը݁ՌʹͳΔͷ͔
    • ґଘϞδϡʔϧʹάϩʔόϧͳঢ়ଶΛ͍࣋ͬͯͯɺΞϓ
    ϦέʔγϣϯίʔυʹΑͬͯมߋ͞ΕΔ΋ͷ͍ͭͯ͸஫
    ҙ͕ඞཁ

    View Slide

  100. αʔόαΠυϨϯμϦϯά
    ʹ͓͚Δ
    όϯυϧԽͷΠϝʔδ

    View Slide

  101. όϯυϧԽͷΠϝʔδ(webpack)

    View Slide

  102. αʔόαΠυʹ͓͚Δ
    Vue ͷ API

    View Slide

  103. ϥΠϑαΠΫϧϑοΫ
    • beforeCreate
    • created











    • beforeMount
    • mounted
    • beforeUpdate
    • updated
    • activated
    • deactivated
    • beforeDestroy
    • destroyed
    ݺ͹ΕΔϑοΫ ݺ͹Εͳ͍ϑοΫ

    View Slide

  104. ϥΠϑαΠΫϧϑοΫҎ֎
    • Ͳͷ API ͕αʔόαΠυͰಈ࡞͢Δ͔Ͳ͏͔͸ɺݫີʹ
    ͸ॻ͔Ε͍ͯͳ͍
    • DOM ʹґଘ͍ͯ͠ͳ͍ܥ౷ͷ΋ͷ͸ɺಈ࡞͢Δ͸ͣ
    • Πϕϯτ: $emit, $off, $on, $once
    • σʔλܥ: $watch, $set, $delete, $data, ͳͲ
    • ͦͷଞ΋Ζ΋Ζ …

    View Slide

  105. αʔόαΠυϨϯμϦϯά
    Example

    View Slide

  106. vue-hackernews-2.0
    • ެࣜͰఏڙ͢ΔαʔόαΠυϨϯμϦϯά example

    https://github.com/vuejs/vue-hackernews-2.0

    View Slide

  107. ·ͱΊ

    View Slide

  108. ϨϯμϦϯάγεςϜ
    • Vue ͷϨϯμϦϯάγεςϜ͸ɺ࠷దԽͱϦΞΫςΟϒ
    γεςϜͱ૊Έ߹ΘͤΔ͜ͱʹΑΓɺಛʹҙࣝ͠ͳͯ͘
    ΋଎͍ϨϯμϦϯάΛఏڙ͍ͯ͠Δ
    • ·ͨɺ೚ҙͰϨϯμϦϯάΛ੍ޚͰ͖Δ࢓૊ΈΛఏڙ͢
    Δ͜ͱͰɺ͞ΒͳΔύϑΥʔϚϯεͷ޲্΋Մೳʹͳͬ
    ͍ͯΔ

    View Slide

  109. αʔόαΠυϨϯμϦϯά
    • ެࣜʹఏڙ͢ΔϥΠϒϥϦͱπʔϧʹΑͬͯɺαʔόα
    ΠυϨϯμϦϯάΛ༰қʹ࣮ݱ͢Δ͜ͱ͕Մೳʹͳͬͨ
    • ͜ΕʹΑΓɺαʔόαΠυͱΫϥΠΞϯταΠυͷ྆ํ
    ʹରԠՄೳͳɺuniversal/isomorphic ͳΞϓϦέʔγϣ
    ϯߏங͕Մೳʹͳͬͨ

    View Slide

  110. ͱ͍͏Θ͚Ͱɺ

    View Slide

  111. universal / isomorphic ͳ
    ίϯϙʔωϯτΛ࡞Δʹ͸ʁ

    View Slide

  112. ༩͑ΒΕͨσʔλʹରͯ͠
    ৗʹಉ͡ϨϯμϦϯά݁ՌʹͳΔ
    ؔ਺ܕͳίϯϙʔωϯτΛ
    ࣮૷Λ͢Δ͜ͱʂ

    View Slide

  113. Ҏ্ʂ

    View Slide

  114. one more thing …

    View Slide

  115. Vue.js ೔ຊޠެࣜαΠτ
    Coming soon!!
    Vue.js ೔ຊޠެࣜαΠτ

    View Slide

  116. ೔ຊਓ޲͚ Vue.js ίϛϡχςΟ
    • URL

    https://vuejs-jp-slackin.herokuapp.com
    • Vue.js ೔ຊޠެࣜαΠτܦ༝Ͱ΋ࢀՃͰ͖·͢

    http://jp.vuejs.org


    View Slide

  117. ͝੩ௌ
    ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ

    View Slide