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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Ryo yasuda
October 31, 2018
Programming
390
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
日経電子版へのPWA導入事例
Ryo yasuda
October 31, 2018
More Decks by Ryo yasuda
See All by Ryo yasuda
GKE+Istio+GitOpsで作る日経電子版の次世代マイクロサービス基盤
ryysd
3
2.2k
Microservices on Fastly v1.1
ryysd
2
1.2k
Microservices on Fastly
ryysd
42
22k
Other Decks in Programming
See All in Programming
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
12k
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.3k
3Dシーンの圧縮
fadis
1
690
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.6k
Oxlintのカスタムルールの現況
syumai
6
1k
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
490
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
210
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
250
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
190
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
320
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
160
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
110
Featured
See All Featured
Designing for Timeless Needs
cassininazir
1
250
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
470
Embracing the Ebb and Flow
colly
88
5.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
300
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
150
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.3k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Producing Creativity
orderedlist
PRO
348
40k
Designing for humans not robots
tammielis
254
26k
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͕ศར
͋Γ͕ͱ͏͍͟͝·ͨ͠