Vue.js 2.0 Server Side Rendering

38bee248082f6071230de65e9d74a944?s=47 kazupon
November 13, 2016

Vue.js 2.0 Server Side Rendering

Nodefest 2016 Nov 13

38bee248082f6071230de65e9d74a944?s=128

kazupon

November 13, 2016
Tweet

Transcript

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

  2. ࣗݾ঺հ

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

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

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

  6. Vue.js ͱ͸ʁ

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

    You
 https://betweenthewires.org/between-the-wires-evan-you-cb56660bc8a4#.6b0vzpgzw ※ ࡞ऀͷαΠτ
 http://evanyou.me
  8. ϓϩάϨογϒϑϨʔϜϫʔΫ

  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 ຊମ
  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
  11. 2.0 Ͱͷେ͖͍มߋ

  12. ϨϯμϦϯάγεςϜ͕࡮৽ʂ • Virtual DOM ΞʔΩςΫνϟΛ࠾༻ • Evan You ࢯʹΑΔϑϧεΫϥον࣮૷ •

    2िؒͨΒͣͰpre-alphaόʔδϣϯΛ࣮૷
  13. Virtual DOM ʹΑΔޮೳ

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

    ެࣜϒϩά)
 https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.v9xl2x8f7
  15. αʔόαΠυϨϯμϦϯά Request Response Client Server render

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

    ࣮૷ • hyperscript / JSX
  17. ΫϩεϓϥοτϑΥʔϜରԠ • ϚϧνϞόΠϧσόΠε޲͚ͷϑϨʔϜϫʔΫ ※ weex
 https://alibaba.github.io/weex/

  18. ΞδΣϯμ

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

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

  21. Vue ͷΑ͋͘ΔҰൠతͳίʔυ <html> <head> ... <script src="./vue.js"></script> </head> <body>
 ...

    <div id="app"></div>
 <script> new Vue({ template: `<div> <p>message: {{msg}}</p> </div>`, data: { msg: 'hi evan!!' } }).$mount('#app') </script>
 ... </body> </html>
  22. ಺෦Ͱ͸৭ʑͱΰχϣΰχϣ͢Δ ॳظϨϯμϦϯά׬ྃ ࠶ϨϯμϦϯά

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

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

    AST Optimized AST Virtual DOM
  25. ίϯύΠϧ

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

    id="app"> <h1>title</h1> <p class="msg"> msg: {{msg}} </p> </div> 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
  27. ςϯϓϨʔτύʔα • ςϯϓϨʔτύʔα͸ɺJohn Resig ࢯ੡ͷ΋ͷΛ fork ͠ ͯ Vue ޲͚ʹಠࣗʹΧελϚΠζ

    ※ ςϯϓϨʔτύʔα
 https://github.com/vuejs/vue/blob/dev/src/compiler/parser/html-parser.js ES2015 Ͱ re-write & ࠷దԽ
  28. ࠷దԽ

  29. Ұൠతͳ Virtual DOM New Virtual Node Tree Old Virtual Node

    Tree diff + patch Ծ૝ϊʔυπϦʔͷ diff ࢉग़ίετ͕͔͔Δ
  30. • Virtual DOM ʹΑΔϨϯμϦϯάͷύϑΥʔϚϯεΛΑ ͘͢ΔͨΊʹɺVue Ͱ͸ AST ʹରͯ͠ҎԼͷ̎ஈ֊ͷॲ ཧΛͯ͠࠷దԽ͢Δ
 


    1. ੩తͳϊʔυͷݕग़
 2. ੩తͳϊʔυπϦʔͷݕग़ AST ʹର͢Δ࠷దԽॲཧ
  31. 1. ੩తͳϊʔυͷݕग़ • ҎԼͷΑ͏ͳςϯϓϨʔτͷέʔεͷ৔߹͸ <div id="app"> <div class="header">title: {{title}}</div> <ul

    style="list-style-type: none" class="menu"> <li style="margin: 0" :class="{ even: isEven(index), odd: isOdd(index) }" v-for="(item, index) in items"> menu{{index}}: {{item}} </li> </ul> <div class="content"> <p>This is content</p> </div> </div> divɺpɺͦͯ͠ text ཁૉΛ ੩తͳϊʔυͱͯ͠ݕग़
  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', … }] }], … }] }
  33. 2. ੩తͳϊʔυπϦʔͷݕग़ • ੩తͳϊʔυΛࢠͱͯ࣋ͭ͠ϧʔτ(root)ͱͳΔཁૉ͕ ͋Δ͔Ͳ͏͔νΣοΫ͢Δ <div id="app"> <div class="header">title: {{title}}</div>

    <ul style="list-style-type: none" class="menu"> <li style="margin: 0" :class="{ even: isEven(index), odd: isOdd(index) }" v-for="(item, index) in items"> menu{{index}}: {{item}} </li> </ul> <div class="content"> <p>This is content</p> </div> </div> ͜ͷέʔεͰ͸ɺ͜ͷ div ཁૉ͕ ੩తͳϊʔυπϦʔͱͯ͠ݕग़
  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, … }], … } ], … } ] }
  35. ϨϯμϦϯάؔ਺ͷੜ੒

  36. AST ͔ΒϨϯμϦϯάؔ਺Λੜ੒ • ҎԼͷؔ਺Λੜ੒͢Δ • render ؔ਺ • staticRenderFns ؔ਺܊

    (഑ྻ) • ͜ΕΒؔ਺͸ɺVue Πϯελϯ εͷ $options ʹ֨ೲ͞ΕΔ Optimized AST
  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) ]) } ࠷దԽʹΑΓݕग़͞Εͨ੩తͳϊʔυπϦʔͷ෦෼͸ɺ ಺෦ϝιουʹϚοϐϯά
  38. staticRenderFns ؔ਺܊ • ࠷దԽʹΑΓ AST Ͱݕग़ͨ͠੩తͳϊʔυπϦʔ͸ɺ Ծ૝ϊʔυπϦʔͱͯ͠ฦ͢Α͏ʹੜ੒ͨؔ͠਺Λ഑ྻ ʹ֨ೲ͢Δ [ function

    anonymous () { with (this) { return _h('div', { staticClass: 'content' }, [ _h('p', ['This is content']) ]) }} ]
  39. ϨϯμϦϯά

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

  41. Watcher ʹΑΔσʔλมߋͷ؂ࢹ • σʔλґଘؔ܎Λ௥੻͠ɺσʔλมߋΛ؂ࢹ͢Δ • σʔλมߋݕग़ͷ౎౓ɺ Watcher ͸಺෦ͷ _render ϝ

    ιουΛݺͼग़ͯ͠࠶ϨϯμϦϯά const Component = { props: ['msg'], data () { return { title: 'hello', items: […] } }, … } msg data/props Watcher title items 0 x … Collect Dependencies
  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
  43. Ծ૝ϊʔυπϦʔͷΩϟγϡԽͱϚʔΩϯά • staticRenderFns ͷ࣮ߦ݁ՌͰಘΒΕΔ੩తͳԾ૝ϊʔυ πϦʔ͸ɺ࠷ॳͷϨϯμϦϯάͷࡍʹ͜ΕΒ݁ՌΛ Vue Πϯελϯε಺෦ʹΩϟογϡ͢Δ • ͜ͷ࣌ɺԾ૝ϊʔυπϦʔʹ isStatic

    = true ͰϚʔΩϯ ά͢Δ͜ͱͰɺޙͷ Virtual DOM ͷ diff ʹ͓͍ͯεΩο ϓ͞ΕΔ • ࠶ϨϯμϦϯά࣌ʹ͸ɺΩϟογϡԽ͞Εͨ΋ͷΛར༻
  44. Vue ͷ Virtual DOM • Virtual DOM ͸ snabbdom Λ

    fork ͯ͠ಠࣗʹΧελϚΠ ζͨ͠΋ͷ
 https://github.com/snabbdom/snabbdom
  45. Virtual DOM ͷ diff / patch • diff / patch

    ͸جຊ snabbdom ϕʔεͰɺVue ͷ࠷దԽॲ ཧʹΑͬͯ diff ΛεΩοϓ͢Δ͜ͱͰɺDOM Λੜ੒͢Δ ·ͰॲཧίετΛ࡟ݮ https://github.com/vuejs/vue/blob/dev/src/core/vdom/patch.js
  46. Ծ૝ϊʔυπϦʔͷੜ੒͔Β Virtual DOM ʹΑΔॲཧ·Ͱͷ Πϝʔδ

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

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

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

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

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

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

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

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

  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
  56. ͞ΒͳΔ࠷దԽʹ޲͚ͯ

  57. ࠷దԽ߲໨ • ςϯϓϨʔτͷࣄલίϯύΠϧ + ϥϯλΠϜ • v-for ʹΑΔϦετϨϯμϦϯά࣌ʹ͓͚Δ key ଐੑ

    • render ؔ਺ʹΑΔύϑΥʔϚϯενϡʔχϯά࣮૷ • ؔ਺ܕίϯϙʔωϯτ (functional component)
  58. αʔόαΠυϨϯμϦϯά

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

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

    • ͞ΒʹɺϋΠυϨʔγϣϯͷ࢓૊ΈɺΫϥΠΞϯταΠ υͷϥΠϒϥϦͷαʔόαΠυରԠͳͲɺશ෦ಠࣗʹର Ԡ͢Δඞཁ͕͋ͬͨ
  61. Vue 2.0 Ͱ͸؀ڥ͕େ͖͘վળ • Virtual DOM ʹΑΓந৅Խ͞ΕͨϨϯμϦϯά • ϋΠυϨʔγϣϯͷ࢓૊Έ •

    ϢχόʔαϧରԠ͞Εͨެࣜʹఏڙ͢ΔϥΠϒϥϦ • Node.js ޲͚ʹϨϯμϥ • ίϯςΩετʹΑΔႈ౳ੑΛอূ͢ΔϨϯμϦϯά • αʔό޲͚ʹ࠷దԽ͞ΕͨϞδϡʔϧͷόϯυϦϯά
  62. • Vue 2.0 Ҏ߱Ͱ͸ɺҎԼͷެࣜϥΠϒϥϦͱόϯυϦϯ άπʔϧͰɺαʔόαΠυϨϯμϦϯάΛ༰қʹ࣮ݱ͢ Δ͜ͱ͕Ͱ͖Δ ੔ͬͨαʔόαΠυϨϯμϦϯά؀ڥ vue vuex vue-router

    vue-server-renderer Vue library stack + and other …
  63. Vue 2.0 ʹ͓͚Δ αʔόαΠυϨϯμϦϯά ͷྲྀΕʹ͍ͭͯݟ͍͖ͯ·͠ΐ͏ʂ

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

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

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

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

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

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

    • 4. όϯυϦϯά
  70. 1. Ϩϯμϥ

  71. ఏڙ͢ΔϨϯμϥ • Vue ΞϓϦέʔγϣϯΛαʔόαΠυͰϨϯμϦϯά͢ ΔͨΊͷ Node.js ؀ڥͰಈ࡞͢ΔϨϯμϦϯάϞδϡʔ ϧ • Ϩϯμϥ͸ɺࢦఆ͞Εͨ

    Vue ΞϓϦέʔγϣϯͷrender ؔ਺ʹΑͬͯऔಘͨ͠Ծ૝ϊʔυπϦʔΛ walk ͯ͠ HTML จࣈྻͱͯ͠ϨϯμϦϯά
  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) // -> <div server-rendered="true">hello</div> })
  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(`<!DOCTYPE html><html><head><title>...</title></head><body>`) stream.on('data', chunk => { res.write(chunk) }) stream.on('end', () => { res.end('</body></html>') }) })
  74. ΩϟγϡʹΑΔߴ଎Խ • Φϓγϣϯʹ cache ΦϒδΣΫτΛࢦఆ͢Δ͜ͱͰɺί ϯϙʔωϯτͷඳը݁ՌΛΩϟογϯά͢Δ͜ͱʹΑ Γɺ͞ΒͳΔύϑΥʔϚϯεΛ޲্͕Մೳ const LRU =

    require('lru-cache') const renderer = createRenderer({ cache: LRU({ max: 10000 }) })
  75. Ωϟγϡʹ͓͚ΔඞࢸΠϯλʔϑΣΠε • Φϓγϣϯʹ ࢦఆ͢Δ cache ΦϒδΣΫτ͸ɺҎԼͷ ΠϯλʔϑΣΠεΛ࣮૷͍ͯ͠Ε͹ΩϟογϡՄೳ { get: (key:

    string, [cb: Function]) => string | void, set: (key: string, val: string) => void, has?: (key: string, [cb: Function]) => boolean | void // optional }
  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) } } })
  77. ίϯϙʔωϯτͷΩϟογϡ • ίϯϙʔωϯτΛΩϟογϡʹରԠ͢ΔͨΊʹ͸ɺҎ ԼΛ಺༰Λ options ʹؚΊ࣮ͯ૷͢Δඞཁ͕͋Δ • name ΦϓγϣϯʹΑΔϢχʔΫͳίϯϙʔωϯτ໊ •

    serverCacheKey ؔ਺ʹΑͬͯίϯϙʔωϯτຖʹϢ χʔΫͳΩʔΛฦ͢
  78. ྫ: ίϯϙʔωϯτͷΩϟογϡରԠ export default { name: 'item', // required props:

    ['item'], serverCacheKey: props => props.item.id, render (h) { return h('div', this.item.id) } }
  79. ΩϟγϡʹΑΔ෭࡞༻ • ࣍ͷΑ͏ͳؒҧͬͨ࢖͍ํΛ͢ΔͱϨϯμϦϯάपΓͷ όάΛੜΈग़͢ͷͰ஫ҙ͕ඞཁ • άϩʔόϧঢ়ଶʹґଘ͢ΔࢠίϯϙʔωϯτͷΩϟο γϡ • εϩοτΛड͚෇͚ΔίϯϙʔωϯτͷΩϟογϡ

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

    • ϘλϯɺΞϥʔτͳͲͷҰൠతͳ UI ίϯϙʔωϯτ
  81. 2. ϋΠυϨʔγϣϯ

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

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


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

    Render Functions ... <div id="app" server-rendered="true"> ... </div> ... response hydrate JSON new Vue({ … }).$mount(‘#app’) render Virtual Node Tree Rendered DOM Tree window.__initial__ = { …. } checking set $el
  85. • αʔόαΠυͰϨϯμϦϯά͞ΕͨDOMπϦʔΛഁغͯ͠ɺΫϥΠ ΞϯταΠυͰैདྷͷVirtual DOM ͷॲཧϑϩʔͰϨϯμϦϯά αʔόͱΫϥΠΞϯτ͕Ұக͠ͳ͔ͬͨ৔߹ HTTP App (Root vue

    instance) Render Functions ... <div id="app" server-rendered="true"> ... </div> ... response hydrate JSON new Vue({ … }).$mount(‘#app’) Rendered DOM Tree window.__initial__ = { …. } checking render Virtual Node Tree diff + patch
  86. ։ൃϞʔυͱϓϩμΫγϣϯϞʔυͷҧ͍ • ։ൃϞʔυͰ͸ɺΫϥΠΞϯτଆͰੜ੒͞ΕͨԾ૝ϊʔ υπϦʔͷɺαʔόͰϨϯμϦϯά͞ΕͨDOMπϦʔͱ Ұக͍ͯ͠Δ͔Ͳ͏͔ͷݕূॲཧ͸࣮ߦ͢Δ • ϓϩμΫγϣϯϞʔυͰ͸ɺύϑΥʔϚϯεΛ࠷େԽ͢ ΔͨΊʹ͜ͷݕূΛແޮʹ͍ͯ͠Δ

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

    evan!</td></tr> </table> ϒϥ΢β͸ࣗಈతʹ <tbody>Λૠೖ͢Δ Vue͸ςϯϓϨʔτΛίϯύΠϧ͢Δͱ ͦͷߏ଄ͷ·· Virtual-DOM Λੜ੒͢Δ ෆਖ਼ͳ<table>ߏ଄Λ࣋ͬͨ
 ςϯϓϨʔτ
  88. 3. ίϯςΩετ

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

    Εͯ͠·͍ɺϨϯμϦϯά ݁ՌʹѱӨڹΛٴ΅͢
  90. ίϯςΩετʹΑΔԚછͷճආ • ֤ϦΫΤετຖʹίϯςΩετΛ࡞੒ͯ͠ɺͦ͜ʹঢ়ଶ Λઃఆ͢Δ͜ͱͰɺ֤αϯυϘοΫε಺Ͱঢ়ଶ͕อޢ ͞ΕΔ request1 request2 requestX Context Context

    Context vm. runInNewContext vm. runInNewContext vm. runInNewContext
  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 }) }
  92. ίϯςΩετͷಋೖ • Vue ͕ఏڙ͢ΔόϯυϧϨϯμϥʹΑΓίϯςΩετʹ ରԠͨ͠ϨϯμϥΛ࡞੒ const createBundleRenderer = require('vue-server-renderer').createBundleRenderer const

    bundle = require('./dist/server-bundle.js') const rederer = createBundleRenderer(bundle)
  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) }) }) ϨϯμϦϯάͷࡍʹ༻ҙͨ͠Τ ϯτϦϙΠϯτ͕ݺ͹Εͯɺί ϯςΩετ͕౉͞ΕΔ
  94. 4. όϯυϦϯά

  95. αʔό޲͚΁όϯυϧԽ͢Δඞཁੑ • ϦΫΤετຖͷαϯυϘοΫε͸ɺΞϓϦέʔγϣϯ ίʔυΛಈ࡞ͤ͞ΔͱશͯͷґଘϞδϡʔϧ΋ҰॹʹҾ ͖ࠐΜͰಈ࡞͢Δ Node process request request load

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

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

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

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

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

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

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


    
 
 
 
 
 • beforeMount • mounted • beforeUpdate • updated • activated • deactivated • beforeDestroy • destroyed ݺ͹ΕΔϑοΫ ݺ͹Εͳ͍ϑοΫ
  104. ϥΠϑαΠΫϧϑοΫҎ֎ • Ͳͷ API ͕αʔόαΠυͰಈ࡞͢Δ͔Ͳ͏͔͸ɺݫີʹ ͸ॻ͔Ε͍ͯͳ͍ • DOM ʹґଘ͍ͯ͠ͳ͍ܥ౷ͷ΋ͷ͸ɺಈ࡞͢Δ͸ͣ •

    Πϕϯτ: $emit, $off, $on, $once • σʔλܥ: $watch, $set, $delete, $data, ͳͲ • ͦͷଞ΋Ζ΋Ζ …
  105. αʔόαΠυϨϯμϦϯά Example

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

  107. ·ͱΊ

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

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

  110. ͱ͍͏Θ͚Ͱɺ

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

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

  113. Ҏ্ʂ

  114. one more thing …

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

  116. ೔ຊਓ޲͚ Vue.js ίϛϡχςΟ • URL
 https://vuejs-jp-slackin.herokuapp.com • Vue.js ೔ຊޠެࣜαΠτܦ༝Ͱ΋ࢀՃͰ͖·͢
 http://jp.vuejs.org


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