Статьи

Начало работы с сервисными работниками

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

Сервисный работник — это скрипт, который работает в фоновом режиме. Для работы не требуется веб-страница или взаимодействие с пользователем. Это означает, что он будет работать, даже если ваш веб-сайт не открыт, даже если он не может получить прямой доступ к DOM (однако DOM может использовать API postMessage для связи с Service Worker). В настоящее время они включают такие функции, как push-уведомления и геозоны. Он также может перехватывать и обрабатывать сетевые запросы, это функция, которую мы собираемся использовать в этом руководстве. Тем из вас, кто интересуется поддержкой браузеров, предлагаю взглянуть сюда . Как вы увидите, его реализация все еще находится на ранней стадии.
Чтобы продемонстрировать, как работает функция перехвата сети Service Workers, мы создадим статический веб-сайт, который работает, даже когда пользователь находится в автономном режиме. Вы можете найти всю демоверсию сайта здесь .

Сервисные работники дают вам контроль над веб-страницей, где вы можете программно выбирать компоненты, которые вы хотите кэшировать. Имейте в виду, что он будет работать в автономном режиме только при втором или последующих посещениях. Причина такого поведения будет объяснена позже в этом руководстве.

конечный результат

Одна из распространенных проблем, с которыми сталкиваются сервисные работники, заключается в том, что они работают только в «безопасных источниках» (в основном на сайтах HTTPS) в соответствии с политикой, которая предпочитает безопасные источники для новых мощных функций . Тем не менее, даже localhost считается безопасным источником, поэтому разработка на нем является простым способом избежать этой ошибки. Если вы предпочитаете, вы также можете использовать GitHub Pages (как я это сделал), поскольку они обслуживаются по HTTP.

Начиная

Первое, что нам нужно сделать, это зарегистрировать работника сервиса. Это будет работать, только если браузер поддерживает это. Это означает, что все следующие фрагменты кода, которые вы найдете в этом руководстве, будут действительны, только если существует navigator.serviceWorker .

 //make sure that Service Workers are supported. if (navigator.serviceWorker) { navigator.serviceWorker.register('./service-worker.js', {scope: './about'}) .then(function (registration) { console.log(registration); }) .catch(function (e) { console.error(e); }) } else { console.log('Service Worker is not supported in this browser.'); } 

В приведенном выше коде ./service-worker.js — это путь работника сервиса. Область действия — это путь, по которому будет работать сервисный работник. В этом примере Сервисный работник будет управлять страницей, имеющей путь /about/ . scope является необязательной и имеет ./ по умолчанию. Метод register возвращает обещание . Мы можем вызывать метод register столько раз, сколько захотим. Когда это будет сделано, браузер автоматически определит, был ли он уже зарегистрирован, и зарегистрирует его, только если он не был зарегистрирован ранее.

Вы можете просмотреть всех зарегистрированных сервисных работников, зайдя в chrome://serviceworker-internals .

Установка

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

 self.addEventListener('install', function(event){ console.log(event); }); self.addEventListener('activate', function(event){ console.log(event); }); 

