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
Loading Performanceとの向き合い方 / InsideFrontend 2019
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Sho Miyamoto
May 18, 2019
Technology
2.4k
8
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Loading Performanceとの向き合い方 / InsideFrontend 2019
Sho Miyamoto
May 18, 2019
More Decks by Sho Miyamoto
See All by Sho Miyamoto
JavaScriptエンジンから見るランタイム / 2024-04-25
shqld
12
2.3k
Proxy-Status & Cache-Status
shqld
0
670
High Performance JavaScript / jsconfjp2019
shqld
0
640
FastlyとTypeScriptで実現するカナリアリリース / yamagoya2020
shqld
21
7.5k
ServiceWorkerの開発 / ServiceWorker Development
shqld
3
800
日経電子版とPWAのこれから / PWANight vol.2
shqld
2
5.2k
日経電子版のマイクロフロントエンドとPWA / devsum2019
shqld
8
13k
Other Decks in Technology
See All in Technology
AI時代、データエンジニアが一番おもろい
genshun9
0
670
アプリをもっと"iOSアプリっぽく"する小さな工夫 / Small Touches That Make Your App Feel More Like an iOS App
matsuji
2
980
SREは、MCPとAutopilotをこう使え!
kazumax55
3
920
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.3k
現場で役立つ技術負債の効果的な返済方法
masuda220
PRO
9
4.7k
AIによるクリエイティブ生成を行う上での試行錯誤
plaidtech
PRO
0
160
GoのInterface内部構造から学ぶ!最高パフォーマンスを出すコード設計
yappli_developers
1
210
サーバーレスをどこまで使う? WebRTC対戦ゲームで選んだVPSとの共存設計
kaidouji85
0
230
AIを活用するために決めた "やらないこと" - 価値に注目する / Not betting on AI
soudai
PRO
3
570
Vibe Coding で作ったプロダクトをどう安全に動かすか / How to Safely Run Products Built with Vibe Coding
glidenote
0
390
C#未経験の僕がAIに読めるコードを書かせるまで
maguroalternative
0
140
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
870
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Color Theory Basics | Prateek | Gurzu
gurzu
1
470
Tell your own story through comics
letsgokoyo
1
1.1k
エンジニアに許された特別な時間の終わり
watany
109
250k
Deep Space Network (abreviated)
tonyrice
0
310
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.1k
Bash Introduction
62gerente
615
220k
Facilitating Awesome Meetings
lara
57
7.1k
Transcript
Loading Performanceͱͷ ͖߹͍ํ ຊܦࡁ৽ฉࣾ ٶຊ ক (@shqld)
- ٶຊ ক (Sho Miyamoto) - @shqld (Github, Twitter) -
ຊܦࡁ৽ฉࣾ ৽ଔ2 - ࠷ۙ։ൃϝΠϯ - r.nikkei.com ͷϑϩϯτɺBFFɺCDN - Իָ - τϥϯϖοτ(JazzFunkܥʣɺϐΞϊ - ౦ೆΞδΞʹॅΈ͍ͨ ͩΕʁ Who am I
ܦిࢠ൛ a.k.a Nikkei 20103݄ץ ຖ900ຊͷهࣄΛ৴ ݄ؒ3ԯΞΫηεҎ্ 201711݄ʹϞόΠϧ൛ϦχϡʔΞϧ
Google IO 2019 Credit: @sisidovski (twitter) Speed at Scale: Web
Performance Tips and Tricks from the Trenches (Google I/O ’19)
7݄ʹ2ͷϦχϡʔΞϧ 2nd time renewal in next July ະެ։
✔ LoadingPerformanceͱܦిࢠ൛ ✔ ֎෦εΫϦϓτͱύϑΥʔϚϯε ✔ ݎ࿚ੑͱύϑΥʔϚϯε ✔ DXͱύϑΥʔϚϯε ✘ PWA
✘ CDN ✘ αʔόαΠυ ࠓ͢͜ͱ Agenda
A brief introduction of Loading Performance
Loading Performance ϏδωεΠϯύΫτ Business Impacts https://dexecure.com/blog/business-web-performance-slow-website-eats-up-your-revenue/
Loading Performance ΩʔϝτϦΫε Key Metrics https://developers.google.com/web/fundamentals/performance/rail
ܦిࢠ൛ͷύϑΥʔϚϯε Performance on Nikkei
LightHouse Score (Top Page) ܦిࢠ൛ͷύϑΥʔϚϯε
͠ݹ͍Λ͍ͬͯͨΒʁ ͠Windows7 & IEͩͬͨΒʁ ͠ΪΨΛ͍Ռ͍ͨͯͨ͠Βʁ ͠Wifi͕͍ڥͩͬͨΒʁ ܦిࢠ൛ͷύϑΥʔϚϯε
No Throttling ܦిࢠ൛ͷύϑΥʔϚϯε LightHouse Score (Top Page) Applied Slow 4G,
4x CPU Slowdown
- Good FMP - ཉ͍͠ίϯςϯπ͙͢ʹݟ͑ΔΑ͏ʹͳΔ - Bad TTI - ϘλϯΛԡͯ͠Ԡ͕ͳ͍
- ϓϩάϨεόʔ͕ফ͑ͳ͍ ܦిࢠ൛ͷύϑΥʔϚϯε Ͳ͏ͳΔͷ͔ How it affects
TTI ܦిࢠ൛ͷύϑΥʔϚϯε ͍ͭͰϢʔβ͔ΒͷೖྗΛड͚ΒΕΔঢ়ଶ
Bad TTI 5.7s ܦిࢠ൛ͷύϑΥʔϚϯε
https://developers.google.com/web/updates/2018/05/first-input-delay جຊతʹFirst CPU Idleͱಉ͡λΠϛϯά Long Tasks͕Ұఆ࣌ؒͳ͍ঢ়ଶ FIDͱࣅ͍ͯΔ͕ҟͳΔ ܦిࢠ൛ͷύϑΥʔϚϯε
ओͳݪҼ: (֎෦ͷ)ࠂεΫϦϓτ Main culprit: external ad scripts ࠂεΫϦϓτ
ࠂεΫϦϓτ Ad scripts ࠂεΫϦϓτ
؆୯ʹಋೖͰ͖Δ Introduce easily ࣮֬ʹදࣔ͢Δ Display certainly ਖ਼֬ʹܭଌ͢Δ Measure precisely ࠂεΫϦϓτ
- ༩͑ΒΕͨεΫϦϓτλάΛష Δ͚ͩͰಋೖͰ͖Δ - ෆมͳεΫϦϓτΛೖΓޱʹ ଟஈݺͼग़͠Λ͍ͯ͠Δ ؆୯ʹಋೖͰ͖Δ Introduce easily -
ωοτϫʔΫϦΫΤετ͕ෳ ճΔ - ίϯτϩʔϧͰ͖ͳ͍ ࠂεΫϦϓτ
- ϓϩμΫτͷίʔυʹӨڹ͞Ε ͳ͍Α͏ͳڧ͍࣮ - iframeͰදࣔ ࣮֬ʹදࣔ͢Δ Display certainly - αΠζ͕͔ͳΓॏ͍
- ࣮ߦ͔࣌ؒͳΓ͍ - `document.write()` ࠂεΫϦϓτ
- ࠂ͕Ϣʔβʹݟ͑ͯॳΊͯΠϯ ϓϨογϣϯͷϏʔίϯ͕ඈͿ - ը໘ʹೖΔ·ͰࠂΛग़͞ͳ͍ ਖ਼֬ʹܭଌ͢Δ Measure precisely - `onScroll`
Ͱࢹ - `img` λάͷsrc ࠂεΫϦϓτ
ͬͺΓࠂͭΒ͍ɺͰ֎ͤͳ͍
ࠂεΫϦϓτͷ࠷దԽ Advertisement Performance τϨʔυΦϑʁ Trade off?
ࠂεΫϦϓτͷ࠷దԽ Ad Scripts Optimization ࠂεΫϦϓτͷ࠷దԽ
ԿΛ͍ͯ͠Δͷ͔͔Βͳ͍ υΩϡϝϯτ͕ͳ͍ ͪ͜ΒଆͰมߋͰ͖ͳ͍ ࠂεΫϦϓτͷ࠷దԽ
ԿΛ͍ͯ͠Δͷ͔͔Βͳ͍ υΩϡϝϯτ͕ͳ͍ ͪ͜ΒଆͰมߋͰ͖ͳ͍ ͦΕͰͰ͖Δ͜ͱ͋Δ ࠂεΫϦϓτͷ࠷దԽ
minify͞ΕͨίʔυΛಡΉ debuggerͰॲཧΛ͏ ࠂεΫϦϓτͷ࠷దԽ
1. εΫϦϓτΛݺͼग़͢ॲཧΛ୳͢ 2. ଟஈʹݺͼग़͞ΕΔεΫϦϓτΛμϯϩʔυ 3. ݺͼग़͠෦Λ௵͢ 4. 1ϑΝΠϧʹ࿈݁ͯ͠minify 5. Fastly͔Β৴
Build ࠂεΫϦϓτͷ࠷దԽ
const bundledScripts = [] const script = await fetch(AD_ENTRY_URL) const
nextScriptURL = script.match(NEXT_URL_REGEX) bundledScripts.push( script.replace( 'createElement("script")', 'createElement("div")' ) ) const nextScript = fetch(nextScriptURL) // … minify(bundledScripts.join('')) Build ࠂεΫϦϓτͷ࠷దԽ
ίϯτϩʔϥɿࠂSDKΛϥοϓ Ϗϡʔɿ֤ΫϦΤΠςΟϒͷදࣔ෦ΛiframeͰϥοϓ Encapsulate ࠂεΫϦϓτͷ࠷దԽ
Encapsulate Controller View (iframe) View (iframe) View (iframe) Ad Server
ࠂεΫϦϓτͷ࠷దԽ
- ίϯτϩʔϥɿSDKͷಈ͖Λ੍ - e.g. `onScroll` -> `IntersectionObserver` - ϏϡʔɿࠂϨεϙϯεΛड͚औΓऔಘͨ͠ ΫϦΤΠςΟϒͷHTMLΛύʔε
- e.g. `document.write` Override ࠂεΫϦϓτͷ࠷దԽ
Off The Main Thread - UIͷදࣔʹؔ͢ΔͷҎ֎WebWorkerͰ - ࠂͷϦΫΤετύʔεΛWorkerͷεϨουͰॲ ཧ͍ͨ͠ -
ࠂεΫϦϓτ͕ݺͿϦΫΤετΛੳͯ͠ɺ WorkerଆͰϦΫΤετΛΈཱͯΔॲཧΛॻ͘ ࠂεΫϦϓτͷ࠷దԽ
import * as Comlink from ‘comlink’ // worker.js const request
= () => { const url = new URL('AD_SERVER_ENDPOINT') url.searchParams = { /*...*/ } return fetch( url.toString(), { headers: { /*...*/ } } ).then((res) => res.json()) } Comlink.expose(request) // main.js const request = Comlink.wrap( new Worker(paths.controllerWorker) ) // ... if (useWorker) { request(sectionId).then(renderAd) } Off The Main Thread ࠂεΫϦϓτͷ࠷దԽ
Off The Main Thread ࠂεΫϦϓτͷ࠷దԽ
ࠂઈରʹग़͞ͳͯ͘ͳΒͳ͍ but… छʑͷ࠷దԽࢪࡦʹΑͬͯ༧ظͤ͵ΫϦΤΠςΟϒͰ දࣔʹࣦഊ͢Δ͜ͱ͕͋Δ
Robustness Performance τϨʔυΦϑʁ Trade off? ࠷దԽ
࠷దԽ Deoptimization ࠷దԽ
Ͳ͔͜ͰҰͰॲཧʹࣦഊͨ͠ͱ͖ ͔ͦ͜Βਖ਼نͷॲཧʹΓସ࣮͑ͯߦ if (!expectedData) { deoptimize() } try { process()
} catch { deoptimize() } ࠷దԽ ࣦഊ࣌ͷϑΥʔϧόοΫ Fallback on failure
Optimized Ad Handler Ad Ad Ad Deoptimize Default Ad Handler
ࣦഊ࣌ͷϑΥʔϧόοΫ Fallback on failure ࠷దԽ
2nd-level ࠷దԽ Dynamic Deoptimization optimized 3rd-level default
- ෳͷ࠷దԽϨϕϧΛઃఆ - σϑΥϧτ࠷ߴ͍Ϩϕϧ - ϙΠϯτͱͳΔՕॴͰͷॲཧʹࣦഊͨ͠ΒɺҰͭϨ ϕϧΛԼ͛ͯܧଓ - ABςετͰσϑΥϧτϨϕϧΛ͚Ε ֤Ϩϕϧͷ࠷దԽॲཧͷΠϯύΫτޭΛଌΕ
Δɺͱ͍͏෭࣍తͳϝϦοτ ࠷దԽ Dynamic Deoptimization
ύϑΥʔϚϯεΛ͍ٻΊΔͱɺ ։ൃମݧ͕͘ͳΔέʔε͋Δ
ϑϩϯτΤϯυઃܭͷ৽ Developer Experience Performance τϨʔυΦϑʁ Trade off?
- จࣈྻςϯϓϨʔτ & VanillaJSͭΒ͍ - όάग़͍͢ - ։ൃऀͷࢀೖোนʹͳΔ ϞμϯͳϑϨʔϜϫʔΫͰ҆৺ɾշదʹ։ൃ͍ͨ͠ ϑϩϯτΤϯυઃܭͷ৽
ύϑΥʔϚϯεͷཪͰ Behind the scenes
ϑϩϯτΤϯυઃܭͷ৽ Redesigning Frontend ϑϩϯτΤϯυઃܭͷ৽
Frontend Backend VanillaJS ϑϩϯτΤϯυઃܭͷ৽ Handlebars ~ 2018
ϑϩϯτΤϯυઃܭͷ৽ Frontend Backend JSX VanillaJS Handlebars ~ 2018 2019 ~
ϑϩϯτΤϯυઃܭͷ৽ Backend Frontend JSX VanillaJS VanillaJS Handlebars ~ 2018 2019
~
- جຊతʹCSR͠ͳͯ͘Α͍ - Universalͳίϯϙʔωϯτ࣮ඞཁͳ͍ - ͱ͍͑ΠϯλϥΫγϣϯཁૉগͳ͘ͳ͍ - ը૾ͷLazyloadɺ ࣌ͷ૬ରදࣔɺ֤छϘλϯ… ϑϩϯτΤϯυઃܭͷ৽
੩తͳαΠτ Static websites is …
ϑϩϯτΤϯυઃܭͷ৽ ඞཁͷͳ͍ͷ Dispensable stuff Components State React
VNode VNode VNode VNode Building Virtual DOM Tree ϑϩϯτΤϯυઃܭͷ৽ Hydration
ඞཁͷͳ͍ͷ Dispensable stuff
ϑϩϯτΤϯυઃܭͷ৽ WebComponents/ CustomElements ✔ ϥΠϒϥϦෆཁ ✔ ωΠςΟϒ࣮ ✔ Webඪ४ ✔
ੜDOMૢ࡞ͱൺͯΔ͔ʹָ ✔ SSRͷ࣮ͱᴥᴪ͕ͳ͍
ϑϩϯτΤϯυઃܭͷ৽ WebComponents/ CustomElements export const Card = (props) => (
<div class=“card"> <p>{props.title}</p> <nikkei-time> {props.publishedAt} </nikkei-time> <nikkei-picture> {props.thumbnail} </nikkei-picture> </div> )
·ͱΊ Summary
ۜͷؙଘࡏ͠ͳ͍ τϨʔυΦϑ͕͋ͬͯఘΊͳ͍ Կ͕ඞཁͳͷ͔ ԿΛ͖͢ͳͷ͔ Ͱ͖Δ͜ͱΛண࣮ʹ͍ͬͯ͘ ·ͱΊ
͋Γ͕ͱ͏͍͟͝·ͨ͠ Thank you