Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

ࣗݾ঺հ

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Vue.js ͱ͸ʁ

Slide 7

Slide 7 text

࡞ऀ Evan You ※ ࡞ऀͷΠϯλϏϡʔهࣄ: Between the Wires | Evan You
 https://betweenthewires.org/between-the-wires-evan-you-cb56660bc8a4#.6b0vzpgzw ※ ࡞ऀͷαΠτ
 http://evanyou.me

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

※ 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 ຊମ

Slide 10

Slide 10 text

• 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

Slide 11

Slide 11 text

2.0 Ͱͷେ͖͍มߋ

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Virtual DOM ʹΑΔޮೳ

Slide 14

Slide 14 text

ϨϯμϦϯάͷߴ଎Խ ※ The Vue Point: Vue 2.0 is Here (Vue.js ެࣜϒϩά)
 https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.v9xl2x8f7

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

ΞδΣϯμ

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

ϨϯμϦϯάγεςϜ

Slide 21

Slide 21 text

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

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

ίϯύΠϧ

Slide 26

Slide 26 text

ςϯϓϨʔτΛ 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

Slide 27

Slide 27 text

ςϯϓϨʔτύʔα • ςϯϓϨʔτύʔα͸ɺJohn Resig ࢯ੡ͷ΋ͷΛ fork ͠ ͯ Vue ޲͚ʹಠࣗʹΧελϚΠζ ※ ςϯϓϨʔτύʔα
 https://github.com/vuejs/vue/blob/dev/src/compiler/parser/html-parser.js ES2015 Ͱ re-write & ࠷దԽ

Slide 28

Slide 28 text

࠷దԽ

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

• Virtual DOM ʹΑΔϨϯμϦϯάͷύϑΥʔϚϯεΛΑ ͘͢ΔͨΊʹɺVue Ͱ͸ AST ʹରͯ͠ҎԼͷ̎ஈ֊ͷॲ ཧΛͯ͠࠷దԽ͢Δ
 
 1. ੩తͳϊʔυͷݕग़
 2. ੩తͳϊʔυπϦʔͷݕग़ AST ʹର͢Δ࠷దԽॲཧ

Slide 31

Slide 31 text

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

This is content

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

Slide 32

Slide 32 text

• ݕग़͞Εͨϊʔυ͸ɺ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', … }] }], … }] }

Slide 33

Slide 33 text

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

This is content

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

Slide 34

Slide 34 text

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, … }], … } ], … } ] }

Slide 35

Slide 35 text

ϨϯμϦϯάؔ਺ͷੜ੒

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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) ]) } ࠷దԽʹΑΓݕग़͞Εͨ੩తͳϊʔυπϦʔͷ෦෼͸ɺ ಺෦ϝιουʹϚοϐϯά

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

ϨϯμϦϯά

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Ծ૝ϊʔυπϦʔͷੜ੒ • 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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

͞ΒͳΔ࠷దԽʹ޲͚ͯ

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

1. Ϩϯμϥ

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

جຊతͳ࢖͍ํ • 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
})

Slide 73

Slide 73 text

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('') }) })

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

ྫ: 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) } } })

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

2. ϋΠυϨʔγϣϯ

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

Vue ͷੈքͰ͸ʁ • ࡶʹ͍͏ͱʮhydration: ঢ়ଶิڅʯ • DOM ͕ঢ়ଶ (JSON) Λิڅͯ͠
 ظ଴͢΂͖࢟ʹͳΔ͜ͱ DOM

Slide 84

Slide 84 text

• αʔόαΠυͰϨϯμϦϯά͞Εͨ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

Slide 85

Slide 85 text

• αʔόαΠυͰϨϯμϦϯά͞Εͨ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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

ϋΠυϨʔγϣϯͷ஫ҙࣄ߲ • αʔόαΠυϨϯμϦϯάͱΫϥΠΞϯτͷϋΠυϨʔ γϣϯʹ͓͍ͯɺValid ͳߏ଄Λͨ͠ HTML Λهࡌ͠ͳ ͍ͱෆҰக͕ൃੜ͢Δ hi evan! ϒϥ΢β͸ࣗಈతʹ Λૠೖ͢Δ Vue͸ςϯϓϨʔτΛίϯύΠϧ͢Δͱ ͦͷߏ଄ͷ·· Virtual-DOM Λੜ੒͢Δ ෆਖ਼ͳߏ଄Λ࣋ͬͨ
 ςϯϓϨʔτ

Slide 88

Slide 88 text

3. ίϯςΩετ

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

ίϯςΩετͷಋೖ • αʔό޲͚ͷ 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 }) }

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

ίϯςΩετͷಋೖ • ϦΫΤετϋϯυϥ಺ͰίϯςΩετΛ࡞੒͠ɺϨϯμ ϥͷϨϯμϦϯάϝιουʹࢦఆ࣮ͯ͠ߦ // 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) }) }) ϨϯμϦϯάͷࡍʹ༻ҙͨ͠Τ ϯτϦϙΠϯτ͕ݺ͹Εͯɺί ϯςΩετ͕౉͞ΕΔ

Slide 94

Slide 94 text

4. όϯυϦϯά

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

αʔό޲͚ͷόϯυϧԽ (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) }

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

ϥΠϑαΠΫϧϑοΫ • beforeCreate • created
 
 
 
 
 
 
 
 
 
 
 • beforeMount • mounted • beforeUpdate • updated • activated • deactivated • beforeDestroy • destroyed ݺ͹ΕΔϑοΫ ݺ͹Εͳ͍ϑοΫ

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

·ͱΊ

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

ͱ͍͏Θ͚Ͱɺ

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

Ҏ্ʂ

Slide 114

Slide 114 text

one more thing …

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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


Slide 117

Slide 117 text

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