Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Offline Web Apps (Service Workers)
Search
Erik Hellman
August 03, 2017
Programming
190
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Offline Web Apps (Service Workers)
Erik Hellman
August 03, 2017
More Decks by Erik Hellman
See All by Erik Hellman
Wireless protocols for the next generation IoT devices
erikhellman
2
160
Working with Custom Android Devices and AOSP build system
erikhellman
2
700
Working with custom Android devices
erikhellman
2
530
Developing system apps without AOSP
erikhellman
2
820
State of BLE on Android in 2023
erikhellman
3
1.1k
State of BLE on Android in 2022
erikhellman
1
1.3k
The technical solutions behind Öppna Skolplattformen
erikhellman
0
290
Bluetooth Low Energy for Modern Android Development
erikhellman
1
1.1k
Introduction to Flutter
erikhellman
0
290
Other Decks in Programming
See All in Programming
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
140
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
130
不幸な GC
chencmd
0
900
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
1.9k
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
240
Family mrubyの進捗
kishima
1
110
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
6.1k
アクセシビリティから考える情報設計
high_g_engineer
0
350
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
120
新卒PdEのリアル
ryu1013
1
480
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
130
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
280
Featured
See All Featured
Paper Plane (Part 1)
katiecoart
PRO
1
11k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
370
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
890
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
450
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Into the Great Unknown - MozCon
thekraken
41
2.7k
4 Signs Your Business is Dying
shpigford
187
23k
Designing Experiences People Love
moore
143
24k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Unsuck your backbone
ammeep
672
58k
Transcript
Offline Web Apps
None
None
Lie-fi
of users abandon sites that take longer than 3 seconds
to load 53%
60% of world-wide mobile connections are 2G
Service Workers
Service Workers are a client-side proxy Service worker (written in
Javascript) Cache Web server
Service Worker Lifecycle • Adds app-like lifecycle to a page
• Wakes up only when the OS says • Only responds to system events Activated Error Idle Active Terminated Install Register
• Adds app-like lifecycle to a page • Wakes up
only when the OS says • Only responds to system events Activated Error Idle Active Terminated Install Register Service Worker Lifecycle
Service Worker Lifecycle • Adds app-like lifecycle to a page
• Wakes up only when the OS says • Only responds to system events Activated Error Idle Active Terminated Install Register
Service Worker is for the SECOND load.
Implementing a Simple Service Worker
Register the Service Worker Activated Error Idle Active Terminated Install
Register
Register the Service Worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js')
.then(function(reg) { console.log('Service Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Register the Service Worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js')
.then(function(reg) { console.log('Service Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Add an install Event Handler Activated Error Idle Active Terminated
Install Register
Add an install Event Handler self.addEventListener('install', function(event) { return self.skipWaiting();
});
Pre-fetch the App Resources Activated Error Idle Active Terminated Install
Register
Pre-fetch the App Resources var cacheName = 'app-shell-cache-v1'; var filesToCache
= ['/', '/index.html', ...]; self.addEventListener('install', function(event) { event.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll(filesToCache); }).then(function() { return self.skipWaiting(); }) ); });
Pre-fetch the App Resources var cacheName = 'app-shell-cache-v1'; var filesToCache
= ['/', '/index.html', ...]; self.addEventListener('install', function(event) { event.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll(filesToCache); }).then(function() { return self.skipWaiting(); }) ); });
Pre-fetch the App Resources var cacheName = 'app-shell-cache-v1'; var filesToCache
= ['/', '/index.html', ...]; self.addEventListener('install', function(event) { event.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll(filesToCache); }).then(function() { return self.skipWaiting(); }) ); });
Pre-fetch the App Resources var cacheName = 'app-shell-cache-v1'; var filesToCache
= ['/', '/index.html', ...]; self.addEventListener('install', function(event) { event.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll(filesToCache); }).then(function() { return self.skipWaiting(); }) ); });
Add an activate Event Handler Activated Error Idle Active Terminated
Install Register
Add an activate Event Handler self.addEventListener('activate', function(e) { e.waitUntil( caches.keys().then(function(keyList)
{ return Promise.all(keyList.map(function(key) { if (key !== cacheName) { return caches.delete(key); } })); }) ); return self.clients.claim(); });
Add an activate Event Handler self.addEventListener('activate', function(e) { e.waitUntil( caches.keys().then(function(keyList)
{ return Promise.all(keyList.map(function(key) { if (key !== cacheName) { return caches.delete(key); } })); }) ); return self.clients.claim(); });
Not Done Yet… Activated Error Idle Active Terminated Install Register
None
Add a fetch Event Handler self.addEventListener('fetch', function(e) { e.respondWith( caches.match(e.request).then(function(response)
{ return response || fetch(e.request); }) ); });
Add a fetch Event Handler self.addEventListener('fetch', function(e) { e.respondWith( caches.match(e.request).then(function(response)
{ return response || fetch(e.request); }) ); });
Add a fetch Event Handler self.addEventListener('fetch', function(e) { e.respondWith( caches.match(e.request).then(function(response)
{ return response || fetch(e.request); }) ); });
Add a fetch Event Handler self.addEventListener('fetch', function(e) { e.respondWith( caches.match(e.request).then(function(response)
{ return response || fetch(e.request); }) ); });
Ready to Go! Activated Error Idle Active Terminated Install Register
Scope if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js') .then(function(reg) { console.log('Service
Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Scope if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js') .then(function(reg) { console.log('Service
Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Scope if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/scripts/s-worker.js') .then(function(reg) { console.log('Service
Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Scope if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js') .then(function(reg) { console.log('Service
Worker Registered', reg); }) .catch(function(err) { console.log('Error registering Service Worker', err); }); }
Caching Strategies YOU are in control of the network
Cache, Falling Back to Network Page Service Worker Network Cache
X
Network, Falling Back to Cache Page Service Worker Network Cache
X
Cache, then Network Page Service Worker Network Cache
Generic Fallback Page Service Worker Network Cache X X
control You are in
Tools
Chrome Dev Tools
Chrome Dev Tools: the cache
Chrome Dev Tools: the cache
sw-toolbox
Cache first in sw-toolbox importScripts('/sw-toolbox.js'); toolbox.router.get('/(.*)', toolbox.cacheFirst, { origin: /\.googleapis\.com$/
});
sw-precache Node module
sw-precache precache.write('service-worker.js', { staticFileGlobs: ['**/*.{html,css}'], runtimeCaching: [ {urlPattern: '/', handler:
'fastest'}, {urlPattern: '/api/.*', handler: 'networkFirst', options: {networkTimeoutSeconds: 5} }, {urlPattern: '/posts/.*', handler: 'cacheFirst'}, {urlPattern: '/styles/.*', handler: 'cacheOnly'}, {urlPattern: '/inbox.json', handler: 'networkOnly'} ] });
PWA Codelab https://codelabs.developers.google.com/codelabs/your-first-pwapp
Service Workers the core underpinning Progressive Web Apps
Service Workers Web Apps will need to worry about lifecycle...
Thank You!