Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
破綻しない Vue.js アプリケーション開発のために大切なこと / How to make ...
Search
potato4d(Takuma HANATANI)
October 15, 2018
Programming
30
10k
破綻しない Vue.js アプリケーション開発のために大切なこと / How to make a robust Vue.js application
2018/10/15 に JSLounge の活動として UUUM株式会社様で行った発表のスライドです。
potato4d(Takuma HANATANI)
October 15, 2018
Tweet
Share
More Decks by potato4d(Takuma HANATANI)
See All by potato4d(Takuma HANATANI)
どうせキレイに書けない処理は逆にAIに書いてもらうほうが良い説 / #kyotojs 22
potato4d
3
330
TSX First な Zero-Runtime SSG potato4d/dodai とその仕組み / owned static site generator #kyotojs
potato4d
1
2.1k
Vue.js with TSX - From Vue 2.x to Vue 3 #v_tokyo11
potato4d
9
4.8k
終わりゆく Vue 2.x 時代の状態設計のアンサー - Vue 3 の Provider への期待 / The Last Architecture of the Vue 2.x
potato4d
25
6.8k
Web Worker を使ってブラウザ上でポケモンの画像を解析したい! / Pokemon recognition from screenshots in browser using web worker
potato4d
0
1.2k
Firebase & Google Cloud によるサーバーレス帳票管理 #FJUG / Serverless Architecture in Candy
potato4d
8
3.6k
NestJS meetup Tokyo Opening Talk / What is NestJS? #nestjs_meetup
potato4d
11
3.9k
私たちはなぜ SPA で開発するのか / Why you choose SPA
potato4d
39
26k
Amplify Console 誕生以来本番運用しつづけてわかったこと #awswakaran_tokyo
potato4d
6
3.4k
Other Decks in Programming
See All in Programming
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
From Translations to Multi Dimension Entities
alexanderschranz
2
130
20年もののレガシープロダクトに 0からPHPStanを入れるまで / phpcon2024
hirobe1999
0
470
RWC 2024 DICOM & ISO/IEC 2022
m_seki
0
210
php-conference-japan-2024
tasuku43
0
280
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
1
440
PSR-15 はあなたのための ものではない? - phpcon2024
myamagishi
0
110
ドメインイベント増えすぎ問題
h0r15h0
2
310
Refactor your code - refactor yourself
xosofox
1
260
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
770
Amazon S3 NYJavaSIG 2024-12-12
sullis
0
100
talk-with-local-llm-with-web-streams-api
kbaba1001
0
180
Featured
See All Featured
Six Lessons from altMBA
skipperchong
27
3.5k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
BBQ
matthewcrist
85
9.4k
Fireside Chat
paigeccino
34
3.1k
Faster Mobile Websites
deanohume
305
30k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
95
17k
Docker and Python
trallard
42
3.1k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
29
2k
Unsuck your backbone
ammeep
669
57k
The Cult of Friendly URLs
andyhume
78
6.1k
Mobile First: as difficult as doing things right
swwweet
222
9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Transcript
ഁ͠ͳ͍ Vue.js ΞϓϦέʔγϣϯ։ൃͷͨΊʹ େͳ͜ͱ 2018.09.15 HANATANI Takuma
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
What's JSLounge produced by ElevenBack ? ΦϑϥΠϯΠϕϯτ ΦϯϥΠϯڭࡐఏڙ اۀ͚ߨश https://jslounge.connpass.com
https://jslounge-archives.elevenback.jp/ https://blog.elevenback.jp
ࠓͷΰʔϧ
ࠓͷΰʔϧ • طଘίʔυͷෛ࠴ • ͍ͭ࡞Γม͑Δ͔ͷΈ • Vue.js ͷΞϯνύλʔϯͷ՝ײ
ࠓͷΰʔϧ • طଘίʔυͷෛ࠴ • ͍ͭ࡞Γม͑Δ͔ͷΈ • Vue.js ͷΞϯνύλʔϯͷ՝ײ • ίʔυͷʮࣺͯͲ͜Ζʯͷཧղ
• ϑϩϯτΤϯυͷ༻ͷѲ • ഁغ͍ͯ͘͜͠ͱΛલఏͱͨ͠ઃܭ
ࠓ͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ༻ʹ͍ͭͯ • Vue.js ͰඞཁΓΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue
CLI / Nuxt.js ʹΑΔഁͮ͠Β͍։ൃڥͷߏங…
ࠓ͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ༻ʹ͍ͭͯ • Vue.js ͰඞཁΓΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue
CLI / Nuxt.js ʹΑΔഁͮ͠Β͍։ൃڥͷߏங
༻ʹ͍ͭͯ • ࣮ࡍͷ։ൃͷγʔϯͰͳ͘ϝϯςφϯεͰ͖Δͷ2,3 ͕ݶ • ΞʔΩςΫνϟϓϩάϥϜͷࢹ͚ͩࡁΉͰͳ͍ • ྫ͑υϝΠϯ֓೦ͷݟ͠ͷै • ྫ͑σβΠϯϦχϡʔΞϧͷै
• ٕज़τϨϯυʹ߹Θͤͨભٶ
υϝΠϯ֓೦ͷݟ͠ • ʮ͜ͷػೳॳ͚͋ͬͨΕͲผػೳʹ౷߹͠Α͏ʯ • ʮҙຯ͢Δͱ͜Ζ͕มΘͬͨͷͰશମΛϦωʔϜ͠Α͏ʯ • ʮআ͠Α͏ʯ
σβΠϯϦχϡʔΞϧͷै • ʮϦϒϥϯσΟϯάͷͨΊʹશମΛϦχϡʔΞϧ͍ͨ͠ʯ • ʮ(ϚςϦΞϧͷΑ͏ͳ)ۀքͷτϨϯυ͕ҠͬͨͷͰ߹Θ͍ͤͨʯ • ʮUIϑϨʔϜϫʔΫϕʔε͚ͩͬͨͲಠࣗʹ͍ͨ͠ʯ
ٕज़τϨϯυʹ߹Θͤͨมભ • Vue.js 1.0 3 લɺ Vue.js 2.0
2 લɺ࣍ͷ v3 …… • ʮݹ͘ͳΔͱใ૿͑ͣศརͳͷ͑ͳ͍ʯ • ʮՄೳͰ͋Ε࣌ؒΛͱͬͯ࠷ݶϝδϟʔ͍͋͛ͨʯ
ٕज़τϨϯυʹ߹Θͤͨมભ • খ͞ͳτϨϯυ୯ҐͰτϨϯυมΘΔ • ࣌ࠁૢ࡞ day.js ͕ moment ͷΘΓʹͳ͍ͬͯΔ͔ •
HTTP ௨৴ XHR ͳ axios Ͱͳ͘ fetch ϕʔεͷͷ͔
࠷ऴతʹΔͷ……ʁ ✘ Vue.js UI ʹܹ͘͠ґଘͨ͠෦ ✘ Build environment ✘
ྲྀߦΓͷϥΠϒϥϦʹΑ࣮ͬͯ͞Εͨ෦ ✘ υϝΠϯશҬ(ഽײίʔυϕʔεͷ6ׂఔҠ২Մೳ) ˕ ϓϩδΣΫτʹ͋Θ͍ͤͨΘΏΔʮϢʔςΟϦςΟʯ ˕ ൚༻తͳ(Ξφϯε௨ͳͲͷ)ίϯϙʔωϯτͷϩδοΫ
࠷ऴతʹΔͷ……ʁ ͍͚ͬͯΔͷࣝͱܦݧ มΘΔ͜ͱΛલఏʹʮࣺ͍ͯ͢ʯίʔυΛ࡞Δ = ϑϩϯτΤϯυϩʔάϥΠΫ
ࠓ͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ༻ʹ͍ͭͯ • Vue.js ͰඞཁΓΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue
CLI / Nuxt.js ʹΑΔഁͮ͠Β͍։ൃڥͷߏங…
جຊతͳߟ͑ํ ʮࣺ͍ͯ͢ʯίʔυͷͨΊʹ…… 1. ʮ࠶ར༻ੑʯͷແؔ৺ͱݻࣥಟ 2. VuexԿͷͨΊʹ͋Δ͔Λߟ͑Δ 3. Vue.js ͓Αͼ SFC
ʹͩ͜ΘΓ͗͢ͳ͍ ͜͜Ͱ֓೦ͷΈɺ࣮ྫ࣍ͷηΫγϣϯͰɹ⾣
ʮ࠶ར༻ੑʯͷແؔ৺ͱݻࣥಟ • ͷଟ͍ίʔυ·ͱΊͯഁغ͢Δඞཁ͕ग़ͯ͘Δ • ͔ͱݴͬͯ Vuex ͳͲͷάϩʔόϧͳσʔλʹ҆қʹґଘ͢Δ ͱࠜຊతͳվमʹ͑ΒΕͳ͍ • ϓϨθϯςʔγϣϯͷͨΊ͚ͩͷσʔλ൚༻ੑΛٻΊΔ
• ϩδοΫ୯ମͰՄೳͳݶΓബ͘ॻ͘ • ͳͲͳͲ……
Vuex ͳΜͷͨΊʹ͋Δ͔Λߟ͑Δ • શͯͷσʔλΛೖΕͯ͠·͏ͱͦΕͨͩͷάϩʔόϧม • ϩʔΧϧεςʔτͱ͏·͍͚͘Δ • Vuex Λͨͩͷശͱͯ͠ஔ͘ͷ͔ɺϦΞΫςΟϒͳυϝΠϯϨ ΠϠʔΛߏங͢Δج൫ͱ͢Δͷ͔Λ͖ͬΓͤ͞Δ
• ͳͲͳͲ……
Vue.js / SFC ʹͩ͜ΘΓ͗͢ͳ͍ • Vue.js ͔ͩΒͱ͍ͬͯશͯΛ .vue Ͱ݁ͤ͞Δඞཁͳ͍ •
SFC Vue Test Utils Λར༻ͨ͠είʔϓͷେ͖͍ςετͳͲ ͕ඞཁʹͳΔͷͰඞવੑͷ͋Δ͚ͩΛͨͤΔ • ͋ͱ VanillaJS ʹΑΔهड़Λ৺͕͚Δ • ৄ࣍͘͠ͷηΫγϣϯͰ
ࠓ͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ༻ʹ͍ͭͯ • Vue.js ͰඞཁΓΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue
CLI / Nuxt.js ʹΑΔഁͮ͠Β͍։ൃڥͷߏங
࠶ར༻ੑͷײ֮ͷζϨ
͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <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
͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <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
վળྫ <template> <button @click="like">Like</button> </template> <script> export default { methods:
{ click(event) { this.$emit('click', event) } } } </script> Vue.js ͷΠϕϯτγεςϜΛͬͯΛബ͘ -JLF#VUUPOWVF
͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <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
͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ <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
վળྫ <template> <div class=“some-form”> <template> <div> <!-— code --> </div>
</template> </div> </template> <script> export default { } </script> 6TFS$SFBUF'PSNWVF ʹͳͬͯͦΕͧΕผͷίʔυʹ͢Δ
վળྫ <template> <div class=“some-form”> <template> <div> <!-— code --> </div>
</template> </div> </template> <script> export default { } </script> 6TFS&EJU'PSNWVF ผͷίʔυʹ͓ͯ͘͠ͱʮߋ৽ෆՄʯͷ߲ͷ࣮༰қ
VuexʹدͤΔ͖ίʔυͱ دͤΔ͖Ͱͳ͍ίʔυ
͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ import { mapGetters, mapActions } from 'vuex' export default
{ computed: { ...mapGetters('entries', { form: 'editEntry' }) }, methods: { ...mapActions('entries', ['updateEditEntry', 'updateEntry']) } } &OUSZ&EJU'PSNWVF
͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ 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 ͮ͠Β͘ͳ͍ͬͯΔ
͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ /* ... 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 ʹԿނ͔ϑΥʔϜͷঢ়ଶ͕
मਖ਼ྫ 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. ೖྗ͕Ωϟϯηϧ͞Εͨ߹ίϯϙʔωϯτͷϥΠϑαΠΫϧʹΑͬͯదʹഁغ
मਖ਼ྫ /* ... state code ... */ const getters =
{ entries: [] } /* ... mutation code ... */ const actions = { updateEntry() {} // ࣮ࡍͷσʔλͷߋ৽͚ͩΛߦ͏ } export default { namespaced: true, state, mutations, getters, actions } FOUSJFTKT Vuex ࣮σʔλʹͷΈઐ೦Ͱ͖ɺ͔ͭԼखʹϦηοτॲཧΛॻ͔ͳ͍Ͱྑ͍Α͏ʹ
Single File Component vs VanillaJS
͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ <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
͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ <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
मਖ਼ྫ function convert(args) { return {...args} } export default convert
VUJMTDPOWFSUFSKT JavaScript ͚ͩͰ݁͢Δ෦ JavaScriptͰΓग़͢
मਖ਼ྫ import convert from './converter' describe('converter.js', () => { test('test
code', () => { const input = { val1: '', val2: '' } expect(convert(input)).toMatchObject(input) }) }) TQFDVUJMTDPOWFSUFSTQFDKT JavaScript Ͱॻ͘͜ͱͰςετίʔυهड़͘͢͠
ࠓ͢͜ͱ • ݱࡏͷϑϩϯτΤϯυΞϓϦέʔγϣϯͷ༻ʹ͍ͭͯ • Vue.js ͰඞཁΓΔͨΊʹඞཁͳجຊతͳߟ͑ํ • ࣮ྫ͔ΒֶͿϝϯςφϏϦςΟΛԼ͛Δίʔυͱઃܭ • Vue
CLI / Nuxt.js ʹΑΔഁͮ͠Β͍։ൃڥͷߏங…
Vue CLI v3 • Vue.js ۘͷ CLI πʔϧ • طଘͷڥ(ࣗྗͰ
webpack Λ৮Δڥ)͔ΒҠߦ͍͢͠ • CLIπʔϧͷԆΒ͍͠ػೳ͕๛ • ϓϥάΠϯʹΑΔڥͷڧԽ͕༰қ • ϓϥάΠϯʹΑΔڥͷߏங͕༰қ • ίϚϯυҰൃͰςετڥͳͲΛ࡞Մೳ • ։ൃମݧͱͯ͠ڥճΓΛڧԽ͢Δཁૉ͕ڧ͍
7VFKT1SPKFDU 5FTUJOH Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551
6UJMJUZ CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU
7VF$-*W1SPKFDU 7VF$-*4FSWJDF 5FTUJOH Vue CLI v3 ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY
7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551 6UJMJUZ
Nuxt.js • Vue.js ͔ΒݟΔ߹ඇެࣜͷϑϨʔϜϫʔΫ • Vue.js ͷίϛϡχςΟύʔτφʔͱͳͬͨͷͰڠྗؔͰ͋Δ • ϑϨʔϜϫʔΫΒ͍͠ػೳΛఏڙ͢Δ •
ಠࣗͷϞδϡʔϧϓϥάΠϯγεςϜ • ΦʔτϩʔσΟϯάܥͷػೳ SSR ͷσϑΥϧταϙʔτ • ϓϩδΣΫτͷجຊઃܭΛ Nuxt.js ʹͤΔ͜ͱ͕Ͱ͖Δ • ։ൃମݧͱͯ͠ϓϩδΣΫτઃܭΛڧԽ͢Δཁૉ͕ڧ͍
7VFKT1SPKFDU 5FTUJOH Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF )551
6UJMJUZ CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU CVJMEFOWJSPONFOU
/VYUKT1SPKFDU 5FTUJOH /VYUKT Nuxt.jsΛ༗ޮ׆༻͢Δ 7VFKT 7VF3PVUFS 7VFY 7VF5FTU6UJMT 1VSF+BWB4DSJQU &YUFSOBM4FSWJDF
)551 6UJMJUZ webpack vue-meta vue-server-renderer Project structure
Vue CLI v3 or Nuxt.js • ར༻Ϟνϕʔγϣϯ͔Βͯ͠ҧ͏ͷͰҰ֓ʹൺֱతͰ͖ͳ͍ • ݸਓతʹ Vue.js
ͷϏΪφʔ͕গͳ͍߹ Nuxt.js Λਪ • ͍͖ͳΓ Nuxt.js Λ৮Δͷϋʔυϧ͕ߴ͍ͷͰඇਪ • ͋Δఔ׳Εͨਓ͕ Nuxt.js ͰҰ௨ΓΜͰ͠·͑ϏΪφʔ͕͋ ͱ͔ΒೖͬͯյΕͳ͍Α͏ͳઃܭ͕Ͱ͖Δ • ͲͷΈͪ 2 ఔͷεύϯͰߟ͑ΔͳΒϨʔϧʹͬͯߴ͍ੜ࢈ ੑΛಘͨ΄͏͕ϓϩδΣΫτΛυϥΠϒͰ͖Δ
thanks!