Pro Yearly is on sale from $80 to $50! »

破綻しない Vue.js アプリケーション開発のために大切なこと / How to make a robust Vue.js application

破綻しない Vue.js アプリケーション開発のために大切なこと / How to make a robust Vue.js application

2018/10/15 に JSLounge の活動として UUUM株式会社様で行った発表のスライドです。

A54b31d4ebbce222dff88a5c42bac033?s=128

Potato4d(Hanatani Takuma)

October 15, 2018
Tweet

Transcript

  1. ഁ୼͠ͳ͍ Vue.js ΞϓϦέʔγϣϯ։ൃͷͨΊʹ େ੾ͳ͜ͱ 2018.09.15 HANATANI Takuma

  2. Profile • Ֆ୩ ୓ຏ as known as potato4d • Vue.js

    / Nuxt.js Japanese Document • Translator / maintainer • Vue.js Japan user group • Staff / Vue Fes Japan 2018 staff • Nuxt.js beginners guide author
  3. What's JSLounge produced by ElevenBack ? ΦϑϥΠϯΠϕϯτ ΦϯϥΠϯڭࡐఏڙ اۀ޲͚ߨश https://jslounge.connpass.com

    https://jslounge-archives.elevenback.jp/ https://blog.elevenback.jp
  4. ࠓ೔ͷΰʔϧ

  5. ࠓ೔ͷΰʔϧ • طଘίʔυͷෛ࠴ • ͍ͭ࡞Γม͑Δ͔ͷ೰Έ • Vue.js ͷΞϯνύλʔϯ΁ͷ՝୊ײ

  6. ࠓ೔ͷΰʔϧ • طଘίʔυͷෛ࠴ • ͍ͭ࡞Γม͑Δ͔ͷ೰Έ • Vue.js ͷΞϯνύλʔϯ΁ͷ՝୊ײ • ίʔυͷʮࣺͯͲ͜Ζʯ΁ͷཧղ

    • ϑϩϯτΤϯυͷ଱༻೥਺ͷ೺Ѳ • ഁغ͍ͯ͘͜͠ͱΛલఏͱͨ͠ઃܭ
  7. ࠓ೔࿩͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ଱༻೥਺ʹ͍ͭͯ • Vue.js Ͱඞཁ೥਺૸Γ੾ΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue

    CLI / Nuxt.js ʹΑΔഁ୼ͮ͠Β͍։ൃ؀ڥͷߏங…
  8. ࠓ೔࿩͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ଱༻೥਺ʹ͍ͭͯ • Vue.js Ͱඞཁ೥਺૸Γ੾ΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue

    CLI / Nuxt.js ʹΑΔഁ୼ͮ͠Β͍։ൃ؀ڥͷߏங
  9. ଱༻೥਺ʹ͍ͭͯ • ࣮ࡍͷ։ൃͷγʔϯͰ͸໰୊ͳ͘ϝϯςφϯεͰ͖Δͷ͸2,3 ೥͕ݶ౓ • ΞʔΩςΫνϟ΍ϓϩάϥϜͷࢹ఺͚ͩࡁΉ໰୊Ͱ͸ͳ͍ • ྫ͑͹υϝΠϯ֓೦ͷݟ௚͠΁ͷ௥ै • ྫ͑͹σβΠϯϦχϡʔΞϧ΁ͷ௥ै

    • ٕज़τϨϯυʹ߹Θͤͨભٶ
  10. υϝΠϯ֓೦ͷݟ௚͠ • ʮ͜ͷػೳ͸౰ॳ͸͚͋ͬͨΕͲผػೳʹ౷߹͠Α͏ʯ • ʮҙຯ͢Δͱ͜Ζ͕มΘͬͨͷͰશମΛϦωʔϜ͠Α͏ʯ • ʮ࡟আ͠Α͏ʯ

  11. σβΠϯϦχϡʔΞϧ΁ͷ௥ै • ʮϦϒϥϯσΟϯάͷͨΊʹશମΛϦχϡʔΞϧ͍ͨ͠ʯ • ʮ(ϚςϦΞϧͷΑ͏ͳ)ۀքͷτϨϯυ͕ҠͬͨͷͰ߹Θ͍ͤͨʯ • ʮUIϑϨʔϜϫʔΫϕʔε͚ͩͬͨͲಠࣗʹ͍ͨ͠ʯ

  12. ٕज़τϨϯυʹ߹Θͤͨมભ • Vue.js 1.0 ͸ 3 ೥લɺ Vue.js 2.0 ͸

    2 ೥લɺ࣍ͷ v3 ͸…… • ʮݹ͘ͳΔͱ৘ใ΋૿͑ͣศརͳ΋ͷ΋࢖͑ͳ͍ʯ • ʮՄೳͰ͋Ε͹࣌ؒΛͱͬͯ΋࠷௿ݶϝδϟʔ͸͍͋͛ͨʯ
  13. ٕज़τϨϯυʹ߹Θͤͨมભ • খ͞ͳτϨϯυ୯ҐͰ΋τϨϯυ͸มΘΔ • ࣌ࠁૢ࡞͸ day.js ͕ moment ͷ୅ΘΓʹͳ͍ͬͯΔ͔΋ •

    HTTP ௨৴΋ XHR ͳ axios Ͱ͸ͳ͘ fetch ϕʔεͷ΋ͷ͔΋
  14. ࠷ऴతʹ࢒Δͷ͸……ʁ ✘ Vue.js ΍ UI ʹܹ͘͠ґଘͨ͠෦෼ ✘ Build environment ✘

    ྲྀߦΓͷϥΠϒϥϦʹΑ࣮ͬͯ૷͞Εͨ෦෼ ✘ υϝΠϯશҬ(ഽײίʔυϕʔεͷ6ׂఔ౓͸Ҡ২Մೳ) ˕ ϓϩδΣΫτʹ͋Θ͍ͤͨΘΏΔʮϢʔςΟϦςΟʯ ˕ ൚༻తͳ(Ξφ΢ϯε΍௨஌ͳͲͷ)ίϯϙʔωϯτͷϩδοΫ
  15. ࠷ऴతʹ࢒Δͷ͸……ʁ ΋͍͚ͬͯΔͷ͸஌ࣝͱܦݧ มΘΔ͜ͱΛલఏʹʮࣺͯ΍͍͢ʯίʔυΛ࡞Δ = ϑϩϯτΤϯυ͸ϩʔάϥΠΫ

  16. ࠓ೔࿩͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ଱༻೥਺ʹ͍ͭͯ • Vue.js Ͱඞཁ೥਺૸Γ੾ΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue

    CLI / Nuxt.js ʹΑΔഁ୼ͮ͠Β͍։ൃ؀ڥͷߏங…
  17. جຊతͳߟ͑ํ ʮࣺͯ΍͍͢ʯίʔυͷͨΊʹ…… 1. ʮ࠶ར༻ੑʯ΁ͷແؔ৺ͱݻࣥ͸ಟ 2. Vuex͸ԿͷͨΊʹ͋Δ͔Λߟ͑Δ 3. Vue.js ͓Αͼ SFC

    ʹͩ͜ΘΓ͗͢ͳ͍ ͜͜Ͱ͸֓೦ͷΈɺ࣮ྫ͸࣍ͷηΫγϣϯͰɹ⾣
  18. ʮ࠶ར༻ੑʯ΁ͷແؔ৺ͱݻࣥ͸ಟ • ੹຿ͷଟ͍ίʔυ͸·ͱΊͯഁغ͢Δඞཁ͕ग़ͯ͘Δ • ͔ͱݴͬͯ Vuex ͳͲͷάϩʔόϧͳσʔλʹ҆қʹґଘ͢Δ ͱࠜຊతͳվमʹ଱͑ΒΕͳ͍ • ϓϨθϯςʔγϣϯ૚ͷͨΊ͚ͩͷσʔλ͸൚༻ੑΛٻΊΔ

    • ϩδοΫ͸୯ମͰ͸ՄೳͳݶΓബ͘ॻ͘ • ͳͲͳͲ……
  19. Vuex ͸ͳΜͷͨΊʹ͋Δ͔Λߟ͑Δ • શͯͷσʔλΛೖΕͯ͠·͏ͱͦΕ͸ͨͩͷάϩʔόϧม਺ • ϩʔΧϧεςʔτͱ͏·͘࢖͍෼͚Δ • Vuex Λͨͩͷശͱͯ͠ஔ͘ͷ͔ɺϦΞΫςΟϒͳυϝΠϯϨ ΠϠʔΛߏங͢Δج൫ͱ͢Δͷ͔Λ͸͖ͬΓͤ͞Δ

    • ͳͲͳͲ……
  20. Vue.js / SFC ʹͩ͜ΘΓ͗͢ͳ͍ • Vue.js ͔ͩΒͱ͍ͬͯશͯΛ .vue Ͱ׬݁ͤ͞Δඞཁ͸ͳ͍ •

    SFC ͸ Vue Test Utils Λར༻ͨ͠είʔϓͷେ͖͍ςετͳͲ ͕ඞཁʹͳΔͷͰඞવੑͷ͋Δ੹຿͚ͩΛ΋ͨͤΔ • ͋ͱ͸ VanillaJS ʹΑΔهड़Λ৺͕͚Δ • ৄ͘͠͸࣍ͷηΫγϣϯͰ
  21. ࠓ೔࿩͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ଱༻೥਺ʹ͍ͭͯ • Vue.js Ͱඞཁ೥਺૸Γ੾ΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue

    CLI / Nuxt.js ʹΑΔഁ୼ͮ͠Β͍։ൃ؀ڥͷߏங
  22. ࠶ར༻ੑͷײ֮஋ͷζϨ

  23. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <template> <button @click=“like”>Like</button> </template> <script> import { mapActions }

    from ‘vuex’ export default { props: { id: Number }, methods: { click() { this.like({ id }) }, .. .mapActions(‘entries’, [‘like’])
 }
 } </script> -JLF#VUUPOWVF
  24. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <template> <button @click=“like”>Like</button> </template> <script> import { mapActions }

    from ‘vuex’ export default { props: { id: Number }, methods: { click() { this.like({ id }) }, .. .mapActions(‘entries’, [‘like’])
 }
 } </script> Atoms ૬౰ͷϞϊ͕ Vuex ʹґଘ͍ͯ͠Δ -JLF#VUUPOWVF
  25. վળྫ <template> <button @click="like">Like</button> </template> <script> export default { methods:

    { click(event) { this.$emit('click', event) } }
 } </script> Vue.js ͷΠϕϯτγεςϜΛ࢖ͬͯ੹຿Λബ͘ -JLF#VUUPOWVF
  26. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <template> <div class=“some-form”> <template v-if=“mode === ‘new’”> <div></div> </template>

    <template v-if=“mode === ‘edit’”> <div></div> </template> <!-— code --> </div> </template> <script> export default { props: { mode: String } } </script> 6TFS'PSNWVF
  27. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <template> <div class=“some-form”> <template v-if=“mode === ‘new’”> <div></div> </template>

    <template v-if=“mode === ‘edit’”> <div></div> </template> <!-— code --> </div> </template> <script> export default { props: { mode: String } } </script> ίϯϙʔωϯτʹೋͭҎ্ͷ໾ׂ͕͋Δ 6TFS'PSNWVF
  28. վળྫ <template> <div class=“some-form”> <template> <div> <!-— code --> </div>

    </template> </div> </template> <script> export default { } </script> 6TFS$SFBUF'PSNWVF ৑௕ʹͳͬͯ΋ͦΕͧΕผͷίʔυʹ͢Δ
  29. վળྫ <template> <div class=“some-form”> <template> <div> <!-— code --> </div>

    </template> </div> </template> <script> export default { } </script> 6TFS&EJU'PSNWVF ผͷίʔυʹ͓ͯ͘͠ͱʮߋ৽ෆՄʯͷ߲໨ͷ࣮૷΋༰қ
  30. VuexʹدͤΔ΂͖ίʔυͱ دͤΔ΂͖Ͱ͸ͳ͍ίʔυ

  31. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ import { mapGetters, mapActions } from 'vuex' export default

    { computed: { ...mapGetters('entries', { form: 'editEntry' })
 }, methods: { ...mapActions('entries', ['updateEditEntry', 'updateEntry']) } } &OUSZ&EJU'PSNWVF
  32. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ import { mapGetters, mapActions } from 'vuex' export default

    { computed: { ...mapGetters('entries', { form: 'editEntry' })
 }, methods: { ...mapActions('entries', ['updateEditEntry', 'updateEntry']) } } &OUSZ&EJU'PSNWVF 1. ίϯϙʔωϯτ͚͕ͩ஌͍ͬͯΕ͹ྑ͍தؒঢ়ଶʹVuexΛ࢖͍ͬͯΔ 2. Vuex ͷ mapXXX ͷΤΠϦΞεػೳͷ͍ͤͰ grep ͮ͠Β͘ͳ͍ͬͯΔ
  33. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ /* ... state code ... */ const getters =

    { entries: [], editEntry: null } /* ... mutation code ... */ const actions = { // ... other actions updateEditEntry({ commit }, { formData }) {commit('updateEditEntry', formData)} } export default { namespaced: true, state, mutations, getters, actions } FOUSJFTKT υϝΠϯ֓೦͕ೖ͍ͬͯΔ͸ͣͷ entries ʹԿނ͔ϑΥʔϜͷঢ়ଶ͕
  34. मਖ਼ྫ import { mapGetters, mapActions } from 'vuex' export default

    { data() { const form = this.entries.find((e) => e.id == this.$route.params.id)) return { form
 } }, computed: { ...mapGetters('entries', ['entries'])
 }, methods: { ...mapActions('entries', ['updateEntry']) } } &OUSZ&EJU'PSNWVF 1. தؒঢ়ଶ͸ϩʔΧϧεςʔτʹด͡ࠐΊͯ Vuex ʹΰϛσʔλ͕࢒Βͳ͍Α͏ʹ 2. ೖྗ͕Ωϟϯηϧ͞Εͨ৔߹΋ίϯϙʔωϯτͷϥΠϑαΠΫϧʹΑͬͯద੾ʹഁغ
  35. मਖ਼ྫ /* ... state code ... */ const getters =

    { entries: [] } /* ... mutation code ... */ const actions = { updateEntry() {} // ࣮ࡍͷσʔλͷߋ৽͚ͩΛߦ͏ } export default { namespaced: true, state, mutations, getters, actions } FOUSJFTKT Vuex ͸࣮σʔλʹͷΈઐ೦Ͱ͖ɺ͔ͭԼखʹϦηοτॲཧΛॻ͔ͳ͍Ͱྑ͍Α͏ʹ
  36. Single File Component vs VanillaJS

  37. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ <script> export default { data() { return { formData:

    { val1: '', val2: '' }, status: '' } // ద౰ͳঢ়ଶ
 } methods: { handleAction() {
 const foo = this.covert({…this.formData}) this.$store.dispatch('namespace/someAction', foo)
 }, convert(args) { return {...args} // Կ͔͠ΒͷॲཧΛߦͬͨޙʹฦ٫ } } } .Z$PNQPOFOUWVF
  38. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ <script> export default { data() { return { formData:

    { val1: '', val2: '' }, status: '' } // ద౰ͳঢ়ଶ
 } methods: { handleAction() {
 const foo = this.covert({…this.formData}) this.$store.dispatch('namespace/someAction', foo)
 }, convert(args) { return {...args} // Կ͔͠ΒͷॲཧΛߦͬͨޙʹฦ٫ } } } ୯ҰϑΝΠϧίϯϙʔωϯτͰ΋ͭඞཁͷͳ͍ॲཧ͕ଘࡏ͢Δ (ಛʹෳ਺ͷίϯϙʔωϯτͰग़ݱ͢Δ৔߹) .Z$PNQPOFOUWVF
  39. मਖ਼ྫ function convert(args) { return {...args}
 } export default convert

    VUJMTDPOWFSUFSKT JavaScript ͚ͩͰ׬݁͢Δ෦෼͸ JavaScriptͰ੾Γग़͢
  40. मਖ਼ྫ import convert from './converter' describe('converter.js', () => { test('test

    code', () => { const input = { val1: '', val2: '' } expect(convert(input)).toMatchObject(input) }) }) TQFDVUJMTDPOWFSUFSTQFDKT JavaScript Ͱॻ͘͜ͱͰςετίʔυ΋هड़͠΍͘͢
  41. ࠓ೔࿩͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ଱༻೥਺ʹ͍ͭͯ • Vue.js Ͱඞཁ೥਺૸Γ੾ΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue

    CLI / Nuxt.js ʹΑΔഁ୼ͮ͠Β͍։ൃ؀ڥͷߏங…
  42. Vue CLI v3 • Vue.js ۘ੡ͷ CLI πʔϧ • طଘͷ؀ڥ(ࣗྗͰ

    webpack Λ৮Δ؀ڥ)͔Β΋Ҡߦ͠΍͍͢ • CLIπʔϧͷԆ௕Β͍͠ػೳ͕๛෋ • ϓϥάΠϯʹΑΔ؀ڥͷڧԽ͕༰қ • ϓϥάΠϯʹΑΔ؀ڥͷߏங͕༰қ • ίϚϯυҰൃͰςετ؀ڥͳͲΛ࡞੒Մೳ • ։ൃମݧͱͯ͠͸؀ڥ΍଍ճΓΛڧԽ͢Δཁૉ͕ڧ͍
  43. 7VFKT1SPKFDU 5FTUJOH Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551

    6UJMJUZ CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU
  44. 7VF$-*W1SPKFDU 7VF$-*4FSWJDF 5FTUJOH Vue CLI v3 ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY

    7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551 6UJMJUZ
  45. Nuxt.js • Vue.js ͔ΒݟΔ৔߹͸ඇެࣜͷϑϨʔϜϫʔΫ • Vue.js ͷίϛϡχςΟύʔτφʔͱͳͬͨͷͰڠྗؔ܎Ͱ͸͋Δ • ϑϨʔϜϫʔΫΒ͍͠ػೳΛఏڙ͢Δ •

    ಠࣗͷϞδϡʔϧ΍ϓϥάΠϯγεςϜ • ΦʔτϩʔσΟϯάܥͷػೳ΍ SSR ͷσϑΥϧταϙʔτ • ϓϩδΣΫτͷجຊઃܭΛ Nuxt.js ʹ೚ͤΔ͜ͱ͕Ͱ͖Δ • ։ൃମݧͱͯ͠͸ϓϩδΣΫτઃܭΛڧԽ͢Δཁૉ͕ڧ͍
  46. 7VFKT1SPKFDU 5FTUJOH Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551

    6UJMJUZ CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU
  47. /VYUKT1SPKFDU 5FTUJOH /VYUKT Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF

    )551 6UJMJUZ webpack vue-meta vue-server-renderer Project structure
  48. Vue CLI v3 or Nuxt.js • ར༻Ϟνϕʔγϣϯ͔Βͯ͠ҧ͏ͷͰҰ֓ʹ͸ൺֱతͰ͖ͳ͍ • ݸਓతʹ͸ Vue.js

    ͷϏΪφʔ͕গͳ͍৔߹͸ Nuxt.js Λਪ঑ • ͍͖ͳΓ Nuxt.js Λ৮Δͷ͸ϋʔυϧ͕ߴ͍ͷͰඇਪ঑ • ͋Δఔ౓׳Εͨਓ͕ Nuxt.js ͰҰ௨Γ૊ΜͰ͠·͑͹ϏΪφʔ͕͋ ͱ͔Βೖͬͯ΋յΕͳ͍Α͏ͳઃܭ͕Ͱ͖Δ • ͲͷΈͪ 2 ೥ఔ౓ͷεύϯͰߟ͑ΔͳΒϨʔϧʹ৐ͬͯߴ͍ੜ࢈ ੑΛಘͨ΄͏͕ϓϩδΣΫτΛυϥΠϒͰ͖Δ
  49. thanks!