Maxim Salnikov
PWA Developer Advocate
Products from the future
UI Engineer at ForgeRock
AJAX
Static
Dynamic
RWD
PWA
... Progressive Web App can be seen as an evolving hybrid of regular web pages (or websites) and a mobile application
... a new software development methodology
self.addEventListener('fetch', function(event) {
event.respondWith(
...
);
});
self.addEventListener('push', function(event) {
...
event.waitUntil(self.registration.showNotification(title, options));
});
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
self.addEventListener('sync', function(event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
SW Boot
Navigation request
SW Boot
Navigation request
self.addEventListener('activate', e => {
e.waitUntil(self.registration.navigationPreload.enable());
});
addEventListener('fetch', event => {
event.respondWith(async function() {
// Respond from the cache if we can
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
// Else, use the preloaded response, if it's there
const response = await event.preloadResponse;
if (response) return response;
// Else try the network.
return fetch(event.request);
}());
});
navigator.serviceWorker.ready.then(function(registration) {
registration.periodicSync.register({
tag: 'get-latest-news', // default: ''
minPeriod: 12 * 60 * 60 * 1000, // default: 0
powerState: 'avoid-draining', // default: 'auto'
networkState: 'avoid-cellular' // default: 'online'
}).then(function(periodicSyncReg) {
// success
}, function() {
// failure
})
});
index.html
self.addEventListener('periodicsync', function(event) {
if (event.registration.tag == 'get-latest-news') {
event.waitUntil(fetchAndCacheLatestNews());
}
else {
// unknown sync, may be old, best to unregister
event.registration.unregister();
}
});
service-worker.js
// You can't do this!
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js');
}
Link: </service-worker.js>; rel="serviceworker"; scope="/"
self.addEventListener('install', function(e) {
e.registerForeignFetch({scopes: ['/myscope'], origins: ['*']});
});
index.html
HTTP header
service-worker.js
self.addEventListener('foreignfetch', function(e) {
// Do whatever local work is necessary to handle the fetch,
// or just pass it through to the network:
e.respondWith(fetch(e.request).then(response => ({
response: response,
origin: e.origin,
headers: ['...']
}));
});
service-worker.js