Maxim Salnikov
@webmaxru
What is an offline-ready web application
Developer Audience Lead at Microsoft
My App
App
Service worker
Browser/OS
Event-driven worker
Cache
fetch
push
sync
self.addEventListener('install', event => {
// Use Cache API to cache html/js/css
})
self.addEventListener('activate', event => {
// Clean the cache from the obsolete versions
})
self.addEventListener('fetch', event => {
// Serve assets from cache or network
})
# Installing the Workbox Node module
$ npm install workbox-build --save-dev
// Sample configuration with the basic options
var workboxConfig = {
globDirectory: 'dist/',
globPatterns: [
'**/*.{txt,png,ico,html,js,json,css}'
],
swSrc: 'src/workbox-service-worker.js',
swDest: 'dist/sw.js'
}
import { precacheAndRoute } from "workbox-precaching";
// Precaching and setting up the routing
precacheAndRoute(self.__WB_MANIFEST)
Caching, serving, managing versions
// We will use injectManifest mode
const {injectManifest} = require('workbox-build')
// Sample configuration with the basic options
var workboxConfig = {...}
// Calling the method and output the result
injectManifest(workboxConfig).then(({count, size}) => {
console.log(`Generated ${workboxConfig.swDest},
which will precache ${count} files, ${size} bytes.`)
})
{
"scripts": {
"build-sw": "node workbox-build.js && npx rollup -c",
"build": "npm run build-app && npm run build-sw"
}
}
self.addEventListener('fetch', event => {
if (event.request.url.indexOf('/api/breakingnews') != -1) {
event.respondWith(
// Network-First Strategy
)
} else if (event.request.url.indexOf('/api/archive') != -1 {
event.respondWith(
// Cache-First Strategy
)
}
})
import { registerRoute } from "workbox-routing";
import * as strategies from "workbox-strategies";
registerRoute(
new RegExp('/api/breakingnews'),
new strategies.CacheFirst()
);
registerRoute(
new RegExp('/api/archive'),
new strategies.CacheFirst({plugins: [...]})
);
navigator.serviceWorker.ready.then( swRegistration => {
return swRegistration.sync.register('postTweet');
});
self.addEventListener('sync', event => {
if (event.tag == 'postTweet') {
event.waitUntil(
// Do useful things...
);
}
});
import {BackgroundSyncPlugin} from 'workbox-background-sync';
const postTweetPlugin =
new BackgroundSyncPlugin('tweetsQueue', {
maxRetentionTime: 24 * 60 // Max retry period
})
registerRoute(
/(http[s]?:\/\/)?([^\/\s]+\/)post-tweet/,
new strategies.NetworkOnly({plugins: [postTweetPlugin]}),
'POST'
)
const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
try {
registration.periodicSync.register('refreshTweets', {
// An interval of one day.
minInterval: 24 * 60 * 60 * 1000,
});
} catch (error) {
// PBS cannot be used.
}
}
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'refreshTweets') {
event.waitUntil(
fetchNewTweets() // Maybe
);
}
});
Maxim Salnikov
@webmaxru
Maxim Salnikov
@webmaxru