Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
破綻しない Vue.js アプリケーション開発のために大切なこと / How to make ...
Search
potato4d(Takuma HANATANI)
October 15, 2018
Programming
10k
30
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
破綻しない Vue.js アプリケーション開発のために大切なこと / How to make a robust Vue.js application
2018/10/15 に JSLounge の活動として UUUM株式会社様で行った発表のスライドです。
potato4d(Takuma HANATANI)
October 15, 2018
More Decks by potato4d(Takuma HANATANI)
See All by potato4d(Takuma HANATANI)
どうせキレイに書けない処理は逆にAIに書いてもらうほうが良い説 / #kyotojs 22
potato4d
3
470
TSX First な Zero-Runtime SSG potato4d/dodai とその仕組み / owned static site generator #kyotojs
potato4d
1
2.6k
Vue.js with TSX - From Vue 2.x to Vue 3 #v_tokyo11
potato4d
9
5.1k
終わりゆく Vue 2.x 時代の状態設計のアンサー - Vue 3 の Provider への期待 / The Last Architecture of the Vue 2.x
potato4d
25
7.2k
Web Worker を使ってブラウザ上でポケモンの画像を解析したい! / Pokemon recognition from screenshots in browser using web worker
potato4d
0
1.4k
Firebase & Google Cloud によるサーバーレス帳票管理 #FJUG / Serverless Architecture in Candy
potato4d
8
3.8k
NestJS meetup Tokyo Opening Talk / What is NestJS? #nestjs_meetup
potato4d
11
4.5k
私たちはなぜ SPA で開発するのか / Why you choose SPA
potato4d
38
29k
Amplify Console 誕生以来本番運用しつづけてわかったこと #awswakaran_tokyo
potato4d
6
3.7k
Other Decks in Programming
See All in Programming
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
170
Event is what happens
moro
2
910
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
800
contenteditable と日本語入力に向き合う
colorful12
0
200
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
350
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
dotNET_vulnclicker_intro.pdf
deka_morita
0
150
AWSに止められる覚悟してますか?
morizo_1984
2
540
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
190
ActionController meets Protocol Buffers
sorah
0
560
Workers Cache を知る
syumai
0
370
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
230
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
3.2k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Between Models and Reality
mayunak
4
500
Build your cross-platform service in a week with App Engine
jlugia
234
19k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
410
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.4k
We Are The Robots
honzajavorek
0
400
Music & Morning Musume
bryan
48
7.4k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
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!