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
2,500万ユーザーを支えるSREチームの6年間のスクラムのカイゼン
honmarkhunt
6
5.3k
SpringBoot3.4の構造化ログ #kanjava
irof
2
990
GoとPHPのインターフェイスの違い
shimabox
2
190
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.3k
『品質』という言葉が嫌いな理由
korimu
0
160
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
160
Conform を推す - Advocating for Conform
mizoguchicoji
3
690
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
120
Linux && Docker 研修/Linux && Docker training
forrep
24
4.5k
楽しく向き合う例外対応
okutsu
0
120
AIの力でお手軽Chrome拡張機能作り
taiseiue
0
170
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
590
Featured
See All Featured
It's Worth the Effort
3n
184
28k
GraphQLとの向き合い方2022年版
quramy
44
13k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Building Applications with DynamoDB
mza
93
6.2k
The Cost Of JavaScript in 2023
addyosmani
47
7.3k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
410
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
A Philosophy of Restraint
colly
203
16k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.4k
Bootstrapping a Software Product
garrettdimon
PRO
306
110k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
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͕ศར
͋Γ͕ͱ͏͍͟͝·ͨ͠