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
Progressive Web Apps with React
Search
Jonathan Mills
October 10, 2018
Technology
0
52
Progressive Web Apps with React
Jonathan Mills
October 10, 2018
Tweet
Share
More Decks by Jonathan Mills
See All by Jonathan Mills
Javascript’s scary side
jonathanfmills
0
480
Keeping Up
jonathanfmills
1
220
Other Decks in Technology
See All in Technology
20260204_Midosuji_Tech
takuyay0ne
1
130
ZOZOにおけるAI活用の現在 ~開発組織全体での取り組みと試行錯誤~
zozotech
PRO
5
4.9k
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
10k
Azure Durable Functions で作った NL2SQL Agent の精度向上に取り組んだ話/jat08
thara0402
0
150
日本の85%が使う公共SaaSは、どう育ったのか
taketakekaho
1
140
AIと新時代を切り拓く。これからのSREとメルカリIBISの挑戦
0gm
0
800
Kiro IDEのドキュメントを全部読んだので地味だけどちょっと嬉しい機能を紹介する
khmoryz
0
170
What happened to RubyGems and what can we learn?
mikemcquaid
0
250
プロポーザルに込める段取り八分
shoheimitani
1
180
2026年、サーバーレスの現在地 -「制約と戦う技術」から「当たり前の実行基盤」へ- /serverless2026
slsops
2
210
Stately
mu7889yoon
1
110
今日から始めるAmazon Bedrock AgentCore
har1101
4
400
Featured
See All Featured
Skip the Path - Find Your Career Trail
mkilby
0
53
How to Talk to Developers About Accessibility
jct
2
130
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
380
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
53
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
130
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Navigating Team Friction
lara
192
16k
How to build a perfect <img>
jonoalderson
1
4.9k
WCS-LA-2024
lcolladotor
0
450
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.7k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Transcript
@ j o n a t h a n f
m i l l s #reactPWA P R O G R E S S I V E W E B A P P S W I T H R E A C T
None
None
None
Progressive Web Apps to the rescue!
What is a PWA? RELIABLE
What is a PWA? RELIABLE FAST
What is a PWA? RELIABLE FAST ENGAGING
Demo
None
Service Workers
Have you heard of a Web Worker?
ServiceWorker != WebWorker
None
if('serviceWorker' in navigator) { navigator.serviceWorker.register('/offline.js', { scope: '/' }) .then(function(registration)
{ console.log('Service Worker Registered'); }); navigator.serviceWorker.ready .then(function(registration) { console.log('Service Worker Ready'); }); } SERVICE WORKER
INSTALL const CACHE_NAME = ‘DevUp’ // Version 0.6.5 self.addEventListener('install', e
=> { console.log('installing service worker!!') const timeStamp = Date.now(); e.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll([ `/`, `/index.html`, `/json/data.json`, `/static/js/bundle.js` ]) .then(() => self.skipWaiting()); }) ); });
INSTALL const CACHE_NAME = ‘DevUp’ // Version 0.6.5 self.addEventListener('install', e
=> { console.log('installing service worker!!') const timeStamp = Date.now(); e.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll([ `/`, `/index.html`, `/json/data.json`, `/static/js/bundle.js` ]) .then(() => self.skipWaiting()); }) ); });
INSTALL const CACHE_NAME = ‘DevUp' // Version 0.6.5 self.addEventListener('install', e
=> { console.log('installing service worker!!') const timeStamp = Date.now(); e.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll([ `/`, `/index.html`, `/json/data.json`, `/static/js/bundle.js` ]) .then(() => self.skipWaiting()); }) ); });
ACTIVATE self.addEventListener('activate', event => { console.log('activating service worker'); event.waitUntil(self.clients.claim()); });
FETCH self.addEventListener('fetch', function(event) {…})
FETCH event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return
response if (response) { return response; } var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME)
FETCH event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return
response if (response) { return response; } var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME)
FETCH event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return
response if (response) { return response; } var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME)
event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return response
if (response) { return response; } var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME) FETCH
} var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { //
Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); FETCH
} var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { //
Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); FETCH
} var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { //
Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); FETCH
} var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { //
Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic'){ return response; } var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); FETCH
Demo
None
Manifest
A manifest describes your web page in an
INDEX.HTML <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
MANIFEST { "short_name": "Library", "name": “DevUp Library Demo", "icons": [
{ "src": "book.png", "sizes": "192X192", "type": "image/png" } ], "start_url": "./index.html", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }
Demo
None
Let’s Deploy
None
Github Pages to the rescue
PACKAGE.JSON – ADDING GH-PAGES { "name": "library", "version": "0.1.0", "private":
true, "homepage": “https://jonathanfmills.github.io/DEVUPPWA”, "dependencies": { "gh-pages": "^1.1.0", … }, "scripts": { "predeploy": "npm run build", "deploy": "gh-pages -d build", } }
Demo
http://bit.ly/devuppwa
@ j o n a t h a n f
m i l l s #reactPWA P R O G R E S S I V E W E B A P P S W I T H R E A C T