Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building PWAs using Workbox

Building PWAs using Workbox

Arnelle Balane

August 01, 2020
Tweet

More Decks by Arnelle Balane

Other Decks in Programming

Transcript

  1. Arnelle Balane Software Developer at Newlogic Google Developers Expert for

    Web Technologies I write about Web stuff on my blog, arnellebalane.com @arnellebalane
  2. ❖ 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
  3. ❖ 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
  4. Service Workers // sw.js addEventListener('install', event => { /**/ });

    addEventListener('activate', event => { /**/ }); addEventListener('fetch', event => { /**/ });
  5. ❖ Service Workers ❖ Cache API ❖ Push Notifications ❖

    Background Sync ❖ Background Fetch ❖ Web Application Manifest Moar APIs for our PWAs!
  6. 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'} ]);
  7. 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'} ]);
  8. 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() );
  9. ExpirationPlugin, expire after some time workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ cacheName:

    'image-cache', plugins: [ new workbox.expiration.ExpirationPlugin({ maxAgeSeconds: 10 }) ] }) );
  10. ExpirationPlugin, limit number of entries workbox.routing.registerRoute( /\.jpg$/, new workbox.strategies.CacheFirst({ cacheName:

    'image-cache', plugins: [ new workbox.expiration.ExpirationPlugin({ maxEntries: 1 }) ] }) );
  11. BroadcastUpdatePlugin, handle in main page // index.js navigator.serviceWorker.onmessage = event

    => { if (event.data.meta === 'workbox-broadcast-update') { displayUpdateAvailableUI(); } };
  12. BroadcastUpdatePlugin, handle in main page // index.js navigator.serviceWorker.onmessage = event

    => { if (event.data.meta === 'workbox-broadcast-update') { displayUpdateAvailableUI(); } };
  13. InjectManifest plugin const {InjectManifest} = require('workbox-webpack-plugin'); module.exports = { /*

    ... */ plugins: [ new InjectManifest({ swSrc: './www/sw.js' }) ] };
  14. 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'} ]);
  15. 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()] }) );
  16. a.k.a I didn’t know where to put these content so

    I’ll just put them at the end... Common recipes
  17. Cache Google Fonts workbox.routing.registerRoute( (context) => context.url.origin === 'https://fonts.googleapis.com', new

    workbox.strategies.StaleWhileRevalidate({ cacheName: 'google-fonts-stylesheets' }) );
  18. 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 }) ] }) );
  19. 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() );
  20. Generic fallbacks workbox.routing.setCatchHandler(async context => { if (context.request.destination === 'image')

    { return workbox.precaching.matchPrecache( '/images/fallback-image.png' ); } });
  21. Generic fallbacks, respond with fallback image workbox.routing.setCatchHandler(async context => {

    if (context.request.destination === 'image') { return workbox.precaching.matchPrecache( '/images/fallback-image.png' ); } });
  22. ❖ Workbox caching strategies ❖ Workbox plugins ❖ Using Workbox

    with Webpack ❖ Common Workbox recipes Recap!