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
10k
30
Share
破綻しない 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
440
TSX First な Zero-Runtime SSG potato4d/dodai とその仕組み / owned static site generator #kyotojs
potato4d
1
2.5k
Vue.js with TSX - From Vue 2.x to Vue 3 #v_tokyo11
potato4d
9
5k
終わりゆく Vue 2.x 時代の状態設計のアンサー - Vue 3 の Provider への期待 / The Last Architecture of the Vue 2.x
potato4d
25
7.1k
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.4k
私たちはなぜ SPA で開発するのか / Why you choose SPA
potato4d
39
28k
Amplify Console 誕生以来本番運用しつづけてわかったこと #awswakaran_tokyo
potato4d
6
3.7k
Other Decks in Programming
See All in Programming
2026_04_15_量子計算をパズルとして解く
hideakitakechi
0
100
PHPで TLSのプロトコルを実装してみるをもう一度しゃべりたい
higaki_program
0
200
ルールルルルルRubyの中身の予備知識 ── RubyKaigiの前に予習しなイカ?
ydah
1
180
ファインチューニングせずメインコンペを解く方法
pokutuna
0
310
クラウドネイティブなエンジニアに向ける Raycastの魅力と実際の活用事例
nealle
2
190
YJITとZJITにはイカなる違いがあるのか?
nakiym
0
220
JAWS-UG横浜 #100 祝・第100回スペシャルAWS は VPC レスの時代へ
maroon1st
0
130
第3木曜LT会 #28
tinykitten
PRO
0
100
事業会社でのセキュリティ長期インターンについて
masachikaura
0
250
AI時代のPhpStorm最新事情 #phpcon_odawara
yusuke
0
180
Coding as Prompting Since 2025
ragingwind
0
830
Don't Prompt Harder, Structure Better
kitasuke
0
750
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.6k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
170
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
100
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
A designer walks into a library…
pauljervisheath
211
24k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.1k
The SEO Collaboration Effect
kristinabergwall1
0
420
Visualization
eitanlees
150
17k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Speed Design
sergeychernyshev
33
1.6k
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!