Service Worker — это файл JS, который запускается независимо от основного потока. Он может перехватывать сетевые запросы от веб-приложения и выступать в качестве посредника.

Service Worker имеет множество вариантов использования при проектировании и разработке PWA (Progressive Web Application).

Офлайн-функции: сервисные работники могут перехватывать сетевые запросы и кэшировать ресурсы, а также обеспечивать работу в автономном режиме, даже если сетевое подключение отсутствует.

например, сайт электронной коммерции может реализовать функцию AppShell и кэшировать статические ресурсы при первой загрузке с помощью Service Worker и API кэширования браузера, чтобы основные функции работали, даже если пользователь находится в автономном режиме.

Push-уведомления. Service Worker можно использовать для отправки и получения push-уведомлений с сервера, даже если веб-приложение закрыто.

например, приложение обмена сообщениями может отображать push-уведомления для пользователя о новых сообщениях, даже если приложение закрыто, как собственное приложение.

Оптимизация производительности. Service Workers можно использовать для оптимизации производительности веб-приложения путем кэширования статических ресурсов, таких как изображения, файлы js и css. это уменьшает количество сетевых запросов к серверу.

Давайте создадим простой пример для демонстрации кэширования статических ресурсов и сокращения времени загрузки приложения.

Наша цель здесь — кешировать активы во время загрузки и обслуживать их из кеша, если будет какой-либо запрос в будущем.

Сначала необходимо зарегистрировать файл Service Worker. После регистрации события Worker запускаются последовательно. Код для регистрации Service Worker должен находиться за пределами файла Service Worker. После завершения регистрации вы можете проверить статус файла Service Worker в консоли разработчика браузера.

Регистрация.

Сервис-воркер — это отдельный файл, который необходимо зарегистрировать перед запуском каких-либо событий. Чтобы сделать sw.js рабочим файлом службы, мы регистрируем его с помощью serviceWorker.register в этом примере.

const registerServiceWorker = async () => {
  if ("serviceWorker" in navigator) {
    let registration;
    try {
      registration = await navigator.serviceWorker.register("sw.js");
    } catch (error) {
      console.error(`failed to register `, error);
    }
    registration.addEventListener("updatefound", (event) => {
      // updatefound event is fired when a new service worker is being installed.
      console.log("new service worker is installing", registration.installing);
    });
  }
};

Установка.

Service Worker запускает событие установки после регистрации. Install вызывается только один раз для каждого сервис-воркера и не будет вызываться снова до его обновления.

const assets = [
  "/assets/img/header-bg.jpg",
  "/assets/img/close-icon.svg",
  "/assets/img/map-image.png",
  "/assets/img/navbar-logo.svg",
  "/assets/img/about/1.jpg",
  "/assets/img/about/2.jpg",
  "/assets/img/about/3.jpg",
  "/assets/img/about/4.jpg",
  "/assets/img/logos/facebook.svg",
  "/assets/img/logos/google.svg",
  "/assets/img/logos/ibm.svg",
  "/assets/img/logos/microsoft.svg",
  "/assets/img/portfolio/1.jpg",
  "/assets/img/portfolio/2.jpg",
  "/assets/img/portfolio/3.jpg",
  "/assets/img/portfolio/4.jpg",
  "/assets/img/portfolio/5.jpg",
  "/assets/img/portfolio/6.jpg",
  "/assets/img/team/1.jpg",
  "/assets/img/team/2.jpg",
  "/assets/img/team/3.jpg",
  "/css/styles.css",
];
self.addEventListener("install", (event) => {
self.skipWaiting();
  event.waitUntil(
    caches.open('agency-static-v1').then((cach) => cach.addAll([...assets]))
  );
});

Это создает новый экземпляр кеша и активы предварительного кеша. event.waitUntil принимает обещание и ждет его разрешения. Здесь он делает две вещи.

  • создайте экземпляр кеша с именем «agency-static-v1».
  • активы предварительно кэшируются во вновь созданном экземпляре кэша с использованием метода addAll.

Если промисы, переданные в WaitUntill, отклоняются, установка сервисного работника завершается сбоем. Если промисы разрешены, тогда статус Service Worker устанавливается на установлен.

пропустить ожидание

Фаза ожидания — это когда одновременно работает только одна версия сайта, но если это не нужно и сделать новый Service Worker активным раньше, вызовите skipWaiting.

Это приводит к тому, что новый сервис-воркер переопределяет активный сервис-воркер и получает контроль над страницей после установки. Это только пропускает ожидание, а не установку.

примечание: пропуск периода ожидания означает, что страница контролировалась старым сервис-воркером, и она заменяется новым, но старый сервис-воркер обрабатывал части выборки и другого кеша, если это может нарушить работу, не используйте пропустить ожидание.

Активация.

После успешной регистрации и установки сервис-воркер активируется, и его состояние становится активируется. Когда сервис-воркер новый, в противном случае он переходит в состояние ожидания, где ему приходится ждать, пока старый сервис-воркер отменит регистрацию. SkipWaiting() гарантирует, что новые сервис-воркеры будут активированы после регистрации и установки.

Новый сервис-воркер начинает управлять страницей после перехода на другую страницу или обновления страницы.

self.addEventListener("activate", (event) => {
  event.waitUntil(caches.keys().then((cacheNames) => {
       return Promise.all(cacheNames.filter(cacheName => {
            return cacheName.startsWith('agency') && cacheName != 'agency-static-v1'             
       }).map((cacheName) => {
        return caches.delete(cacheName);
       })
       )
  }));
});

так как событие activate срабатывает при установке нового Service Worker, поэтому это хорошее место для удаления старого кеша.

Получить.

Это событие запускается всякий раз, когда есть сетевой запрос от веб-приложения. здесь сетевые запросы на активы могут быть перехвачены и обслужены из кеша, если он доступен.

self.addEventListener('fetch', (event) => {
  const url = new URL(event.request.url);
  if (assets.includes(url.pathname)) {
    event.respondWith(caches.match(url.pathname));
  }
});

давайте сравним, насколько улучшилось время загрузки до и после кэширования.

На приведенных ниже снимках показано время загрузки различных файлов при загрузке из сети.

как показано на снимке, следующие файлы style.css заняли 38 мс, а header-bg.jpg — 103 мс.

при перезагрузке сайта после кеша дальнейшие запросы к ассетам обслуживаются из кеша Service Worker и время загрузки для style.css 2мс, а для header-bg.jpg тоже 2мс.

как вы можете видеть, как резко сокращается время загрузки ресурсов.