$30 off During Our Annual Pro Sale. View Details »

Vue.js Performance Tips / #v_kansai 11

Vue.js Performance Tips / #v_kansai 11

v-kansai Vue.js/Nuxt Meetup #11 (京都Devかふぇ共催)でVue.jsのパフォーマンスに関する発表を行いました。

https://vuekansai.connpass.com/event/144194/

# 参考にした記事
- 超速! Webページ速度改善ガイド(WEB+DB PRESS plus)
- https://www.amazon.co.jp/dp/477419400X
- Web Fundamentals | Google Developers
- https://developers.google.com/web/fundamentals
- Vue.js App Performance Optimization – A Tutorial Series
- https://madewithvuejs.com/blog/vue-js-app-performance-optimization-a-tutorial-series-via-itnext
- How to Drastically Reduce Estimated Input Latency and Time to Interactive of SSR Vue.js Applications
- https://markus.oberlehner.net/blog/how-to-drastically-reduce-estimated-input-latency-and-time-to-interactive-of-ssr-vue-applications/
- Progressive Hydration #react_fukuoka - Speaker Deck
- https://speakerdeck.com/pirosikick/progressive-hydration-number-react-fukuoka

Masashi Hirano

October 09, 2019
Tweet

More Decks by Masashi Hirano

Other Decks in Programming

