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
Building PWAs using Workbox
Search
Arnelle Balane
August 01, 2020
Programming
0
220
Building PWAs using Workbox
Arnelle Balane
August 01, 2020
Tweet
Share
More Decks by Arnelle Balane
See All by Arnelle Balane
Introduction to building Chrome Extensions
arnellebalane
0
110
Color Palettes Of The Most Colorful Birds
arnellebalane
0
110
Let's build a video streaming app using Web technologies
arnellebalane
0
140
Let's build a video calling app with Web technologies and Firebase!
arnellebalane
0
140
Ridiculous Scientific Names
arnellebalane
0
220
Fishes With Terrestrial-Animal Names
arnellebalane
0
150
Making the Web more capable with Project Fugu
arnellebalane
0
110
Frontend Web Development in 2021+
arnellebalane
0
160
Extending CSS using Houdini
arnellebalane
0
110
Other Decks in Programming
See All in Programming
「テストは愚直&&網羅的に書くほどよい」という誤解 / Test Smarter, Not Harder
munetoshi
0
170
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
170
iOS 26にアップデートすると実機でのHot Reloadができない?
umigishiaoi
0
130
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
250
AI時代の『改訂新版 良いコード/悪いコードで学ぶ設計入門』 / ai-good-code-bad-code
minodriven
14
5k
レベル1の開発生産性向上に取り組む − 日々の作業の効率化・自動化を通じた改善活動
kesoji
0
220
AI時代のソフトウェア開発を考える(2025/07版) / Agentic Software Engineering Findy 2025-07 Edition
twada
PRO
87
29k
Porting a visionOS App to Android XR
akkeylab
0
470
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
510
AIプログラマーDevinは PHPerの夢を見るか?
shinyasaita
1
220
データの民主化を支える、透明性のあるデータ利活用への挑戦 2025-06-25 Database Engineering Meetup#7
y_ken
0
360
10 Costly Database Performance Mistakes (And How To Fix Them)
andyatkinson
0
340
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
20k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Typedesign – Prime Four
hannesfritz
42
2.7k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
690
A Modern Web Designer's Workflow
chriscoyier
695
190k
Fireside Chat
paigeccino
37
3.5k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Thoughts on Productivity
jonyablonski
69
4.7k
The Invisible Side of Design
smashingmag
301
51k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.3k
Transcript
Software Developer, Newlogic Arnelle Balane @arnellebalane Building PWAs using Workbox
Arnelle Balane Software Developer at Newlogic Google Developers Expert for
Web Technologies I write about Web stuff on my blog, arnellebalane.com @arnellebalane
None
Progressive Web Apps Websites built using Web technologies, and act
and feel like native apps
❖ Can be installed to the home screen ❖ Works
well even in intermittent or unreliable network conditions ❖ Works on any device ❖ Send notifications even when app is closed Progressive Web Apps
❖ Usually built using the application shell model, minimizing page
refresh ❖ Generally easier to deploy and maintain than native apps ❖ SEO, URLs, etc. Progressive Web Apps
Service Workers <script> if (navigator.serviceWorker) { window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js'); }); } </script>
Service Workers // sw.js addEventListener('install', event => { /**/ });
addEventListener('activate', event => { /**/ }); addEventListener('fetch', event => { /**/ });
❖ Service Workers ❖ Cache API ❖ Push Notifications ❖
Background Sync ❖ Background Fetch ❖ Web Application Manifest Moar APIs for our PWAs!
None
Workbox JavaScript libraries for adding offline support to Web applications
❖ from CDN ❖ Node module ❖ Webpack plugin Using
Workbox
Credits to Afrian Hanafi dribbble.com/shots/13125619-Makers-Workshop-Concept-II
Credits to Afrian Hanafi dribbble.com/shots/13125619-Makers-Workshop-Concept-II 2 pages 2 images 1
stylesheet 1 script
Import the library // sw.js importScripts('https://storage.googleapis.com/workbox-cdn/ releases/5.1.2/workbox-sw.js');
Precache site assets (deprecated) workbox.precaching.precache([ '/', '/classes', '/index.css', '/index.js', '/images/image-01.jpg',
'/images/image-02.jpg' ]);
Precache site assets, with versioning workbox.precaching.precache([ {url: '/', revision: 'v1'},
{url: '/classes', revision: 'v1'}, {url: '/index.css', revision: 'v1'}, {url: '/index.js', revision: 'v1'}, {url: '/images/image-01.jpg', revision: 'v1'}, {url: '/images/image-02.jpg', revision: 'v1'} ]);
Verify cache in Chrome Devtools
Y u no work?
Route precached assets workbox.precaching.precache([ /* ... */ ]); workbox.precaching.addRoute();
Precache and route site assets workbox.precaching.precacheAndRoute([ {url: '/', revision: 'v1'},
{url: '/classes', revision: 'v1'}, {url: '/index.css', revision: 'v1'}, {url: '/index.js', revision: 'v1'}, {url: '/images/image-01.jpg', revision: 'v1'}, {url: '/images/image-02.jpg', revision: 'v1'} ]);
Now it works offline!
Precaching Adding items to the cache in advance, even before
they are used
Gradually adding items to the cache as they are requested
Runtime caching
Cache a specific URL at runtime workbox.routing.registerRoute( '/images/image-01.jpg', new workbox.strategies.NetworkFirst()
);
Verify cache in Chrome Devtools
Cache a URL pattern at runtime workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.NetworkFirst()
);
Runtime caching using a “match callback” workbox.routing.registerRoute( (context) => context.url.origin
=== 'https://arnelle.me', new workbox.strategies.NetworkFirst() ); workbox.routing.registerRoute( (context) => context.request.destination === 'image', new workbox.strategies.NetworkFirst() );
Runtime caching https://developers.google.com/web/tools/workbox/reference-docs /latest/module-workbox-routing Precaching https://developers.google.com/web/tools/workbox/reference-docs /latest/module-workbox-precaching More Info
Workbox provides simple implementations for common service worker caching strategies
Caching strategies
Network-First Image from web.dev
Network-First workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.NetworkFirst() );
Network-First workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.NetworkFirst({ networkTimeoutSeconds: 3 }) );
Cache-First Image from web.dev
Cache-First workbox.routing.registerRoute( /\.css$/, new workbox.strategies.CacheFirst() );
Stale-While-Revalidate Image from web.dev
Stale-While-Revalidate workbox.routing.registerRoute( (context) => context.url.pathname.startsWith('/blog'), new workbox.strategies.StaleWhileRevalidate() );
❖ Nothing special other than they can use Workbox Plugins
Cache-Only Network-Only
The Offline Cookbook https://developers.google.com/web/fundamentals/instant-and -offline/offline-cookbook Workbox Strategies https://developers.google.com/web/tools/workbox/reference-docs /latest/module-workbox-strategies More
Info
Additional service worker behaviours without writing more boilerplate code Workbox
plugins
❖ ExpirationPlugin ❖ BroadcastUpdatePlugin ❖ BackgroundSyncPlugin ❖ CacheableResponsePlugin ❖ RangeRequestsPlugin
Workbox plugins
Using plugins workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ plugins: [ /* plugins
here */ ] }) );
ExpirationPlugin, expire after some time workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ cacheName:
'image-cache', plugins: [ new workbox.expiration.ExpirationPlugin({ maxAgeSeconds: 10 }) ] }) );
ExpirationPlugin, custom cache name workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ cacheName: 'image-cache',
plugins: [ new workbox.expiration.ExpirationPlugin({ maxAgeSeconds: 10 }) ] }) );
ExpirationPlugin, limit number of entries workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ cacheName:
'image-cache', plugins: [ new workbox.expiration.ExpirationPlugin({ maxEntries: 1 }) ] }) );
ExpirationPlugin
ExpirationPlugin
BroadcastUpdatePlugin workbox.routing.registerRoute( /\/blog\/.+$/, new workbox.strategies.StaleWhileRevalidate({ plugins: [ new workbox.broadcastUpdate.BroadcastUpdatePlugin() ]
}) );
BroadcastUpdatePlugin, handle in main page // index.js navigator.serviceWorker.onmessage = event
=> { if (event.data.meta === 'workbox-broadcast-update') { displayUpdateAvailableUI(); } };
BroadcastUpdatePlugin, handle in main page // index.js navigator.serviceWorker.onmessage = event
=> { if (event.data.meta === 'workbox-broadcast-update') { displayUpdateAvailableUI(); } };
BroadcastUpdatePlugin
Custom Plugins https://developers.google.com/web/tools/workbox/guides /using-plugins#custom_plugins Using Plugins https://developers.google.com/web/tools/workbox/guides /using-plugins More Info
Use Workbox with popular JavaScript frameworks. Webpack plugin
Install dependencies npm install -D workbox-webpack-plugin
GenerateSW plugin const {GenerateSW} = require('workbox-webpack-plugin'); module.exports = { /*
... */ plugins: [ new GenerateSW({ swDest: 'sw.js' }) ] };
InjectManifest plugin const {InjectManifest} = require('workbox-webpack-plugin'); module.exports = { /*
... */ plugins: [ new InjectManifest({ swSrc: './www/sw.js' }) ] };
InjectManifest plugin // sw.js importScripts('https://storage.googleapis.com/...'); workbox.precaching.precacheAndRoute([ {url: '/', revision: 'v1'},
{url: '/classes', revision: 'v1'}, {url: '/index.css', revision: 'v1'}, {url: '/index.js', revision: 'v1'} ]);
InjectManifest plugin, add injection point // sw.js importScripts('https://storage.googleapis.com/...'); workbox.precaching.precacheAndRoute( self.__WB_MANIFEST
);
InjectManifest plugin, build result // dist/sw.js importScripts('https://storage.googleapis.com/...'); workbox.precaching.precacheAndRoute([ {'revision':'b91028...','url':'index.329fc4.js'}, {'revision':'20420e...','url':'index.html'}
]);
Update service worker imports // sw.js import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute(self.__WB_MANIFEST);
Update service worker imports import {registerRoute} from 'workbox-routing'; import {StaleWhileRevalidate}
from 'workbox-strategies'; import {BroadcastUpdatePlugin} from 'workbox-broadcast-update'; registerRoute( /\/blog\/.+$/, new StaleWhileRevalidate({ plugins: [new BroadcastUpdatePlugin()] }) );
Webpack plugin reference https://developers.google.com/web/tools/workbox/reference-doc s/latest/module-workbox-webpack-plugin Using bundlers with Workbox https://developers.google.com/web/tools/workbox/guides
/using-bundlers More Info
a.k.a I didn’t know where to put these content so
I’ll just put them at the end... Common recipes
Cache Google Fonts workbox.routing.registerRoute( (context) => context.url.origin === 'https://fonts.googleapis.com', new
workbox.strategies.StaleWhileRevalidate({ cacheName: 'google-fonts-stylesheets' }) );
Cache Google Fonts workbox.routing.registerRoute( (context) => context.url.origin === 'https://fonts.gstatic.com', new
workbox.strategies.CacheFirst({ cacheName: 'google-fonts-webfonts', plugins: [ new workbox.expiration.ExpirationPlugin({ maxAgeSeconds: 60 * 60 * 24 * 365, // one year maxEntries: 30 }) ] }) );
Generic fallbacks
Generic fallbacks
Generic fallbacks, precache fallback image workbox.precaching.precache([ {url: '/images/fallback-image.png', revision: 'v1'},
]);
Generic fallbacks, route all images workbox.precaching.precache([ {url: '/images/fallback-image.png', revision: 'v1'},
]); workbox.routing.registerRoute( (context) => context.request.destination === 'image', new workbox.strategies.NetworkOnly() );
Generic fallbacks workbox.routing.setCatchHandler(async context => { if (context.request.destination === 'image')
{ return workbox.precaching.matchPrecache( '/images/fallback-image.png' ); } });
Generic fallbacks, respond with fallback image workbox.routing.setCatchHandler(async context => {
if (context.request.destination === 'image') { return workbox.precaching.matchPrecache( '/images/fallback-image.png' ); } });
Generic fallbacks
Generic fallbacks, for other pages
Workbox https://developers.google.com/web/tools/workbox Common Recipes https://developers.google.com/web/tools/workbox/guides /common-recipes More Info
❖ Workbox caching strategies ❖ Workbox plugins ❖ Using Workbox
with Webpack ❖ Common Workbox recipes Recap!
❖ Web Application Manifest ❖ Push Notifications ❖ Background Sync
❖ Web Capabilities What’s next?
Building PWAs using Workbox Arnelle Balane That’s all for today!
Thank you!