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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Jonathan Mills
October 10, 2018
Technology
77
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Progressive Web Apps with React
Jonathan Mills
October 10, 2018
More Decks by Jonathan Mills
See All by Jonathan Mills
Javascript’s scary side
jonathanfmills
0
510
Keeping Up
jonathanfmills
1
240
Other Decks in Technology
See All in Technology
取引先から届く 「セキュリティチェックシート」の読み解き方
kamadamakoto
0
140
ガバメントクラウドでのランサムウェア対策
techniczna
2
1.1k
生成 AI の基礎 〜 サンプル実装で学ぶ基本原理
enakai00
7
4.4k
クラウドセキュリティ入門 ~安全なクラウド利用のための基礎知識~
lhazy
13
8.6k
日本語を汚染するAI
route250
1
120
つくって納得、つかって実感! 大規模言語モデルことはじめ ver2.0
recruitengineers
PRO
4
1.5k
え?フロントエンドエンジニアの ワイがインフラも!?
puku0x
1
510
【CEDEC2026】グラフィックスエンジニアのためのニューラルシェーディング入門
cygames
PRO
0
140
『三匹の子ぶた』から学ぶネットワークセキュリティの昔と今 / Network Security: Then and Now Through the Lens of The Three Little Pigs
nttcom
1
1.8k
システム思考で問題に対処する
yussak
0
240
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
19k
JavaScript 研修 (2026)
recruitengineers
PRO
2
520
Featured
See All Featured
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
610
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
340
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
The browser strikes back
jonoalderson
0
1.5k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
Ruling the World: When Life Gets Gamed
codingconduct
0
290
YesSQL, Process and Tooling at Scale
rocio
174
15k
Faster Mobile Websites
deanohume
310
32k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
3
430
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