Погружение

в Service Workers

Максим Сальников

  • Google Developer Expert по Angular

  • Организатор AngularJS Oslo Meetup

  • Организатор MobileEra.rocks

UI Engineer  продуктов из будущего

в ForgeRock

Google Experts это глобальная сеть опытных разработчиков, дизайнеров, маркетологов, активно поддерживающих разработчиков, стартапы и компании, которые изменяют мир своими веб- и мобильными приложениями

Google Developer

Experts

Progressive Web App

Progressive Web App (PWA) is a term used to denote a new software development methodology.

 

Unlike traditional applications, Progressive Web App can be seen as an evolving hybrid of regular web pages (or websites) and a mobile application.

Прогрессивное Веб-приложение

  • Прогрессивное
  • Адаптивное
  • Независимое от соединения
  • "Как нативное" для пользователя
  • Всегда свежая версия
  • Безопасное
  • Доступное для поиска
  • Удерживающее
  • Легко устанавливаемое
  • Легко распространяемое

ServiceWorker

PWA

Работа приложения в автономном режиме

Повышение быстродействия за счет уменьшения количества обращений к сети

Удобные инструменты для обработки случаев проблем с соединением

Не только работа с сетью!

Синхронизация данных в фоновом режиме

Централизованное получение обновлений результатов сложных вычислений (геолокация, данные с гироскопа и т.д.) для использования сразу несколькими частями приложения

Компиляция и управление зависимостями CoffeeScript, less, CJS/AMD и т.д. на стороне клиента

Повышениe быстродействия за счет предзагрузки ресурсов, которые могут потребоваться в ближайшем будущем, например, следующего фото при просмотре фотоальбома

Физически

*.JS

-файл

 Логически

Программируемый сетевой прокси-сервер, расположенный между приложением, запущенным в браузере и сетью

App

SW

Браузер

Это  Worker

  • Работает в фоновом режиме

  • Нет доступа к DOM

Отдельный контекст для выполнения фоновых задач, который не блокирует UI

Особенности

  • Регистрируется непосредственно из одного из скриптов приложения для определенного адреса (URL)

  • Работает только по HTTPS (или на localhost)

  • Не может использоваться для хранения состояния, но имеет доступ к Cache API и IndexedDB API

Event-driven

  • Реагирует на события (запросы в сеть со стороны клиента, push-уведомления со стороны сервера)

  • Может получать сообщения от клиента (с помощью postMessage)

Время работы

  • Запускается только при наступлении событий

  • Работает ровно столько времени, сколько требуется для обработки события

Автономная работа приложения

Регистрация

// app.js

if ('serviceWorker' in navigator) {  
    navigator.serviceWorker.register('/sw.js')
    .then(function(registration) {
        // Successful registration
        console.log("Service Worker Registered", registration);
    })
    .catch(function(err) {
        // Registration failed
        console.log("Service Worker Failed to Register", err);
    })
}

Область видимости!

Зарегистрирован

Установлен

=

Установка

// sw.js

var currentCacheName = 'pwaday-sw-v1';

var filesToCache = [
    '/index.html',
    '/css/main.css',
    '/img/logo.png',
    '/js/main.js'
];

self.addEventListener('install', function(event) {  
  event.waitUntil(
    caches.open(currentCacheName).then(function(cache) {
      return cache.addAll(filesToCache);
    })
  );
});

Установлен

Активирован

=

Активация

// sw.js

self.addEventListener('activate', function(event) {  
  event.waitUntil(
    // Get all the cache names
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        // Get all the items that are not the current one
        cacheNames.filter(function(cacheName) {
          return cacheName != currentCacheName;
        }).map(function(cacheName) {
          // Delete the items
          return caches.delete(cacheName);
        })
      ); // end Promise.all()
    }) // end caches.keys()
  ); // end event.waitUntil()
});

Активирован

Перехватывает и принимает

=

Запросы и сообщения

// sw.js

self.addEventListener('fetch', function(event) {  
  // Do stuff with fetch events
});

self.addEventListener('message', function(event) {  
  // Do stuff with postMessage() received from document
});

self.addEventListener('push', function(event) {  
  // Do stuff with push-notifications received from server
});