Transcript

  1. Vue.js
    Performance
    Tips
    v-kansai Vue.js/Nuxt.js meetup #11
    Masashi Hirano / @shisama

    View Slide

  2. ฏ໺ ণ࢜ / Masashi Hirano
    αΠϘ΢ζגࣜձࣾ
    ɹɹϑϩϯτΤϯυΤΩεύʔτνʔϜ
    @shisama_
    @shisama
    Node.js Core Collaborator
    ؔ੢NodeֶԂOrganizer

    View Slide

  3. Agenda
    • Webϖʔδͷ଎౓ʹ͍ͭͯ
    • ύϑΥʔϚϯεͷܭଌ
    • ϖʔδϩʔυͷ଎౓վળ
    • ϥϯλΠϜͷ଎౓վળ

    View Slide

  4. Webϖʔδͷ଎౓ʹΑΔӨڹ
    • αΠτͷىಈ͕࣌ؒ3ඵҎ্

    ɹ὎53%ͷϢʔβ͕அ೦ͯ͠͠·͏
    • ىಈ͕࣌ؒ1ඵ஗͘ͳΔ

    ɹ὎ίϯόʔδϣϯ཰͕ 7% ‑Down

    View Slide

  5. Webϖʔδ͕දࣔ͞ΕΔ·Ͱ
    Loading
    Scripting
    Rendering
    Painting

    View Slide

  6. Webϖʔδ͕දࣔ͞ΕΔ·Ͱ
    Loading
    Scripting
    Rendering
    Painting
    Runtime

    View Slide

  7. ύϑΥʔϚϯεࢦඪʹͳΔRAILϞσϧ
    https://developers.google.com/web/fundamentals/performance/rail
    100ms 10ms 50ms 1000ms
    Ϣʔβʔೖྗ
    εΫϩʔϧ

    Ξχϝʔγϣϯ
    ΞΠυϧதͷॲཧ ϖʔδϩʔυ

    View Slide

  8. https://developers.google.com/web/fundamentals/performance/rail
    100ms 10ms 50ms 1000ms
    Ϣʔβʔೖྗ
    εΫϩʔϧ

    Ξχϝʔγϣϯ
    ΞΠυϧதͷॲཧ ϖʔδϩʔυ
    3VOUJNF
    ύϑΥʔϚϯεࢦඪʹͳΔRAILϞσϧ

    View Slide

  9. Webϖʔδͷ଎౓
    • ϖʔδϩʔυͷ଎౓
    • Loadingͷ࣌ؒΛ͍͔ʹ୹͘Ͱ͖Δ͔
    • ϥϯλΠϜͷ଎౓
    • දࣔ·Ͱͷ଎౓Λ͍͔ʹ୹͘Ͱ͖Δ͔
    • ϢʔβʔΠϯλϥΫγϣϯʹ͍͔ʹ଎͘Ԡ͑Δ͔

    View Slide

  10. ύϑΥʔϚϯεΛܭଌ͢Δ

    View Slide

  11. ύϑΥʔϚϯεͷվળʹ͸ܭଌ͕ॏཁ
    • Measure, Don’t Guess (ਪଌ͢ΔͳɺܭଌͤΑ)
    • ݱঢ়ΛՄࢹԽͯ͠ϘτϧωοΫΛݟ͚ͭΔ
    • Chrome DevToolsɺLighthouseɺWebPageTestͳͲศརͳ
    πʔϧ͕͋Δ
    • User Timing APIͳͲͰݸผͷॲཧΛܭଌ

    View Slide

  12. User Timing API
    // ܭଌ։࢝ͷϚʔΫ
    performance.mark(“A");
    heavyTask();
    // ܭଌऴྃͷϚʔΫ
    performance.mark(“B");
    // “heavy task”ͱ͍͏໊લͰ”A”ͱ”B”ͷؒͷ࣌ؒΛܭଌ
    performance.measure("heavy task", "A", "B");

    View Slide

  13. User Timing API

    View Slide

  14. Vue.config.performance
    • ίϯϙʔωϯτ͝ͱͷॲཧ࣌ؒΛܭଌ
    • தͰUser Timing API͕࢖ΘΕ͍ͯΔ
    const isDev = process.env.NODE_ENV !== “production";
    Vue.config.performance = isDev; // trueͰܭଌ͞ΕΔ
    new Vue({
    router,
    store,
    render: h => h(App)
    }).$mount("#app");

    View Slide

  15. Vue.config.performance

    View Slide

  16. ϖʔδϩʔυͷ଎౓վળ

    View Slide

  17. ϖʔδϩʔυͷ଎౓վળ
    • JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    • ը૾ͷ஗ԆಡΈࠐΈ
    • ը૾ͷ࠷దԽ
    • ServiceWorkerʹΑΔΩϟογϡ
    • …etc

    View Slide

  18. ϖʔδϩʔυͷ଎౓վળ
    • JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    • ը૾ͷ஗ԆಡΈࠐΈ
    • ը૾ͷ࠷దԽ
    • ServiceWorkerʹΑΔΩϟογϡ
    • …etc

    View Slide

  19. JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    import Home from ‘./Home.vue’
    import About from ‘./About.vue’
    const router = new VueRouter({
    routes: [
    { path: '/', component: Home },
    { path: ‘/about', component: About },
    ]
    })
    ੩తͳimport

    View Slide

  20. JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    "QQWVF
    )PNFWVF "CPVUWVF
    FOUSZKT
    7VF
    WVF
    SPVUFS
    SPVUFSKT
    BQJKT BYJPT
    BQQKT
    ϒϥ΢βͰ࣮ߦ͞ΕΔίʔυ

    View Slide

  21. JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    const router = new VueRouter({
    routes: [
    {path: '/',component: () => import('./Home.vue')},
    {path: '/about',component: () => import('./About.vue')},
    ]
    })
    ಈతͳimportʹ͢Δ͜ͱͰ
    ෼ׂ͢Δ͜ͱ͕Ͱ͖Δ

    View Slide

  22. JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    "QQWVF
    )PNFWVF "CPVUWVF
    FOUSZKT
    7VF
    WVF
    SPVUFS
    SPVUFSKT
    BQJKT BYJPT
    BQQKT
    IPNFKT
    BCPVUKT

    View Slide

  23. JavaScriptͷ෼ׂɾ஗ԆಡΈࠐΈ
    "QQWVF
    )PNFWVF "CPVUWVF
    FOUSZKT
    7VF
    WVF
    SPVUFS
    SPVUFSKT
    BQJKT BYJPT
    BQQKT
    IPNFKT
    BCPVUKT
    ࠷ॳ͸app.js͚ͩಡΈࠐΈɺ࣮ߦ࣌ʹ
    ෼ׂͨ͠ίʔυΛϩʔυ͢Δ

    View Slide

  24. ը૾ͷ஗ԆಡΈࠐΈ

    View Slide

  25. ϖʔδશମͷ͏ͪɺ࠷ॳʹදࣔ
    ͞ΕΔͷ͸͚ͩ͜͜

    View Slide

  26. ஗ԆಡΈࠐΈՄೳ

    View Slide


  27. εΫϦʔϯʹ
    ͍ࣸͬͯΔൣғ
    (viewport)
    ը૾ͷ஗ԆಡΈࠐΈ

    View Slide

  28. ը૾ͷཁૉ͕viewport
    ʹೖΔͱը૾Λϩʔυ
    ը૾ͷ஗ԆಡΈࠐΈ

    View Slide

  29. v-lazy-image
    https://github.com/alexjoverm/v-lazy-image

    View Slide

  30. v-lazy-image
    import Vue from "vue";
    import { VLazyImagePlugin } from "v-lazy-image";
    import App from "./src/App";
    Vue.use(VLazyImagePlugin);
    new Vue({
    el: "#app",
    render: h => h(App)
    });
    Vue.useʹ౉͢͜ͱͰͲͷίϯϙʔω
    ϯτͰ΋࢖͑ΔΑ͏ʹͳΔ

    View Slide

  31. v-lazy-image


    src=“https://path/to/image.jpeg”
    alt="sample"
    >


    <br/>.v-lazy-image {<br/>width: 100%;<br/>}<br/>
    ίϯϙʔωϯτ಺Ͱ
    v-lazy-imageΛ࢖͏

    View Slide

  32. ϥϯλΠϜͷ଎౓վળ

    View Slide

  33. ϥϯλΠϜͷ଎౓վળ
    • FCP΍TTI·Ͱͷ࣌ؒΛ୹͘͢Δ
    • UIϒϩοΫ͢Δॏ͍ॲཧΛආ͚Δ
    • ϒϥ΢βͷΞΠυϧ࣌ؒΛ࠷େݶ׆༻͢Δ
    • Web WorkerΛ༻͍ͨϝΠϯεϨουͷॲཧͷ࡟ݮ
    • …etc

    View Slide

  34. ϥϯλΠϜͷ଎౓վળ
    • FCP΍TTI·Ͱͷ࣌ؒΛ୹͘͢Δ
    • UIϒϩοΫ͢Δॏ͍ॲཧΛආ͚Δ
    • ϒϥ΢βͷΞΠυϧ࣌ؒΛ࠷େݶ׆༻͢Δ
    • Web WorkerΛ༻͍ͨϝΠϯεϨουͷॲཧͷ࡟ݮ
    • …etc

    View Slide

  35. https://developers.google.com/web/fundamentals/performance/rail

    View Slide

  36. https://developers.google.com/web/fundamentals/performance/rail
    Կ͔͕දࣔ͞Εͨͱ͖ Կ͔ίϯςϯπ͕දࣔ͞Εͨͱ͖
    ҙຯͷ͋Δද͕ࣔ͞Εͨͱ͖ ૢ࡞Մೳͱͳͬͨͱ͖

    View Slide

  37. Loading
    HTMLɾCSS
    JavaScript
    '$1
    55*
    Client Side Rendering

    View Slide

  38. Loading
    JavaScript
    '$1
    55*
    Server Side Rendering
    HTMLɾCSS

    View Slide

  39. Loading
    JavaScript
    '$1
    55*
    Server Side Rendering
    αʔόʔαΠυͰϨϯμϦϯάͨ݁͠ՌΛฦ͍ͯ͠Δ
    HTMLɾCSS

    View Slide

  40. • VueͷίʔυΛNode.jsͰ࣮ߦ͠αʔόʔαΠυͰHTMLΛ૊
    ΈཱͯΔ
    • ΫϥΠΞϯτ༻ͷJSϑΝΠϧ΋഑৴͢Δ
    • Nuxt.js͸σϑΥϧτͰSSR
    Server Side Rendering

    View Slide

  41. https://ssr.vuejs.org/guide/hydration.html

    View Slide

  42. • αʔόʔαΠυͰ૊ΈཱͯͨDOMΛ࠶ར༻͢Δ
    • ੩తͳHTMLʹΫϥΠΞϯταΠυͷVueΛΞλον
    • ΫϥΠΞϯταΠυͰσʔλมߋʹରԠͰ͖ΔಈతDOM
    ʹม׵
    Client Side Hydration

    View Slide

  43. Loading
    JavaScript
    '$1
    55*
    HTMLɾCSS
    Hydration
    )ZESBUJPO͍ͯ͠Δؒ͸
    ૢ࡞Ͱ͖ͳ͍

    View Slide

  44. Loading
    JavaScript
    '$1 55*
    HTMLɾCSS
    Hydration
    ஈ֊తʹ)ZESBUJPO͢Δ

    View Slide

  45. Progressive Hydration
    • ඞཁͳ෼Λஈ֊తʹHydration͢Δ
    • Hydrationͷ࣌ؒΛ୹͘͢Δ͜ͱͰTTI·Ͱͷ࣌ؒΛ୹͘͢Δ
    • Google I/O 2019Ͱ΋঺հ͞Ε͍ͯΔ

    https://youtu.be/k-A2VfuUROg

    View Slide


  46. Progressive Hydration
    ·ͩHydration
    ͞Ε͍ͯͳ͍

    View Slide

  47. viewportʹೖ͖ͬͯͨͱ͖ʹ
    hydrationͯ͠ૢ࡞Մೳʹ͢Δ
    Progressive Hydration

    View Slide

  48. https://github.com/maoberlehner/vue-lazy-hydration

    View Slide

  49. vue-lazy-hydration







    <br/>import LazyHydrate from 'vue-lazy-<br/>hydration';<br/>export default {<br/>components: {<br/>LazyHydrate,<br/>SomeComponent: () =><br/>import('./SomeComponent.vue'),<br/>},<br/>// ...<br/>};<br/>

    View Slide













  50. ϒϥ΢β͕ΞΠυϧঢ়ଶʹͳͬ
    ͨͱ͖ʹhydration

    View Slide













  51. SSRͰͷΈॲཧ͢Δ

    View Slide













  52. viewportʹೖ͖ͬͯͨΒhydration

    View Slide













  53. ίϯϙʔωϯτʹରͯ͠
    ૢ࡞ͨ͠ͱ͖hydration
    e.g. focusɺhover

    View Slide

  54. when-idle
    https://github.com/maoberlehner/vue-lazy-hydration/blob/master/src/LazyHydrate.js

    View Slide

  55. requestIdleCallback
    • ϒϥ΢β͕ΞΠυϧঢ়ଶͷͱ͖ʹίʔϧόοΫؔ਺Λ࣮ߦ͢
    Δ
    • ϝΠϯεϨουઐ༗ʹΑΔϨϯμϦϯά΍Ϣʔβʔૢ࡞ͷ๦
    ֐Λճආ͢Δ

    View Slide

  56. requestIdleCallback
    // 1ඵܦͬͯίʔϧόοΫ͕࣮ߦ͞Εͳ͚Ε͹λΠϜΞ΢τ
    const requestId = requestIdleCallback(() => {
    // ΞΠυϧঢ়ଶʹͳΕ͹࣮ߦ
    heavyTask();
    }, {timeout: 1000});
    // Ωϟϯηϧ͢Δ͜ͱ΋Մೳ
    cancelIdleCallback(requestId);

    View Slide

  57. when-visible
    https://github.com/maoberlehner/vue-lazy-hydration/blob/master/src/LazyHydrate.js

    View Slide

  58. IntersectionObserver
    • λʔήοτཁૉ͕viewportͱަࠩ͢Δͱ͖(ը໘಺ʹೖͬͯ
    ͖ͨͱ͖)ʹίʔϧόοΫؔ਺Λ࣮ߦ͢Δ
    • ࢖༻ྫɿը૾஗ԆಡΈࠐΈɺແݶεΫϩʔϧ etc

    View Slide

  59. IntersectionObserver
    const observer = new IntersectionObserver(entries => {
    const entry = entries[0];
    if (entry.intersectionRatio > 0) {
    enterTask(); // ཁૉ͕ը໘಺ʹೖͬͨͱ͖
    } else {
    exitTask(); // ཁૉ͕ը໘಺ʹग़ͨͱ͖
    }
    });
    observer.observe(document.querySelector("#target"));

    View Slide

  60. https://github.com/vuejs/vue-next

    View Slide

  61. https://github.com/vuejs/vue-next
    4JHOJpDBOUMZGBTUFS
    ʹޤ͏͝ظ଴

    View Slide

  62. ·ͱΊ
    • ύϑΥʔϚϯεܭଌΛ͢Δ΂͠
    • ଎౓վળʹ͸ϖʔδϩʔυͱϥϯλΠϜ͕͋Δ
    • ଎౓վળͷͨΊͷVue༻ͷOSSϥΠϒϥϦ͕͋Δ

    View Slide

  63. ࢀߟ
    • ௒଎! Webϖʔδ଎౓վળΨΠυ(WEB+DB PRESS plus)
    • Web Fundamentals | Google Developers
    • Vue.js App Performance Optimization – A Tutorial Series
    • How to Drastically Reduce Estimated Input Latency and Time to
    Interactive of SSR Vue.js Applications
    • Progressive Hydration #react_fukuoka - Speaker Deck

    View Slide

  64. એ఻
    10/25(Fri) 11/30(Sat), 12/1(Sun)

    View Slide

  65. Thanks.
    @shisama_
    @shisama

    View Slide