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

[Viktor Zozuliak] Service Worker - Native Apps Experience For The Web

[Viktor Zozuliak] Service Worker - Native Apps Experience For The Web

Presentation from GDG DevFest Ukraine 2015 - the biggest Google related event in the country. October 23-24, Lviv. Learn more at http://devfest.gdg.org.ua/

Google Developers Group Lviv

October 24, 2015
Tweet

More Decks by Google Developers Group Lviv

Other Decks in Programming

Transcript

  1. Native Apps Experience For The Web Service Worker Viktor Zozuliak

    Front-End Developer @ DataXu/RailsReactor
  2. #dfua Who is mr. ServiceWorker? Service Worker - is a

    new JavaScript API, special type of Web Worker Web Worker - script running in background in separate thread
  3. #dfua What is the purpose of ServiceWorker? To fill the

    gap between web and native apps in context of offline-first and background operations.
  4. #dfua Cache Manifest • Allows to cache only GET requests

    • Only full cache update - no individual record updates • No possibility to add switching logic between network and cache • ==> Deprecated!
  5. #dfua What Service Worker Offers? • making apps available offline

    - install/update • full control over app caches • full control over network requests • subscribing to push notifications • background synchronization
  6. #dfua Service Worker Lifecycle • register • install • wait

    (for old worker to be released) • activate (start receiving events) • suspend (on page close, but still receive events)
  7. #dfua Registering Service Worker navigator.serviceWorker.getRegistration() .then(function(registration) { if (!registration) {

    navigator.serviceWorker.register('/service-worker.js') .then(function (registration) { console.log('SW registration successful'); }) .catch(function (err) { console.log('SW Registration failed: ', err); }); } });
  8. #dfua Registering Service Worker - Gotchas • navigator.serviceWorker - a

    place for SW API • SW is a separate file • SW can’t be registered from other domain • https is required, but localhost is white-listed • SW doesn’t have access to main app context • in real world we need to check if SW is supported: if ('serviceWorker' in navigator)
  9. #dfua self.addEventListener('install', function(event) { var urlsToCache = ['/', '/app.css', '/app.js',

    '/vendor.js']; event.waitUntil( caches.open('static-cache-v1').then(function(cache) { return Promise.all(urlsToCache.map(function (url) { return cache.add(url); })); }); ); }); Installing The App
  10. #dfua • ExtendableEvent - API allowing to pause event processing

    • window.caches - place for Cache API Installing The App - Gotchas
  11. #dfua Cache First Caching Strategy self.addEventListener('fetch', function(event) { event.respondWith( caches.open('static-cache-v1').then(function(cache)

    { return cache.match(event.request).then(function(cachedResponse) { if (cachedResponse) return cachedResponse; else return fetch(event.request); }); }) ); });
  12. #dfua Cache First Caching Strategy - Gotchas • FetchEvent -

    new type of event that allows to intercept network requests • everything is a Promise when it comes to Service Worker
  13. #dfua Network First Cache Strategy event.respondWith( fetch(event.request).then(function (response) { if

    (response.status === 200) { caches.open('api-cache-v1').then(function (cache) { cache.put(event.request, response); }); } return response.clone(); }) ).catch(function (error) { // lookup in cache, if not found - return error(see next slide) });
  14. #dfua Network First Cache Strategy event.respondWith( fetch(event.request).then(function (response) { //

    add to cache and return response (see previous slide) }).catch(function (error) { return caches.open('api-cache-v1').then(function (cache) { return cache.match(event.request).then(function (cachedResponse) { if (cachedResponse) return cachedResponse; else return error; }); }); }) );
  15. #dfua Network First Cache Strategy - Gotchas • Fetch -

    new API for network requests. It is based on Promise. Say “bye-bye” to callback based XHRs. • Fetch promise .catch() is executed when network is unavailable • Response - API for working with network responses • Response has stream nature so it can be read only once. . clone()method is used to overcome this.
  16. #dfua Modifying The Response event.respondWith( fetch(event.request).then(function (response) { return response.text().then(function

    (responseText) { return new Response( responseText.replace(/foo/g, 'bar'), {headers: response.headers} ); }); }) );
  17. #dfua Modifying The Response - Gotchas • We can modify

    the response whatever way we want! • We’ve got network interceptors running right in browser!
  18. #dfua Updating The App • Install event is fired with

    every service worker file update • Service Worker file is considered updated when it changes in size • Activate event can be used to clean up the old version stuff • Service Worker has two update modes - cold (default) and hot
  19. #dfua Updating The App - Cold Mode • run install

    step • set service worker to waiting state • release old worker when all the pages with current active worker are closed • run activate step when page with app is opened • take control over the page • ==> it’s like Google Chrome update model!
  20. #dfua Updating The App - Hot Mode self.skipWaiting(); => •

    run install step • run activate step • take control over the page ⇓⇓⇓ Old app controlled by new Service Worker.
  21. #dfua Updating The App Cold mode - to use when:

    • new worker version is not compatible with old app • new app version is not compatible with old one (guarantees that different versions don’t run in different tabs)
  22. #dfua Updating The App Hot mode - to use when

    • old app is compatible with new service worker • new app version is compatible with old one
  23. #dfua Updating The App - Cache Versioning var staticVersion =

    1; self.addEventListener('install', function(event) { var urlsToCache = ['/', '/app.css', '/app.js', '/vendor.js']; event.waitUntil( caches.open('static-cache-v' + staticVersion).then(function(cache){ return Promise.all(urlsToCache.map(function (url) { return cache.add(url); })); }); ); });
  24. #dfua Updating The App - Cleaning Old Caches self.addEventListener('activate', function(event)

    { event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (cacheName.startsWith('static-cache-v') && !cacheName.endsWith('-v' + staticVersion)) { return caches.delete(cacheName); } }) ); }) ); });
  25. #dfua Sending Messages To Client - Service Worker Side function

    sendToClients (message) { return self.clients.matchAll({includeUncontrolled: true}) .then(function (clients) { clients.forEach(function (client) { client.postMessage(message); }); }); }
  26. #dfua Push Messages Push messages is a really HUGE topic.

    There is a great article on Google Dev Site: And nice simple demo:
  27. #dfua Background Sync • Gives the ability to postpone tasks

    until user has connectivity • Now in state of proposal draft, available only in Chrome Canary, and a big subject to change. • Docs available here:
  28. #dfua Service Worker Browser Support Chrome - very good (most

    features) Firefox - quite good (key features, many features in nightly) Opera - good (key features) IE - optimistic (no support, but under consideration) Safari - bad (no public commitment) Details:
  29. #dfua Resources • Developer Guide on Chromium site: https://www.chromium.org/blink/serviceworker •

    Is Service Worker Ready? by Jake Archibald: https://jakearchibald.github.io/isserviceworkerready/ • Introduction To Service Worker on HTML5 Rocks : http://www.html5rocks.com/en/tutorials/service-worker/introduction/ • Service Worker Libraries maintained by Google: https://developers.google.com/web/tools/service-worker-libraries/