Maxim Salnikov
@webmaxru
Azure Developer Technical Lead at Microsoft
Progressive web apps use modern web APIs along with traditional progressive enhancement strategy to create cross-platform web applications.
* but not everything**
** use progressive enhancement strategy
"Progressive Web Apps State of the Union" by Dominick Ng at BlinkOn 10
"Progressive Web Apps State of the Union" by Dominick Ng at BlinkOn 10
April 8th
April 9-10th
May 6-8th
May 6-8th
# Installing the Workbox Node module
$ npm install workbox-build --save-dev
// Importing Workbox itself from Google CDN
importScripts('https://googleapis.com/.../workbox-sw.js');
// Precaching and setting up the routing
workbox.precaching.precacheAndRoute([])
[
{
"url": "index.html",
"revision": "34c45cdf166d266929f6b532a8e3869e"
},
{
"url": "favicon.ico",
"revision": "b9aa7c338693424aae99599bec875b5f"
},
...
]
workbox.routing.registerRoute(
new RegExp('/app/v2/'),
workbox.strategies.networkFirst()
);
workbox.routing.registerRoute(
new RegExp('/images/'),
workbox.strategies.cacheFirst({
plugins: [...]
})
);
const postTweetPlugin =
new workbox.backgroundSync.Plugin('tweetsQueue', {
maxRetentionTime: 24 * 60 // Max retry period
})
workbox.routing.registerRoute(
/(http[s]?:\/\/)?([^\/\s]+\/)post-tweet/,
new workbox.strategies.NetworkOnly({
plugins: [postTweetPlugin]
}),
'POST'
)
A new version of the app is available. Click to refresh.
const updateChannel = new BroadcastChannel('app-shell');
updateChannel.addEventListener('message', event => {
// Inform about the new version & prompt to reload
});
workbox.precaching.addPlugins([
new workbox.broadcastUpdate.Plugin('app-shell')
]);
// Feature detection
if ('serviceWorker' in navigator) {
// Postponing the registration for better performance
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}
import { Workbox } from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('service-worker.js');
// Event listeners...
wb.register();
}
$ npm install workbox-window
<script type="module">
import {Workbox} from 'https://...cdn.com/workbox-window.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('service-worker.js');
wb.register();
}
</script>
wb.addEventListener('installed', event => {
if (event.isUpdate) {
// Show "Newer version is available. Refresh?" prompt
} else {
// Optionally: show "The app is offline-ready" toast
}
});
workbox.core.skipWaiting()
workbox.core.clientsClaim()
wb.addEventListener('activated', (event) => {
// Service worker activated
});
wb.addEventListener('waiting', (event) => {
// Service worker was installed but can't be activated
});
externalinstalled, externalwaiting, externalactivated
wb.addEventListener('message', (event) => {
if (event.data.type === 'CACHE_UPDATE') {
const {updatedURL} = event.data.payload;
console.log(`A new version of ${updatedURL} is available!`);
}
});
wb.addEventListener('activated', (event) => {
const urlsToCache = [...];
// Send that list of URLs to your router in the service worker.
wb.messageSW({
type: 'CACHE_URLS',
payload: {urlsToCache},
});
});
Maxim Salnikov
@webmaxru
Maxim Salnikov
@webmaxru
import { precacheAndRoute }
from 'workbox-precaching/precacheAndRoute.mjs'
import { skipWaiting }
from 'workbox-core/skipWaiting.mjs'
import { clientsClaim }
from 'workbox-core/clientsClaim.mjs'
skipWaiting()
clientsClaim()
precacheAndRoute([])
import resolve from 'rollup-plugin-node-resolve'
import replace from 'rollup-plugin-replace'
import { terser } from 'rollup-plugin-terser'
export default {
input: 'dist/angular-pwa/service-worker.js',
output: {
file: 'dist/angular-pwa/service-worker.js',
format: 'iife'
},
plugins: [...]
}
plugins: [
resolve(),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
terser()
]
"build-pwa-bundle":
"ng build --prod &&
node workbox-build-inject.js &&
npx rollup -c"