наш блог

Скрипт-субмарина: основы стремительного погружения в Service Worker

Service Worker – замечательная технология, с помощью которой можно расширить возможности твоего сайта. Она представляет собой почти обычный javascript-файл. Я написал «почти» потому, что в нем нет привычного доступа к объекту document и window.

Кстати, это некоторые из его возможностей:

  • Кэширование данных сайта для увеличения скорости повторной загрузки;
  • Перехват и модифицирование запросов браузера;
  • Работа с push-уведомлениями;
  • Progressive Web Application.

Тем не менее существует и ряд нюансов, ограничивающих работу Service Worker. Во-первых, это относительно новая технология, которая «не уживается» с устаревшими браузерами. Во-вторых, Service Worker не работает в режиме инкогнито. А главное, в целях обеспечения безопасности технология взаимодействует только с протоколом HTTPS. Единственное исключение – разработка на localhost.

По сути, Service Worker – это посредник между браузером и сервером. Впрочем, довольно теории. Перейдем к коду. Html-файл рассматриваемой мною страницы будет выглядеть так:

index.html
<!doctype html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport"
         content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>SW deep dive</title>
</head>
<body>
   <h1>SW deep dive!</h1>
   <script src="script.js"></script>
</body>
</html>

Страница может быть любой. Все, что требуется – подключить javascript-файл, в котором нужно будет зарегистрировать Service Worker.

script.js
if ('serviceWorker' in navigator) {
   window.addEventListener('load', () => {
       navigator.serviceWorker.register('/sw.js').then(
           registration => {
               console.log('ServiceWorker registration successful with scope: ', registration.scope);
           },
           err => {
               console.log('ServiceWorker registration failed: ', err);
           }
       );
   });

В коде, который показан выше, происходит регистрация Service Worker. Так и начинается его жизненный цикл. Но обо всем по порядку. В первую очередь нужно проверить, есть ли в глобальном объекте navigator объект serviceWorker. Это необходимо для того, чтобы исключить возможные ошибки в устаревших браузерах.

Далее нужно вызвать метод register(), в который первым параметром указывается путь к файлу Service Worker. Важно запомнить, что делается это относительно корня приложения, а не местоположения в проекте. А значит, sw.js будет находиться по адресу «https://my_site.com/sw.js». Также есть возможность указать рамки действия Service Worker, что достигается передачей объекта опций с полем scope во второй параметр метода регистрации:

navigator.serviceWorker.register('/sw.js', {scope: '/some_scope'})

Теперь Service Worker будет контролировать все страницы с адресом, который начинается с «https://my_site.com/some_scope». Если не указывать scope, то он установится по умолчанию. Это и будет корень сайта. Файл sw.js будет выглядеть так:

sw.js
self.addEventListener('install', function(event) {
   console.log('installed!', event)
});
self.addEventListener('activate', function(event) {
   console.log('activated!', event)
});
self.addEventListener('fetch', function(event) {
   console.log('fetch', event)
});

Первым делом, после регистрации Service Worker, возникнет событие install. Зачастую в его обработчике кешируют необходимые файлы. Далее «включается» обработчик события activate. Оно может возникнуть в двух ситуациях. Либо во время установки нового Service Worker. Либо если его файл изменился и отличается от ранее установленного. В последнем варианте новый Service Worker переходит в состояние wating, а старый продолжает контролировать сайт до того момента, пока не будут закрыты все страницы.

И наконец, событие fetch. Его обработчик вызывается после установки Service Worker – в момент, когда пользователь обновляет страницу или переходит на другую. В этом обработчике можно перехватывать уходящие запросы и каким-то образом модифицировать их. А также вместо запроса «отдавать» на сервер данные из кэша.

Для запуска рассматриваемого примера потребуется виртуальный сервер. Я буду использовать http-server. Установить его можно командой «npm i-g http-server». Но только тогда, когда уже имеется установленный node.js. Запускаю сайт командой «http-server» в корне проекта. И если все условия установки Service Worker соблюдены, то в консоле браузера появляется строка: «ServiceWorker registration successful with scope: http://localhost:8080/». Она и будет свидетельствовать об успешной установке.

Юрий Кизилов, компания Craft Group