Upgrade to Pro — share decks privately, control downloads, hide ads and more …

破綻しない 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株式会社様で行った発表のスライドです。

Potato4d(Hanatani Takuma)

October 15, 2018
Tweet

More Decks by Potato4d(Hanatani Takuma)

Other Decks in Programming

Transcript

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

    View Slide

  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

    View Slide

  3. What's JSLounge produced by ElevenBack ?
    ΦϑϥΠϯΠϕϯτ ΦϯϥΠϯڭࡐఏڙ اۀ޲͚ߨश
    https://jslounge.connpass.com https://jslounge-archives.elevenback.jp/ https://blog.elevenback.jp

    View Slide

  4. ࠓ೔ͷΰʔϧ

    View Slide

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

    View Slide

  6. ࠓ೔ͷΰʔϧ
    • طଘίʔυͷෛ࠴
    • ͍ͭ࡞Γม͑Δ͔ͷ೰Έ
    • Vue.js ͷΞϯνύλʔϯ΁ͷ՝୊ײ
    • ίʔυͷʮࣺͯͲ͜Ζʯ΁ͷཧղ
    • ϑϩϯτΤϯυͷ଱༻೥਺ͷ೺Ѳ
    • ഁغ͍ͯ͘͜͠ͱΛલఏͱͨ͠ઃܭ

    View Slide

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

    View Slide

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

    View Slide

  9. ଱༻೥਺ʹ͍ͭͯ
    • ࣮ࡍͷ։ൃͷγʔϯͰ͸໰୊ͳ͘ϝϯςφϯεͰ͖Δͷ͸2,3
    ೥͕ݶ౓
    • ΞʔΩςΫνϟ΍ϓϩάϥϜͷࢹ఺͚ͩࡁΉ໰୊Ͱ͸ͳ͍
    • ྫ͑͹υϝΠϯ֓೦ͷݟ௚͠΁ͷ௥ै
    • ྫ͑͹σβΠϯϦχϡʔΞϧ΁ͷ௥ै
    • ٕज़τϨϯυʹ߹Θͤͨભٶ

    View Slide

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

    View Slide

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

    View Slide

  12. ٕज़τϨϯυʹ߹Θͤͨมભ
    • Vue.js 1.0 ͸ 3 ೥લɺ Vue.js 2.0 ͸ 2 ೥લɺ࣍ͷ v3 ͸……
    • ʮݹ͘ͳΔͱ৘ใ΋૿͑ͣศརͳ΋ͷ΋࢖͑ͳ͍ʯ
    • ʮՄೳͰ͋Ε͹࣌ؒΛͱͬͯ΋࠷௿ݶϝδϟʔ͸͍͋͛ͨʯ

    View Slide

  13. ٕज़τϨϯυʹ߹Θͤͨมભ
    • খ͞ͳτϨϯυ୯ҐͰ΋τϨϯυ͸มΘΔ
    • ࣌ࠁૢ࡞͸ day.js ͕ moment ͷ୅ΘΓʹͳ͍ͬͯΔ͔΋
    • HTTP ௨৴΋ XHR ͳ axios Ͱ͸ͳ͘ fetch ϕʔεͷ΋ͷ͔΋

    View Slide

  14. ࠷ऴతʹ࢒Δͷ͸……ʁ
    ✘ Vue.js ΍ UI ʹܹ͘͠ґଘͨ͠෦෼
    ✘ Build environment
    ✘ ྲྀߦΓͷϥΠϒϥϦʹΑ࣮ͬͯ૷͞Εͨ෦෼
    ✘ υϝΠϯશҬ(ഽײίʔυϕʔεͷ6ׂఔ౓͸Ҡ২Մೳ)
    ˕ ϓϩδΣΫτʹ͋Θ͍ͤͨΘΏΔʮϢʔςΟϦςΟʯ
    ˕ ൚༻తͳ(Ξφ΢ϯε΍௨஌ͳͲͷ)ίϯϙʔωϯτͷϩδοΫ

    View Slide

  15. ࠷ऴతʹ࢒Δͷ͸……ʁ
    ΋͍͚ͬͯΔͷ͸஌ࣝͱܦݧ
    มΘΔ͜ͱΛલఏʹʮࣺͯ΍͍͢ʯίʔυΛ࡞Δ
    = ϑϩϯτΤϯυ͸ϩʔάϥΠΫ

    View Slide

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

    View Slide

  17. جຊతͳߟ͑ํ
    ʮࣺͯ΍͍͢ʯίʔυͷͨΊʹ……
    1. ʮ࠶ར༻ੑʯ΁ͷແؔ৺ͱݻࣥ͸ಟ
    2. Vuex͸ԿͷͨΊʹ͋Δ͔Λߟ͑Δ
    3. Vue.js ͓Αͼ SFC ʹͩ͜ΘΓ͗͢ͳ͍
    ͜͜Ͱ͸֓೦ͷΈɺ࣮ྫ͸࣍ͷηΫγϣϯͰɹ⾣

    View Slide

  18. ʮ࠶ར༻ੑʯ΁ͷແؔ৺ͱݻࣥ͸ಟ
    • ੹຿ͷଟ͍ίʔυ͸·ͱΊͯഁغ͢Δඞཁ͕ग़ͯ͘Δ
    • ͔ͱݴͬͯ Vuex ͳͲͷάϩʔόϧͳσʔλʹ҆қʹґଘ͢Δ
    ͱࠜຊతͳվमʹ଱͑ΒΕͳ͍
    • ϓϨθϯςʔγϣϯ૚ͷͨΊ͚ͩͷσʔλ͸൚༻ੑΛٻΊΔ
    • ϩδοΫ͸୯ମͰ͸ՄೳͳݶΓബ͘ॻ͘
    • ͳͲͳͲ……

    View Slide

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

    View Slide

  20. Vue.js / SFC ʹͩ͜ΘΓ͗͢ͳ͍
    • Vue.js ͔ͩΒͱ͍ͬͯશͯΛ .vue Ͱ׬݁ͤ͞Δඞཁ͸ͳ͍
    • SFC ͸ Vue Test Utils Λར༻ͨ͠είʔϓͷେ͖͍ςετͳͲ
    ͕ඞཁʹͳΔͷͰඞવੑͷ͋Δ੹຿͚ͩΛ΋ͨͤΔ
    • ͋ͱ͸ VanillaJS ʹΑΔهड़Λ৺͕͚Δ
    • ৄ͘͠͸࣍ͷηΫγϣϯͰ

    View Slide

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

    View Slide

  22. ࠶ར༻ੑͷײ֮஋ͷζϨ

    View Slide

  23. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ

    Like

    <br/>import { mapActions } from ‘vuex’<br/>export default {<br/>props: { id: Number },<br/>methods: {<br/>click() {<br/>this.like({ id })<br/>},<br/>.. .mapActions(‘entries’, [‘like’])
<br/>}
<br/>}<br/>
    -JLF#VUUPOWVF

    View Slide

  24. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ

    Like

    <br/>import { mapActions } from ‘vuex’<br/>export default {<br/>props: { id: Number },<br/>methods: {<br/>click() {<br/>this.like({ id })<br/>},<br/>.. .mapActions(‘entries’, [‘like’])
<br/>}
<br/>}<br/>
    Atoms ૬౰ͷϞϊ͕ Vuex ʹґଘ͍ͯ͠Δ
    -JLF#VUUPOWVF

    View Slide

  25. վળྫ

    Like

    <br/>export default {<br/>methods: {<br/>click(event) {<br/>this.$emit('click', event)<br/>}<br/>}
<br/>}<br/>
    Vue.js ͷΠϕϯτγεςϜΛ࢖ͬͯ੹຿Λബ͘
    -JLF#VUUPOWVF

    View Slide

  26. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ











    <br/>export default {<br/>props: { mode: String }<br/>}<br/>
    6TFS'PSNWVF

    View Slide

  27. ͜Μͳίϯϙʔωϯτ࡞ͬͯ·ͤΜ͔ʁ











    <br/>export default {<br/>props: { mode: String }<br/>}<br/>
    ίϯϙʔωϯτʹೋͭҎ্ͷ໾ׂ͕͋Δ
    6TFS'PSNWVF

    View Slide

  28. վળྫ









    <br/>export default {<br/>}<br/>
    6TFS$SFBUF'PSNWVF
    ৑௕ʹͳͬͯ΋ͦΕͧΕผͷίʔυʹ͢Δ

    View Slide

  29. վળྫ









    <br/>export default {<br/>}<br/>
    6TFS&EJU'PSNWVF
    ผͷίʔυʹ͓ͯ͘͠ͱʮߋ৽ෆՄʯͷ߲໨ͷ࣮૷΋༰қ

    View Slide

  30. VuexʹدͤΔ΂͖ίʔυͱ
    دͤΔ΂͖Ͱ͸ͳ͍ίʔυ

    View Slide

  31. ͜ΜͳίʔυΛॻ͍ͯ·ͤΜ͔ʁ
    import { mapGetters, mapActions } from 'vuex'
    export default {
    computed: {
    ...mapGetters('entries', { form: 'editEntry' })

    },
    methods: {
    ...mapActions('entries', ['updateEditEntry', 'updateEntry'])
    }
    }
    &OUSZ&EJU'PSNWVF

    View Slide

  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 ͮ͠Β͘ͳ͍ͬͯΔ

    View Slide

  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 ʹԿނ͔ϑΥʔϜͷঢ়ଶ͕

    View Slide

  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. ೖྗ͕Ωϟϯηϧ͞Εͨ৔߹΋ίϯϙʔωϯτͷϥΠϑαΠΫϧʹΑͬͯద੾ʹഁغ

    View Slide

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

    View Slide

  36. Single File Component vs VanillaJS

    View Slide

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

    View Slide

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

    View Slide

  39. मਖ਼ྫ
    function convert(args) {
    return {...args}

    }
    export default convert
    VUJMTDPOWFSUFSKT
    JavaScript ͚ͩͰ׬݁͢Δ෦෼͸ JavaScriptͰ੾Γग़͢

    View Slide

  40. मਖ਼ྫ
    import convert from './converter'
    describe('converter.js', () => {
    test('test code', () => {
    const input = { val1: '', val2: '' }
    expect(convert(input)).toMatchObject(input)
    })
    })
    TQFDVUJMTDPOWFSUFSTQFDKT
    JavaScript Ͱॻ͘͜ͱͰςετίʔυ΋هड़͠΍͘͢

    View Slide

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

    View Slide

  42. Vue CLI v3
    • Vue.js ۘ੡ͷ CLI πʔϧ
    • طଘͷ؀ڥ(ࣗྗͰ webpack Λ৮Δ؀ڥ)͔Β΋Ҡߦ͠΍͍͢
    • CLIπʔϧͷԆ௕Β͍͠ػೳ͕๛෋
    • ϓϥάΠϯʹΑΔ؀ڥͷڧԽ͕༰қ
    • ϓϥάΠϯʹΑΔ؀ڥͷߏங͕༰қ
    • ίϚϯυҰൃͰςετ؀ڥͳͲΛ࡞੒Մೳ
    • ։ൃମݧͱͯ͠͸؀ڥ΍଍ճΓΛڧԽ͢Δཁૉ͕ڧ͍

    View Slide

  43. 7VFKT1SPKFDU
    5FTUJOH
    Nuxt.jsΛ༗ޮ׆༻͢Δ
    7VFKT
    7VF3PVUFS
    7VFY
    7VF5FTU6UJMT
    1VSF+BWB4DSJQU
    &YUFSOBM4FSWJDF
    )551
    6UJMJUZ
    CVJMEFOWJSPONFOU
    CVJMEFOWJSPONFOU
    CVJMEFOWJSPONFOU

    View Slide

  44. 7VF$-*W1SPKFDU
    7VF$-*4FSWJDF
    5FTUJOH
    Vue CLI v3 ༗ޮ׆༻͢Δ
    7VFKT
    7VF3PVUFS
    7VFY
    7VF5FTU6UJMT
    1VSF+BWB4DSJQU
    &YUFSOBM4FSWJDF
    )551
    6UJMJUZ

    View Slide

  45. Nuxt.js
    • Vue.js ͔ΒݟΔ৔߹͸ඇެࣜͷϑϨʔϜϫʔΫ
    • Vue.js ͷίϛϡχςΟύʔτφʔͱͳͬͨͷͰڠྗؔ܎Ͱ͸͋Δ
    • ϑϨʔϜϫʔΫΒ͍͠ػೳΛఏڙ͢Δ
    • ಠࣗͷϞδϡʔϧ΍ϓϥάΠϯγεςϜ
    • ΦʔτϩʔσΟϯάܥͷػೳ΍ SSR ͷσϑΥϧταϙʔτ
    • ϓϩδΣΫτͷجຊઃܭΛ Nuxt.js ʹ೚ͤΔ͜ͱ͕Ͱ͖Δ
    • ։ൃମݧͱͯ͠͸ϓϩδΣΫτઃܭΛڧԽ͢Δཁૉ͕ڧ͍

    View Slide

  46. 7VFKT1SPKFDU
    5FTUJOH
    Nuxt.jsΛ༗ޮ׆༻͢Δ
    7VFKT
    7VF3PVUFS
    7VFY
    7VF5FTU6UJMT
    1VSF+BWB4DSJQU
    &YUFSOBM4FSWJDF
    )551
    6UJMJUZ
    CVJMEFOWJSPONFOU
    CVJMEFOWJSPONFOU
    CVJMEFOWJSPONFOU

    View Slide

  47. /VYUKT1SPKFDU
    5FTUJOH
    /VYUKT
    Nuxt.jsΛ༗ޮ׆༻͢Δ
    7VFKT
    7VF3PVUFS
    7VFY
    7VF5FTU6UJMT
    1VSF+BWB4DSJQU
    &YUFSOBM4FSWJDF
    )551
    6UJMJUZ
    webpack
    vue-meta
    vue-server-renderer
    Project structure

    View Slide

  48. Vue CLI v3 or Nuxt.js
    • ར༻Ϟνϕʔγϣϯ͔Βͯ͠ҧ͏ͷͰҰ֓ʹ͸ൺֱతͰ͖ͳ͍
    • ݸਓతʹ͸ Vue.js ͷϏΪφʔ͕গͳ͍৔߹͸ Nuxt.js Λਪ঑
    • ͍͖ͳΓ Nuxt.js Λ৮Δͷ͸ϋʔυϧ͕ߴ͍ͷͰඇਪ঑
    • ͋Δఔ౓׳Εͨਓ͕ Nuxt.js ͰҰ௨Γ૊ΜͰ͠·͑͹ϏΪφʔ͕͋
    ͱ͔Βೖͬͯ΋յΕͳ͍Α͏ͳઃܭ͕Ͱ͖Δ
    • ͲͷΈͪ 2 ೥ఔ౓ͷεύϯͰߟ͑ΔͳΒϨʔϧʹ৐ͬͯߴ͍ੜ࢈
    ੑΛಘͨ΄͏͕ϓϩδΣΫτΛυϥΠϒͰ͖Δ

    View Slide

  49. thanks!

    View Slide