Жизненный цикл

Жизненный цикл

Обновление

  1. Обновляется .js-файл Service Worker 

  2. Регистрируется новый SW и вызывается событие install

  3. Старый SW все еще управляет страницами приложения, поэтому новый находится в состоянии installed / waiting

  4. Когда все страницы (закладки) приложения закрываются, старый SW переходит в состояние redundant, контроль переходит к новому

  5. Вызывается событие activate

Fast-track

self.addEventListener('install', (event) => {
  event.waitUntil(self.skipWaiting());
});


self.addEventListener('activate', (event) => {
  event.waitUntil(self.clients.claim());
});

Перехват запросов

// sw.js

self.addEventListener('fetch', function(event) {
  event.respondWith(
    ...
  );
});

Cache-first

// sw.js

this.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
  );
});

Вернем то, что находится в cache

Cache-first

// sw.js

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
        return fetch(event.request);
      }
    )
  );
});

Вернем то, что находится в cache. В случае неуспеха - возьмем из сети.

Cache-first

// sw.js

var currentCacheName = 'pwaday-sw-v1';

this.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(resp) {
      return resp || fetch(event.request).then(function(response) {
        return caches.open(currentCacheName).then(function(cache) {
          cache.put(event.request, response.clone());
          return response;
        });  
      });
    })
  );
});

Вернем то, что находится в cache. В случае неуспеха - возьмем из сети и поместим в cache (на будущее)

Дальнейшие улучшения

  • Предусмотреть вариант, когда ресурса нет ни в cache, ни в сети

  • Предусмотреть обновление cache при обновлении статических ресурсов, например, используя параметр last-modified из HTTP заголовков

  • ...

Network-first

// sw.js

var currentCacheName = 'pwaday-sw-v1';

this.addEventListener('fetch', function(event) {
  event.respondWith(
    
    fetch(e.request)
      .then((response) => {
        return caches.open(currentCacheName).then((cache) => {

          cache.put(e.request.url, response.clone());
          return response.clone();

        });
      })

  );
});

Стратегии

  1. Cache-first, Network-first, Fastest, Cache-only, Network-only...

  2. Могут быть разные для разных адресов, типов файлов, методов запросов и т.д.

  3. Можно добавить логику с настраиваемым Timeout, несколькими попытками запросов и т.д.

Когда же?

Целый набор API

  • ServiceWorker API

  • Cache API

  • IndexedDB API

  • Fetch API

  • Notifications API

  • Push API

  • Promise

Инструменты

sw-toolbox

Манипуляции с cache

toolbox.precache(filesToCache);

Маршрутизация

toolbox.networkFirst, toolbox.cacheFirst, toolbox.fastest,
toolbox.cacheOnly, toolbox.networkOnly

Стратегии

toolbox.router.get('/assets/data/(.*)', toolbox.networkFirst, {
	cache: { name: currentCacheName }
});

Angular

Mobile Toolkit

Ресурсы

Спасибо!

@webmaxru

Максим Сальников

Погружение в Service Workers

By Maxim Salnikov

Погружение в Service Workers

The term Progressive Web App refers to a group of technologies, such as service workers, and push notifications, that can bring native-like performance and user experience to web apps. Progressive Web Apps are interesting because in some ways they represent a coming of age for the Web. The Angular Mobile Toolkit makes it easy to build snappy Web apps that load instantly on any device, even without an internet connection. Take advantage of the searchability, shareability, and no-install-required-ability of the Web without compromise. During this 100% hands-on session we'll have a look on recent tools and guides from Angular team to help us build Progressive Web Apps. We'll have a look at Angular CLI and plugins/libraries for App Shell, Service Worker, and Application Manifest supporting us in fast and easy creation of installable, offline-capable, mobile-network-friendly apps. Agenda Introduction to PWA and Workshop Setup Introduction to Angular Mobile Toolkit Create an installable mobile web app with Angular CLI Make the App Installable with Web App Manifest App Shell Architecture Add an app shell component to the App Deep dive into Service Workers Add basic offline capabilities with Service Worker Adding Splash Screen Sending Push Notifications Questions and answers

  • 2,926