На этом этапе мы будем перехватывать запросы к серверу. Для этого мы прослушиваем событие 'fetch' используя метод self.addEventListener , который возвращает объект события в self.addEventListener . Мы получаем URL-адрес запроса в качестве значения event.request.url .

 self.addEventListener('fetch', function(event){ console.log(event.request.url); // return something for each interception }); 

Если вы хотите импортировать любой внешний скрипт в Service Worker, вы можете сделать это с помощью importScripts() . В этом примере мы будем использовать cache-polyfill, так как поддержка cache ограничена.

 importScripts('js/cache-polyfill.js'); var CACHE_VERSION = 'app-v1'; var CACHE_FILES = [ '/', 'images/background.jpeg', 'js/app.js', 'css/styles.css', 'https://fonts.googleapis.com/css?family=Roboto:100' ]; self.addEventListener('install', function (event) { event.waitUntil( caches.open(CACHE_VERSION) .then(function (cache) { console.log('Opened cache'); return cache.addAll(CACHE_FILES); }) ); }); 

В нашем прослушивателе событий install мы используем метод waitUntil() из предоставленного объекта event чтобы сообщить браузеру обещание, когда процесс установки в нашем Service Worker завершится. Предоставленное обещание является возвращаемым значением метода caches.open() который открывает кэш с именем app-v1.

Как только кеш открывается должным образом, мы добавляем в него наши активы. Метод install завершается только после сохранения ресурсов. Если при сохранении какого-либо из активов произошла ошибка, Service Service Worker не будет успешно зарегистрирован. Это означает, что мы должны гарантировать, что мы кэшируем только важные файлы, поскольку большее количество файлов увеличивает вероятность сбоя. Вам следует кэшировать только те компоненты, которые улучшают воспринимаемое время загрузки веб-страницы.

Когда этап установки завершен, сервисный работник активируется. Здесь обслуживающий работник берет на себя управление страницей.

Теперь запросы перехватываются, но нам нужно выяснить, что мы собираемся делать, когда это произойдет. Могут быть случаи, когда Service Service Worker не может прочитать данные из кэша или запрос не соответствует URL-адресу запроса активов, сохраненному в кэше.
Вот что мы собираемся сделать после перехвата запроса:

  1. Сначала мы открываем кеш и сопоставляем запрос с имеющимися в кеше. Если они совпадают, мы возвращаем данные из кеша. Если запрос не совпадает, мы перенаправляем запрос на сервер.
  2. Когда данные успешно получены с сервера, мы возвращаем эти данные.
  3. Затем мы открываем кеш и сохраняем эти данные здесь, используя cache.put() чтобы к ним можно было обращаться непосредственно из кеша при следующих попытках.
 self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function(res){ if(res){ return res; } requestBackend(event); }) ) }); function requestBackend(event){ var url = event.request.clone(); return fetch(url).then(function(res){ //if not a valid response send the error if(!res || res.status !== 200 || res.type !== 'basic'){ return res; } var response = res.clone(); caches.open(CACHE_VERSION).then(function(cache){ cache.put(event.request, response); }); return res; }) } 

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

  1. Обновите CACHE_VERSION потому что, если браузер обнаружит какое-либо изменение в Service Worker, он загрузит его заново. Событие install в новом сервисном работнике будет запущено, но новый сервисный работник войдет в стадию «ожидания», поскольку страница все еще будет контролироваться старым сервисным работником.
  2. Когда все экземпляры вашего веб-сайта будут закрыты, новый сервисный работник получит контроль (вместо старого).
  3. В этот момент будет install событие install , и здесь нам потребуется некоторое управление кешем.

Мы обнаружим, что все ключи отличаются от текущей версии, а затем очистим их с помощью функции ниже.

 self.addEventListener('activate', function (event) { event.waitUntil( caches.keys().then(function(keys){ return Promise.all(keys.map(function(key, i){ if(key !== CACHE_VERSION){ return caches.delete(keys[i]); } })) }) ) }); 

ServiceWorkers будут установлены при первом посещении веб-сайта. Не ожидайте, что они примут контроль над страницей при первом посещении. Они просто будут зарегистрированы и установлены. Запрос отправится на сервер, и оттуда будут получены ресурсы. Более того, пока они будут сохранены в кеше. При последующих посещениях работник сервиса перехватывает запросы и возвращает активы из кэша.

Чтобы лучше понять все это, откройте вкладку «Сети» в инструментах разработчика. Если вы снова откроете страницу позже, вы увидите, что все кэшированные ресурсы извлекаются из Service Worker.

сеть

Следует иметь в виду, что браузер контролирует время жизни сервисного работника. Время работы после установки не фиксировано.

Отладка

Отладка сервисного работника немного сложна для новичка. Вы должны включить его, так как это все еще эксперимент. Чтобы сделать это, выполните следующие действия:

  1. Перейдите в chrome://flags и включите опцию «Включить эксперименты DevTools».
  2. Откройте DevTools, затем перейдите в Настройки> Эксперименты и нажмите Shift 6 раз.
  3. Проверьте «Сервисные работники на панели ресурсов» и перезапустите DevTools

Теперь у вас включен этот эксперимент, и вы можете найти этот параметр на вкладке Ресурсы DevTools.

Отладка

Если вы хотите вручную отменить регистрацию Service Worker, перейдите в chrome://serviceworker-internals/ и нажмите соответствующую кнопку «Отменить регистрацию». Более подробную информацию о процессе отладки можно найти здесь .

Выводы

В этой статье мы создали веб-сайт, который демонстрирует использование сервисных работников для создания автономных веб-приложений. Мы также обсудили несколько концепций, касающихся сервисных работников и способов их устранения.
Я действительно надеюсь, что вам понравился урок.
Если вы хотите поиграть с исходным кодом, вы можете найти его здесь .