2020/12/15 @ FE Study #2 パフォーマンスチューニングの話です。
ϝλɾύϑΥʔϚϯενϡʔχϯά2020/12/15 @FE Study #2
View Slide
Twitter: @yosuke_furukawaGithub: yosuke-furukawa࠷ۙͷ׆ಈ$ISPNF"EWJTPSZ#PBSE+4$POG+1PSHBOJ[FSFUD
͜͜࠷ۙɺύϑΥʔϚϯεपΓͷߋ৽͕ଟ͍ɻಛʹ Web Vitals पΓɻ
Web Vitals• Google ͕ఏএ͢Δ৽͍͠ UX ͷࢦඪ• Largest Contentful Paint• First Input Delay• Cumulative Layout Shift• ͷ3͔ͭΒͳΔɻ
Largest Contentful Paint• ϖʔδͷ࠷େͷ໘ੵΛද͖͔ࣔͬͨ͠Ͳ͏͔• 2500 ms Ҏʹද͖ࣔ͠ΕͨΒ Good• 4000 ms Ҏ্ͩͱ Poor
/BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM1BJOULoading..'JSTU.FBOJOHGVM1BJOU-BSHFTU$POUFOUGVM1BJOU*NBHF5JNF5P*OUFSBDUJWF*NBHF'VMMZ-PBEFE*NBHFԿ͔දࣔ͞ΕΔ·ͰίϯςϯπͷதͰҰ൪େ͖͍ཁૉ͕ݟ͑Δ·Ͱ݁ہϢʔβʔϝΠϯίϯςϯπ͕ಡΈࠐ·ΕΔ·ͰಡΈਐΊͳ͍ͰͬͯΔࣄ͕ଟ͍ɻLargest Contentful Paint
Largest Contentful Paint• LCP͕͍࣌ͷվળϙΠϯτ• αʔόͷϨεϙϯελΠϜ• JSCSSͳͲͷ render blocking resource ͷ༗ແ• Client Side RenderingΛආ͚Δ (JS͕ϩʔυ͞Ε͔ͯΒ͡Όͳ͍ͱίϯςϯπ͕දࣔ͞Εͳ͍ͷͰ)• ώʔϩʔը૾ Preload ͢ΔͳͲɻ
Largest Contentful Paint• ώʔϩʔը૾ Preload ͓ͯ͘͠ͱྑ͍ɻhttps://web.dev/optimize-lcp/#preload-important-resources
First Input Delay• ϖʔδ͕ೖྗʹԠͰ͖Δ·Ͱͷ࣌ؒ• 100ms Ͱ Good• 300ms ͩͱ Poor
/BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM1BJOULoading..'JSTU.FBOJOHGVM1BJOU-BSHFTU$POUFOUGVM1BJOU*NBHF5JNF5P*OUFSBDUJWF*NBHF'VMMZ-PBEFE*NBHFදࣔͯ͠ಡΊΔΑ͏ʹͳΔ·Ͱૢ࡞Ͱ͖ΔΑ͏ʹͳΔ·Ͱ ૢ࡞த͜ͷ࣌ؒͷဃ͕͚Ε͍΄Ͳૢ࡞Ͱ͖ͣʹϢʔβʔͷετϨεʹͳΔFirst Input Delay
First Input Delay• ͦͦಡΈࠐ·ΕͯΔJavaScriptΛݕ౼͢Δ• defer/async ͳͲͷಡΈࠐΈํͷվળ• code split ͰJSΛ͚Δ• polyfill ͷར༻Λ߇͑ΔʢϞμϯϒϥβ͚ͷ Bundle JSΛ࡞Δ)• ΘΕͯͳ͍ JS ΛΔ• ͦΕͰͲ͏ʹͳΒͳ͍ͱ͖ WebWorker ΛͬͨΓ͢Δʢඈͼಓ۩ʣ
Cumulative Layout Shift• ϖʔδ͕ಡΈࠐ·Ε࢝Ί͔ͯΒྖҬ͕ͣΕͨ߹ͷζϨ෯ͷ• 0.1 Ҏͷ Layout Shift είΞͳΒ Good• 0.25 Ҏ্ͳΒ Poor
Cumulative Layout Shift• Layout Shift = impact friction(ͲΕ͚ͩͷେ͖͞ͷΤϨϝϯτ͔) * distance friction (ͲΕ͚ͩಈ͍͔ͨ)• Layout Shift ͷ૯͕CLS
Cumulative Layout ShiftLayout Shiftϩʔυͨ͠ޙͰҐஔ͕ͣΕΔͱ༧ظ͠ͳ͍ঢ়گʹͳΓɺϢʔβʔށ͏ɻϨΠΞτTUBCMFͰ͋Δ͖ɻ
Cumulative Layout Shift• Α͋͘Δͷը૾ͷॎԣ෯Λࢦఆͯ͠ͳ͍• ಈըiframeॎ෯ԣ෯Λࢦఆͯ͠ͳ͍• Webfont FOUT FOIT ʹΑΓएׯϨΠΞτγϑτ͕ى͖Δ͕࣌͋ΓɺͦΕݪҼͷҰͭʹͳΓ͑Δɻ
• Public CDN ͔Βαʔϒ͞ΕΔWebFont͏͍Βͳ͍͔ʁ• Cache Partitioning ʹΑΓɺ Public CDN ͷࢫຯ͕མͪͯΔCumulative Layout Shifthttps://wicki.io/posts/2020-11-goodbye-google-fonts/
ͨͩ͜͠ΕΒͷࢦඪมΘΓಘΔࣄΛ࠷ॳ͔Βࣔࠦ͞Ε͍ͯΔɻ
Chrome Dev Summit ͰૣมΘΔ͜ͱ͕ൃද͞Ε͍ͯͨ
Web Vitals มߋ• Largest Contentful Paint:First Contentful Paintʢ࠷ॳʹCSSͷ͋ͨͬͨྖҬ͕ग़Δ·Ͱͷ࣌ؒʣࢦඪʹೖΕΔɻProgressive ͳϩʔυ͕Ͱ͖͍ͯΔ͜ͱΛݟΔɻ
Web Vitals มߋ• Progressive Loading/BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM1BJOULoading..'JSTU.FBOJOHGVM1BJOU-BSHFTU$POUFOUGVM1BJOU*NBHF5JNF5P*OUFSBDUJWF*NBHF'VMMZ-PBEFE*NBHFԿ͔දࣔ͞ΕΔ·ͰίϯςϯπͷதͰҰ൪େ͖͍ཁૉ͕ݟ͑Δ·ͰશମͰධՁ͞ΕΔΑ͏ʹͳΔɻ-$1͚ͩૣ͚ΕΑ͍Θ͚Ͱͳ͘ɺ࠷ॳ͔Β-$1·Ͱશ෦ૣ͘ͳΒͳ͍ͱ͍͚ͳ͍
Web Vitals มߋ• First Input Delay:γϯϓϧʹ͕࣌ؒݮΔ (50ms - 75ms) Λᮢͱ͢Δɻ
/BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM1BJOULoading..'JSTU.FBOJOHGVM1BJOU-BSHFTU$POUFOUGVM1BJOU*NBHF5JNF5P*OUFSBDUJWF*NBHF'VMMZ-PBEFE*NBHFදࣔͯ͠ಡΊΔΑ͏ʹͳΔ·Ͱૢ࡞Ͱ͖ΔΑ͏ʹͳΔ·Ͱ ૢ࡞தNT͗ͨ͢ɻUJMFͰNTͰͳͦ͞͏ͳͷͰɺͦͪΒʹϑΥʔΧεΛͯΔFirst Input Delay
Web Vitals มߋ• Cumulative Layout Shift:ϨϯμϦϯά࣌ͷΈͷγϑτͰͳ͘ɺظؒੜ͖ͯΔϖʔδ (SPAͷΑ͏ͳ) ʹಉ͡είΞΛద༻͍ͯ͘͠ɻ
Cumulative Layout ShiftLayout Shiftϩʔυ͠ऴΘͬͨޙʹ-BZPVU4IJGU͕ൃੜͨ͠߹Ͱ͋ͬͯదٓͦΕ͕ධՁ͞ΕΔɻ
ॳظදࣔ࣌ͰͷධՁ͔Βnavigation scroll ͳͲͷૢ࡞ΛؚΊͨτʔλϧͷධՁ͕伴ʹͳΔ
ͱɺ͜ͷΑ͏ʹCore Web VitalsͱҰޱʹݴͬͯࢦඪมΘΔ͠ɺΔ͜ͱมΘΔɻ
աڈʹ͋ͬͨ(ࠓ͋Δ?)ࢦඪPRPL / RAIL
WebύϑΥʔϚϯεੜ͖ࢦඪมΘΕվળϙΠϯτৗʹมΘΓਐԽ͢Δ
୭ͷͨΊͷύϑΥʔϚϯεʁ
ຐ๏ͷݴ༿:ݕࡧΤϯδϯʹධՁ͞ΕΔ
ݕࡧΤϯδϯʹධՁ͞ΕΔ͔ͩΒύϑΥʔϚϯενϡʔχϯάΛΔɺͱ͍͏ͷखஈͱత͕มΘͬͯΔ
ຊདྷϢʔβʔͷମݧΛ্ͤ͞ΔͨΊʹύϑΥʔϚϯεΛ্͛Δɺͦͷ݁ՌݕࡧΤϯδϯʹධՁ͞ΕΔ
ύϑΥʔϚϯεϢʔβʔͷͨΊͷͷ
ύϑΥʔϚϯεੜ͖Ͱ͋ΓɺϢʔβʔͷମݧΛ্ͤ͞ΔͨΊʹߟ͑ͳ͍ͱ͍͚ͳ͍ͷ
զʑͲ͏͢Δ͖͔ʁ
3ͭώϯτΛհ
1.ͳΔ͘ݟ͑ΔԽ͢ΔɺطଘͷՄࢹԽπʔϧ͚ͩͰͳࣗ͘Ͱ࡞Δ͜ͱࢹʹೖΕΔ
ݟ͑ͳ͍ͷଌΕͳ͍ଌΕͳ͍ͷվળͰ͖ͳ͍
طଘͷπʔϧΛ͏• SpeedCurve• Lighthouse CI• CrUX• Page Speed Insights• etc
طଘͷπʔϧΛ͏• ࠷ۙग़ͨͭ (AutoWebPerf)
ͪΖΜطଘͷπʔϧॏཁ͚ͩͲɺ࠷ۙUI͕ߴԽ͍ͯ͠Δࣄ͋Γɺ୯७ͳई͚ͩͰΓͳ͍͜ͱ͋Δ
ՄࢹԽ͕ॏཁ• AirSHIFTͰɺϢʔβʔͷ࣮ࡍͷૢ࡞Λجʹ͔͔ͬͨඵΛkibanaͰݟ͑ΔΑ͏ʹ͍ͯ͠Δɻ
طଘͷπʔϧͰऔΕΔϝτϦΫε࠷ݶඞཁͳͷͱͯ͠ɺϢʔβʔͷମݧͦͷͷͷύϑΥʔϚϯεΛՄࢹԽ͢Δ͜ͱͰΑΓମݧʹ͕݁ͨ࣌ؒ͠औΕΔɻ
2.ͳΔ͘ϞμϯͳϑϨʔϜϫʔΫʹΔɺͰ͖ͳ͍ͳΒͬͯΔ͜ͱΛΔ
ϞμϯͳΑ͘ΘΕ͍ͯΔϑϨʔϜϫʔΫʹϕετϓϥΫςΟεͬΆ͍͜ͱ͕٧·ͬͯΔɻ
Next.js / Nuxt.js
Next.js / Nuxt.js• JS ͷ Code Split Server Side Rendering / Static SiteGeneration ͳͲͷݱͷϕετϓϥΫςΟεͬΆ͍͜ͱ͍͍ͩͨͬͯ͘ΕΔɻ• next/link ͰಡΈࠐΈઌͷϖʔδ͕ݟ͑ͨΒɺઌಡΈ(prefetch)ͱ͔ͯ͘͠ΕΔɻ• AMP͕ built-inͰΈࠐ·Ε͍ͯͯɺ AMP ʹ͢Δ͜ͱͰ͖Δɻ
Next.js• next/image ॎ෯ɾԣ෯Λࢦఆͤ͞Δ͜ͱͰ LayoutShift Λى͜͞ͳ͘͢Δɻ͞Βʹը૾ͷ࠷దԽΛߦ͏ΈҰॹʹఏڙ͍ͯ͠Δ• reportWebVitals ͰWebVitalsͷϝτϦΫε͕औΕΔɻ
3.ύϑΥʔϚϯεվળΛઐՈʹΑΔ৬ਓܳʹ͠ͳ͍
ύϑΥʔϚϯεվળ͕৬ਓܳʹͳΔͱ৬ਓ్͕ઈ͑ͨॠؒʹվળݟࠐΊͳ͘ͳΔɻ
εϐʔυϋοΧιϯ/ISUCON
ΣϒϑϩϯτΤϯυ͚ͩͰͲ͜·ͰLighthouseͷείΞΛ্͛ΒΕΔ͔ڝ͏େձ
ظతʹੑೳʹؔ͢ΔφϨοδΛ࣮ઓܗࣜͰஷΊΒΕΔɻ
ͳΔ͘ݟΛڞ༗͢Δɻͬͱݴ͏ͱจԽʹ͢Δɻ
·ͱΊ
·ͱΊ• ύϑΥʔϚϯεੜ͖ɺࢦඪมΘΕվળϙΠϯτมΘ͍ͬͯ͘ɻ• ύϑΥʔϚϯεϢʔβʔͷͨΊͷͷɻχʔζʹΑͬͯݟΔ͖ϙΠϯτมΘΔɻ• զʑ͕Ͱ͖Δ͜ͱ• ͳΔ͘ݟ͑ΔԽ͢Δ• ϞμϯͳϑϨʔϜϫʔΫʹΔ• ύϑΥʔϚϯεվળΛจԽʹ͢Δ
ࢀߟࢿྉ• https://web.dev/lcp/• https://web.dev/fid/• https://web.dev/cls/• https://web.dev/optimize-lcp/#preload-important-resources• https://wicki.io/posts/2020-11-goodbye-google-fonts/• https://ja.nuxtjs.org/• https://nextjs.org/• https://nextjs.org/docs/advanced-features/measuring-performance• https://nextjs.org/docs/basic-features/image-optimization• https://recruit-tech.co.jp/blog/2020/01/29/wow-the-beauty-speed-hackathon/• http://isucon.net/
͋Γ͕ͱ͏͍͟͝·ͨ͠