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
日経電子版へのPWA導入事例
Search
Ryo yasuda
October 31, 2018
Programming
1
330
日経電子版へのPWA導入事例
Ryo yasuda
October 31, 2018
Tweet
Share
More Decks by Ryo yasuda
See All by Ryo yasuda
GKE+Istio+GitOpsで作る日経電子版の次世代マイクロサービス基盤
ryysd
3
2k
Microservices on Fastly v1.1
ryysd
2
1.1k
Microservices on Fastly
ryysd
42
22k
Other Decks in Programming
See All in Programming
新宿駅構内を三人称視点で探索してみる
satoshi7190
2
120
5分で理解する SOLID 原則 #phpcon_nagoya
shogogg
1
300
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
860
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
40
16k
Serverless Rust: Your Low-Risk Entry Point to Rust in Production (and the benefits are huge)
lmammino
1
150
15分で学ぶDuckDBの可愛い使い方 DuckDBの最近の更新
notrogue
3
490
Formの複雑さに立ち向かう
bmthd
1
930
Jakarta EE meets AI
ivargrimstad
0
320
Rubyと自由とAIと
yotii23
6
1.7k
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
5
960
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
140
Djangoアプリケーション 運用のリアル 〜問題発生から可視化、最適化への道〜 #pyconshizu
kashewnuts
1
260
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
80
8.9k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
570
Statistics for Hackers
jakevdp
797
220k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
46
2.3k
Raft: Consensus for Rubyists
vanstee
137
6.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Fontdeck: Realign not Redesign
paulrobertlloyd
83
5.4k
Automating Front-end Workflow
addyosmani
1368
200k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.3k
Writing Fast Ruby
sferik
628
61k
GraphQLとの向き合い方2022年版
quramy
44
14k
Transcript
ܦిࢠ൛ͷPWAಋೖࣄྫ ຊܦࡁ৽ฉࣾ ҆ా ཽ "84%FW%BZ
ࣗݾհ ҆ా ཽ (ͩ͢ Γΐ͏) 2015: NTTݚڀॴ ೖࣾ - ίϯςφܕԾԽٕज़ؔ࿈ͷݚڀʹैࣄ
2016: ຊܦࡁ৽ฉࣾ ೖࣾ - ܦిࢠ൛ϦχϡʔΞϧ൛ ։ൃϝϯόʔ - ϑϩϯτΤϯυɾόοΫΤϯυɾΠϯϑϥॾʑ୲ Α͘ॻ͘ݴޠ: js, golang, python
ܦిࢠ൛ 20103݄ץ ຖ900ຊͷهࣄΛ৴ ༗ྉձһ54ສਓҎ্ɾແྉձһ300ສਓҎ্ ݄ؒ3ԯΞΫηε
ܦిࢠ൛ ϦχϡʔΞϧ ϓϩδΣΫτ (r.nikkei) SPAഇࢭ UI/UXվળ (PWAԽɾϨεϙϯγϒԽ) MicroservicesΞʔΩςΫνϟͷ࠾༻
ϦχϡʔΞϧʹΑΔޮՌ Before After
ϦχϡʔΞϧʹΑΔޮՌ •58% better conversion rate •40% more daily active user
•2x faster Speed Index •14 seconds faster Time-To-Interactive •2.3x organic traffic
PWA(Progressive Web Application)ͱ ωΠςΟϒΞϓϦΆ͍UXΛఏڙ͢ΔWebΞϓϦ
PWAͱ – GoogleʹΑΔఆٛ • Fast • ϖʔδͷϩʔυɾԠ͕͍ • Reliable •
ωοτϫʔΫঢ়گʹґଘ͠ͳ͍(ΦϑϥΠϯͰར༻Մೳ) • Engaging • ϓογϡ௨ • ϗʔϜը໘ͷՃ https://developers.google.com/web/progressive-web-apps/checklist
ܦʹ͓͚ΔPWA • Fast • ϦχϡʔΞϧલͷഒͷදࣔ • Reliable • τοϓͷهࣄͳͲΦϑϥΠϯͰӾཡՄ •
Engaging • ϓογϡ௨ • ϗʔϜը໘ͷՃ
Fast
ϑΝʔετϏϡʔදࣔͷ࠷దԽ • ϑΝʔετϏϡʔ • WebϖʔδΛ։͍ͨ࣌࠷ॳʹݟ͑ΔྖҬ • ͜ͷྖҬͷදࣔʹؔΘΔॲཧΛ࠷༏ઌ
ϑΝʔετϏϡʔදࣔͷ࠷దԽ – PRPLύλʔϯ • Push: ϑΝʔετϏϡʔͷඳըʹඞཁͳϦιʔεΛPush • Render: ϑΝʔετϏϡʔΛඳը •
Pre-cache: ࣍ʹඞཁͳϦιʔεϖʔδΛPre-cache • Lazyload: ϑΝʔετϏϡʔ֎ͷίϯςϯπΛLazyload *Googleͷఏএ͢ΔSPAΛલఏͱͨ͠PRPLύλʔϯͱҟͳΔͷͷࢀߟʹ͍ͯ͠Δ
ϑΝʔετϏϡʔදࣔͷ࠷దԽ – PRPLύλʔϯ • Push: ϑΝʔετϏϡʔͷඳըʹඞཁͳϦιʔεΛPush • Render: ϑΝʔετϏϡʔΛඳը •
Pre-cache: ࣍ʹඞཁͳϦιʔεϖʔδΛPre-cache • Lazyload: ϑΝʔετϏϡʔ֎ͷίϯςϯπΛLazyload *Googleͷఏএ͢ΔSPAΛલఏͱͨ͠PRPLύλʔϯͱҟͳΔͷͷࢀߟʹ͍ͯ͠Δ
HTTP/2 Server Push ΫϥΠΞϯτ͔ΒͷϦΫΤετແ͠ʹαʔό͔Βσʔλૹ৴ ΫϥΠΞϯτ αʔό ΫϥΠΞϯτ αʔό index.html bundle.js
bundle.css index.html index.html bundle.js bundle.css Pushແ͠ Push༗Γ
HTTP/2 Server Push Pushແ͠ Push༗Γ ϖʔδͷμϯϩʔυޙʹjsɾcssΛμϯϩʔυ ϖʔδͷμϯϩʔυͱฒߦͯ͠jsɾcssΛμϯϩʔυ
• HTTP/2 Server H2OΛར༻ • Link HeaderʹϦιʔεΛهड़͢ΔͱPushͯ͘͠ΕΔ HTTP/2 Server Push
Origin Server H2O Client Link:<bundle.js>;rel=preload;, <bundle.css>; rel=preload; Push: bundle.css Push: bundle.js
• Fastly(CDN)͕LinkϔομΛͬͨPushΛαϙʔτ • r.nikkeiͰFastlyͬͯͨͷͰPushͷಋೖͷखؒখ͍͞ HTTP/2 Server Push Origin Server Fastly
(CDN) Client Link:<bundle.js>;rel=preload;, <bundle. css>; rel=preload; Push: bundle.css Push: bundle.js
ϑΝʔετϏϡʔදࣔͷ࠷దԽ – PRPLύλʔϯ • Push: ϑΝʔετϏϡʔͷඳըʹඞཁͳϦιʔεΛPush • Render: ϑΝʔετϏϡʔΛඳը •
Pre-cache: ࣍ʹඞཁͳϦιʔεϖʔδΛPre-cache • Lazyload: ϑΝʔετϏϡʔ֎ͷίϯςϯπΛLazyload *Googleͷఏএ͢ΔSPAΛલఏͱͨ͠PRPLύλʔϯͱҟͳΔͷͷࢀߟʹ͍ͯ͠Δ
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS Continue Building DOM Render Page GET html Response Response Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page GET html
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
GET html Response
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
GET html Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS GET html Response Response Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS Continue Building DOM GET html Response Response Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS Continue Building DOM Render Page GET html Response Response Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS Continue Building DOM Render Page GET html Response Response Response GET css GET js CSSϒϩοΩϯά JSϒϩοΩϯά
Render – Critical CSS • ϑΝʔετϏϡʔʹඞཁͳCSSͷΈΛinlineͰຒΊࠐΉ ɾ ɾ ɾ ←ͷදࣔʹඞཁͳ࠷ݶͷCSSΛ
HTMLʹຒΊࠐΉ ←ͷCSSը໘දࣔޙʹಡΈࠐΉ
Render – Critical CSS • ϑΝʔετϏϡʔʹඞཁͳCSSͷΈΛinlineͰຒΊࠐΉ • CSSऔಘʹඞཁͳϦΫΤετΛݮΒͤΔ • CSSOMߏஙɾϨΠΞτͷ࣌ؒΛݮͰ͖Δ
Render – Critical CSS • ҎલπʔϧͰࣗಈੜ͍ͯͨ͠ (https://github.com/addyosmani/critical) • ඞཁͳCSS༷ʑͳ݅ͰมΘΔͷͰࣗಈੜͰ͍͠ •
ݱࡏਓखͰඞཁͳCSSΛཧ هࣄ༰ʹΑͬͯϑΝʔετϏϡʔʹೖΔཁૉ͕ඍົʹมΘΔ
Render – async/defer <script src= ”/bundle.js” async> <script src=”/bundle.js” defer>
• r.nikkeinon-SPA+SSRͳͷͰϑΝʔετϏϡʔදࣔʹjsෆཁ • jsͷ࣮ߦը໘දࣔޙͰे • async/deferͰjsͷಡΈࠐΈɾ࣮ߦλΠϛϯάΛมߋ
Render – async/defer ύʔα͕scriptλάʹ౸ୡ HTMLύʔεྃ DOMContentLoaded default https://html.spec.whatwg.org/multipage/scripting.html#attr-script-async HTMLύʔε JSμϯϩʔυ
JS࣮ߦ
Render – async/defer ύʔα͕scriptλάʹ౸ୡ HTMLύʔεྃ DOMContentLoaded default async https://html.spec.whatwg.org/multipage/scripting.html#attr-script-async HTMLύʔε
JSμϯϩʔυ JS࣮ߦ
Render – async/defer ύʔα͕scriptλάʹ౸ୡ HTMLύʔεྃ DOMContentLoaded default async defer https://html.spec.whatwg.org/multipage/scripting.html#attr-script-async
HTMLύʔε JSμϯϩʔυ JS࣮ߦ jsͷDLɾ࣮ߦʹΑΔ ϒϩοΩϯάΛճආ
Render – Critical Rendering Pathͷ࠷దԽ Request Page Start building DOM
Build CSSOM Run JS Continue Building DOM Render Page GET html Response Response Response GET css GET js
Render – Critical Rendering Pathͷ࠷దԽ Request Page Build CSSOM Run
JS Continue Building DOM Render Page GET Html + Critical CSS Response Response GET js Start building DOM
ϑΝʔετϏϡʔදࣔͷ࠷దԽ – PRPLύλʔϯ • Push: ϑΝʔετϏϡʔͷඳըʹඞཁͳϦιʔεΛPush • Render: ϑΝʔετϏϡʔΛඳը •
Pre-cache: ࣍ʹඞཁͳϦιʔεϖʔδΛPre-cache • Lazyload: ϑΝʔετϏϡʔ֎ͷίϯςϯπΛLazyload *Googleͷఏএ͢ΔSPAΛલఏͱͨ͠PRPLύλʔϯͱҟͳΔͷͷࢀߟʹ͍ͯ͠Δ
Pre-cache Ϣʔβ͕࣍ʹඞཁͱ͢ΔίϯςϯπΛࣄલʹΩϟογϡ
Pre-cache – ServiceWorker • ϒϥβ্ʹଘࡏ͢ΔϓϩΩγαʔόΈ͍ͨͳͷ • jsͰॊೈʹΩϟογϡͷ੍ޚ͕Մೳ • ΦϑϥΠϯͰΩϟογϡʹΞΫηεՄೳ ϒϥβ
Service Worker Cache Network
Pre-cache – ServiceWorkerͷޮՌͷҰྫ ServiceWorkerແ͠ ServiceWorker༗Γ
Pre-cache – Ωϟογϡઓུ • τοϓϖʔδே༦ץͷهࣄͳͲΛΩϟογϡ • ճ༡͠ͳ͍Ϣʔβʹpre-cache͠ͳ͍ • େ͖ͳίϯςϯπwifiଓ࣌ͷΈΩϟογϡ NetworkInformation
APIͰwifiଓঢ়گ֬ೝ
Pre-cache Service Workerॊೈ͚ͩͲख͔͔ؒΔ
Pre-cache – ΩϟογϡͷTTLཧ • ݹ͍ΩϟογϡΛআͯ͘͠ΕͨΓ͠ͳ͍ͷͰࣗલ࣮ • URLͱtimestampΛIndexed DBʹอଘ • Ωϟογϡߋ৽࣌ʹtimestampൺֱͯ͠ݹ͚Εআ
Pre-cache – Ωϟογϡͷಉظ • Ϣʔβͷೝূঢ়ଶ͕มԽͨ͠ࡍʹෆ߹͕ੜ͡Δ • ϩάΞτͯ͠ϩάΠϯঢ়ଶͷΩϟογϡ͕දࣔ͞ΕΔ • ༗ྉձһʹͳͬͯແྉձһ࣌ͷΩϟογϡ͕දࣔ͞ΕΔ etc…
Pre-cache – Ωϟογϡͷಉظ • ϩάΠϯ/ϩάΞτΛݕͯ͠Ωϟογϡআ • ձһঢ়ଶΛࢹͯ͠ɺมԽ͕͋ͬͨΒΩϟογϡআ Ϣʔβ͕ ༗ྉձһԽ ϒϥβ
Service Worker Auth Status API purge ݖݶͷมԽΛݕ
Resource Hints • ࣍ʹඞཁͱͳΔϦιʔεΛࣄલʹ४උ͢ΔͨΊͷAPI • dns-prefetch: DNSʹΑΔ໊લղܾΛࣄલʹߦ͏ • preconnect :
TCPଓΛࣄલʹߦ͏ • prefetch : ࣄલʹίϯςϯπΛऔಘͯ͠Ωϟογϡ • prerender : ϖʔδશମΛࣄલʹϨϯμϦϯά ྫ: <link rel="preconnect" href="//example.com">
Resource Hints - ே༦ץϖʔδͷprefetch • ϢʔβͷಡΜͰ͍Δ໘ͷ࣍ͷ໘Λprefetch • URLݻఆɾϦιʔε͕੩తͳͷͰprefetch͍͢͠ Prefetchແ͠: ServerSide+Clientͷoverhead
Prefetch༗Γ: overheadແ͠
Resource Hints – ֎෦ίϯςϯπͷpreconnect • ࠂͷ֎෦ίϯςϯπͰར༻͞ΕΔυϝΠϯpreconnect • ίϯςϯπURL͕ಈతͰprefetchͮ͠Β͍ : DNSʹΑΔ໊લղܾ
ᒵ: TCP handshake ࢵ: SSL handshake փ: ࣮σʔλͷऔಘ
Resource Hints – ಈతͳprerender • Ϣʔβ͕࣍ʹ։͜͏ͱ͍ͯ͠ΔϖʔδΛprerender • ϚεΧʔιϧ͕ϦϯΫʹ͍ۙͮͨΒlinkλάΛૠೖ • λϒΓସ͑ͱಉ͡ͰϖʔδભҠ
LinkλάΛૠೖ
ϑΝʔετϏϡʔදࣔͷ࠷దԽ – PRPLύλʔϯ • Push: ϑΝʔετϏϡʔͷඳըʹඞཁͳϦιʔεΛPush • Render: ϑΝʔετϏϡʔΛඳը •
Pre-cache: ࣍ʹඞཁͳϦιʔεϖʔδΛPre-cache • Lazyload: ϑΝʔετϏϡʔ֎ͷίϯςϯπΛLazyload *Googleͷఏএ͢ΔSPAΛલఏͱͨ͠PRPLύλʔϯͱҟͳΔͷͷࢀߟʹ͍ͯ͠Δ
Lazyload ϑΝʔετϏϡʔपลͷΈಡΈࠐΈ PlaceholderΛૠೖ ࣮σʔλΛಡΈࠐΈ • DOMϊʔυͷେ͖͞ɾਂ͞Λ͑ͯߴԽ
ύϑΥʔϚϯεϞχλϦϯά • ϑΝΠϧαΠζϨϯμϦϯάऴྃ࣌ؒͳͲΛࢹ • Ұఆͷਫ४ΛԼճͬͨΒslackʹ௨
Reliable
ΦϑϥΠϯͰهࣄ͕ӾཡͰ͖Δ ϒϥβ Service Worker Cache Network Offlineͷ߹ ServiceWorkerͷΩϟογϡฦ͢
ΦϑϥΠϯͰϢʔβߦಈΛτϥοΩϯάͰ͖Δ • Background Sync • ΦϑϥΠϯ࣌ʹૹ৴ͨ͠ϦΫΤετΛΦϯϥΠϯ෮ؼ࣌ʹ࠶ૹ • τϥοΩϯά༻ͷσʔλΛBackground SyncͰૹ৴ •
ΦϑϥΠϯ࣌ͷهࣄอଘɾίϝϯτߘͳͲʹԠ༻Մೳ ϦΫΤετΛ อଘ ϒϥβ Indexed DB Server Service Worker Background Sync ͷొ ΦϯϥΠϯ෮ؼ·Ͱػ ϦΫΤετΛ ૹ৴
Engaging
ϗʔϜը໘ͷՃ • ϫϯλοϓͰΞΫηεՄೳ • ωΠςΟϒΞϓϦͬΆ͍ݟͨ web manifestΛొ͢ΔͱϗʔϜը໘ొՄೳ
ϗʔϜը໘ͷՃ • ϗʔϜը໘͔Βىಈ͞Εͨ߹ʹΩϟογϡྔ૿͢ • ΑΓαΫαΫಈ͔ͨ͢Ί • ϗʔϜը໘͔Βͷىಈnavigator.standaloneͰผՄೳ
Push௨ • ใ௨ʹར༻ • एϝʔϧΑΓ։෧͕ߴ͍ • ػցֶशʹΑΔΫϦοΫ࠷େԽ ͳͲΛݕ౼த
Service Workerͷ։ൃ
Workboxͷஔ͖͑ • ࠷ۙ·ͰϑϧεΫϥονͰॻ͍͍͕ͯͨϝϯς͕͖͍ͭ • ΩϟογϡͷTTLͳͲɺΩϟογϡཧશͯࣗྗ࣮ • IDBͬͯtimestampཧ͢Δͷͱ͔໘… GoogleͷServiceWorker։ൃ༻ͷϥΠϒϥϦɾπʔϧ
WorkboxͰग़དྷΔ͜ͱ – TTLͷ࣮ྫ WorkboxΛར༻͠ͳ͍߹ WorkboxΛར༻ͨ͠߹
WorkboxͰग़དྷΔ͜ͱ • SWͰΓ͍ͨجຊతͳࣄ֓Ͷ࣮͞Ε͍ͯΔ • Precaching • Runtime caching • Cache
Strategies (stale-while-revalidateͱ͔) • Request routing • Background sync • ϩά͕Ͱڍಈ͕ͱͯΘ͔Γ͍͢
ServiceWorkerͷςετ • seleniumͰෳϒϥβͰͷࣗಈςετΛ࣮ߦ • ServiceWorker༻ͷUnit/E2EςετϔϧύΛར༻ • https://github.com/GoogleChromeLabs/sw-testing-helpers • Ͱ͏ϝϯς͞Εͯͳͦ͞͏…
·ͱΊ • ܦిࢠ൛PWAԽͰCVRɾDAUଟ͘ͷࢦඪ͕վળͨ͠ • PWAԽͰϑΝʔετϏϡʔͷදࣔΛॏࢹ • දࣔվળͰPRPLύλʔϯΛࢀߟ • ύϑΥʔϚϯεܧଓతʹվળ͕ඞཁ •
ServiceWorker։ൃͰworkboxsw-testing-helper͕ศར
͋Γ͕ͱ͏͍͟͝·ͨ͠