Написание скрипта для сервисного работника

Эта практическая работа является частью учебного курса «Разработка прогрессивных веб-приложений», разработанного командой Google Developers Training. Вы получите максимальную пользу от этого курса, если будете выполнять практические работы последовательно.

Полную информацию о курсе смотрите в обзоре «Разработка прогрессивных веб-приложений» .

Введение

В этой лабораторной работе вы познакомитесь с созданием простого сервисного работника и поймете его жизненный цикл.

Чему вы научитесь

  • Создайте базовый скрипт Service Worker, установите его и выполните простую отладку.

Что вам следует знать

  • Базовый JavaScript и HTML
  • Концепции и базовый синтаксис обещаний ES2015
  • Как включить консоль разработчика

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

Загрузите или клонируйте репозиторий pwa-training-labs с github и установите LTS-версию Node.js , если необходимо.

Перейдите в каталог service-worker-lab/app/ и запустите локальный сервер разработки:

cd service-worker-lab/app
npm install
node server.js

Вы можете завершить работу сервера в любое время с помощью сочетания Ctrl-c .

Откройте браузер и перейдите по адресу localhost:8081/ .

Примечание: Отмените регистрацию всех сервис-воркеров и очистите все кэши сервис-воркеров для локального хоста, чтобы они не мешали работе лаборатории. В Chrome DevTools это можно сделать, нажав «Очистить данные сайта» в разделе «Очистить хранилище» на вкладке «Приложение» .

Откройте папку service-worker-lab/app/ в предпочитаемом вами текстовом редакторе. В папке app/ вы будете создавать лабораторию.

Эта папка содержит:

  • below/another.html , js/another.js , js/other.js и other.html — это примеры ресурсов, которые мы используем для экспериментов с областью действия Service Worker.
  • Папка styles/ содержит каскадные таблицы стилей для этой лаборатории.
  • папка test/ содержит файлы для проверки вашего прогресса
  • index.html — это главная HTML-страница для нашего образца сайта/приложения.
  • service-worker.js — это файл JavaScript, который используется для создания нашего сервисного работника.
  • package.json и package-lock.json отслеживают пакеты узлов, используемые в этом проекте.
  • server.js — это простой экспресс-сервер, который мы используем для размещения нашего приложения.

Откройте service-worker.js в текстовом редакторе. Обратите внимание, что файл пустой. Мы пока не добавили код для запуска внутри сервис-воркера.

Откройте index.html в текстовом редакторе.

Внутри тегов <script> добавьте следующий код для регистрации сервисного работника:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('service-worker.js')
    .then(registration => {
      console.log('Service Worker is registered', registration);
    })
    .catch(err => {
      console.error('Registration failed:', err);
    });
  });
}

Сохраните скрипт и обновите страницу. Консоль должна вернуть сообщение о регистрации сервис-воркера. В Chrome вы можете проверить регистрацию сервис-воркера, открыв DevTools (Ctrl + Shift + I в Windows и Linux или ⌘ + alt + I на Mac), перейдя на вкладку «Приложение» и выбрав пункт «Сервис-воркеры» . Вы должны увидеть что-то похожее на следующее:

Дополнительно : откройте сайт в неподдерживаемом браузере и убедитесь, что условие проверки поддержки работает.

Объяснение

Приведённый выше код регистрирует файл service-worker.js как сервис-воркер. Сначала он проверяет, поддерживает ли браузер сервис-воркеры. Это следует делать каждый раз при регистрации сервис-воркера, поскольку некоторые браузеры могут не поддерживать сервис-воркеры. Затем код регистрирует сервис-воркер с помощью метода register API ServiceWorkerContainer , который содержится в интерфейсе Navigator окна.

navigator.serviceWorker.register(...) возвращает промис, который разрешается с объектом registration после успешной регистрации сервис-воркера. Если регистрация не удалась, промис будет отклонен.

Изменения статуса сервисного работника запускают события в сервисном работнике.

Добавить прослушиватели событий

Откройте service-worker.js в текстовом редакторе.

Добавьте следующие прослушиватели событий к сервисному работнику:

self.addEventListener('install', event => {
  console.log('Service worker installing...');
  // Add a call to skipWaiting here
});

self.addEventListener('activate', event => {
  console.log('Service worker activating...');
});

Сохраните файл.

Вручную отмените регистрацию сервис-воркера и обновите страницу, чтобы установить и активировать обновлённый сервис-воркер. В журнале консоли должно быть указано, что новый сервис-воркер был зарегистрирован, установлен и активирован.

Примечание: Журнал регистрации может отображаться не по порядку с другими журналами (установки и активации). Сервис-воркер работает одновременно со страницей, поэтому мы не можем гарантировать порядок журналов (журнал регистрации поступает со страницы, а журналы установки и активации — от сервис-воркера). Однако установка, активация и другие события сервис-воркера происходят в определённом порядке внутри сервис-воркера и всегда должны отображаться в ожидаемом порядке.

Объяснение

Сервис-воркер генерирует событие install в конце регистрации. В приведённом выше коде сообщение регистрируется внутри прослушивателя события install , но в реальном приложении это было бы подходящим местом для кэширования статических ресурсов.

При регистрации сервис-воркера браузер определяет, является ли он новым (либо отличается от ранее установленного сервис-воркера, либо для этого сайта нет зарегистрированного сервис-воркера). Если сервис-воркер новый (как в данном случае), браузер устанавливает его.

Сервис-воркер генерирует событие activate , когда получает управление страницей. Приведённый выше код регистрирует здесь сообщение, но это событие часто используется для обновления кэшей.

В каждый момент времени для данной области действия может быть активен только один сервис-воркер (см. раздел «Изучение области действия сервис-воркера»). Поэтому вновь установленный сервис-воркер не активируется, пока существующий сервис-воркер не перестанет использоваться. Поэтому все страницы, контролируемые сервис-воркером, должны быть закрыты, прежде чем новый сервис-воркер сможет взять на себя управление. Поскольку мы отменили регистрацию существующего сервис-воркера, новый сервис-воркер был активирован немедленно.

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

Примечание: вы также можете вручную активировать новый service worker с помощью инструмента разработчика некоторых браузеров и программно с помощью skipWaiting() , что мы обсудим в разделе 3.4.

Обновление сервисного работника

Добавьте следующий комментарий в любое место service-worker.js :

// I'm a new service worker

Сохраните файл и обновите страницу. Посмотрите логи в консоли: новый сервис-воркер устанавливается, но не активируется. В Chrome вы можете увидеть ожидающий сервис-воркер на вкладке «Приложение» в DevTools.

Закройте все страницы, связанные с сервис-воркером. Затем снова откройте localhost:8081/ . В журнале консоли должно быть указано, что новый сервис-воркер активирован.

Примечание: если вы получаете неожиданные результаты, убедитесь, что HTTP-кеш отключен в инструментах разработчика.

Объяснение

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

Пропуск фазы ожидания

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

В service-worker.js добавьте вызов skipWaiting в прослушивателе событий install :

self.skipWaiting();

Сохраните файл и обновите страницу. Обратите внимание, что новый сервис-воркер устанавливается и активируется немедленно, даже если управление осуществлял предыдущий сервис-воркер.

Объяснение

Метод skipWaiting() позволяет сервис-воркеру активироваться сразу после завершения установки. Прослушиватель событий install — это обычное место для вызова skipWaiting() , но его можно вызвать где угодно во время фазы ожидания или до неё. Подробнее о том, когда и как использовать skipWaiting() , см. в этой документации . В оставшейся части лабораторной работы мы можем тестировать новый код сервис-воркера, не отменяя регистрацию сервис-воркера вручную.

Для получения дополнительной информации

Сервисные работники могут выступать в качестве прокси-сервера между вашим веб-приложением и сетью.

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

Добавьте следующий код в service-worker.js :

self.addEventListener('fetch', event => {
  console.log('Fetching:', event.request.url);
});

Сохраните скрипт и обновите страницу, чтобы установить и активировать обновленный Service Worker.

Проверьте консоль и убедитесь, что события выборки не зарегистрированы. Обновите страницу и снова проверьте консоль. На этот раз вы должны увидеть события выборки для страницы и её ресурсов (например, CSS).

Нажмите на ссылки «Другая страница» , «Другая страница» и «Назад» .

Вы увидите события выборки в консоли для каждой страницы и её ресурсов. Понятны ли все записи в журналах?

Примечание: Если вы посещаете страницу и HTTP-кеширование не отключено, ресурсы CSS и JavaScript могут быть локально кэшированы. В этом случае вы не увидите события загрузки для этих ресурсов.

Объяснение

Сервис-воркер получает событие fetch для каждого HTTP-запроса, выполненного браузером в пределах его области действия. Объект события fetch содержит запрос. Прослушивание событий fetch в сервис-воркере аналогично прослушиванию событий click в DOM. В нашем коде при возникновении события fetch мы выводим запрошенный URL-адрес в консоль (на практике мы также могли бы создать и вернуть собственный ответ с произвольными ресурсами).

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

Для получения дополнительной информации

Код решения

Чтобы получить копию рабочего кода, перейдите в папку 04-intercepting-network-requests/ .

У сервис-воркеров есть область действия . Область действия сервис-воркера определяет, с каких путей сервис-воркер перехватывает запросы.

Найдите область применения

Обновите регистрационный код в index.html следующим образом:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('service-worker.js')
    .then(registration => {
      console.log('SW registered with scope:', registration.scope);
    })
    .catch(err => {
      console.error('Registration failed:', err);
    });
  });
}

Обновите браузер. Обратите внимание, что в консоли отображается область действия сервис-воркера (в данном случае это http://localhost:8081/ ).

Объяснение

Обещание, возвращаемое методом register() разрешается в объект регистрации , который содержит область действия сервисного работника.

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

Переместить сервисного работника

Переместите service-worker.js в каталог below/ и обновите URL-адрес service worker в коде регистрации в index.html .

Отмените регистрацию текущего сервисного работника в браузере и обновите страницу.

В консоли показано, что область действия сервис-воркера теперь http://localhost:8081/below/ . В Chrome область действия сервис-воркера также можно увидеть на вкладке «Приложение» в DevTools:

Вернувшись на главную страницу, нажмите «Другая страница» , «Другая страница» и «Назад» . Какие запросы на выборку регистрируются, а какие — нет?

Объяснение

Область действия сервис-воркера по умолчанию — это путь к файлу сервис-воркера. Поскольку файл сервис-воркера теперь находится в below/ , это и есть область его действия. Консоль теперь регистрирует только события выборки для another.html , another.css и another.js , поскольку это единственные ресурсы в области действия сервис-воркера.

Установить произвольную область действия

Переместите service worker обратно в корневой каталог проекта ( app/ ) и обновите URL service worker в коде регистрации в index.html .

Используйте ссылку на MDN , чтобы установить область действия сервисного работника в каталоге below/ используя необязательный параметр в register() .

Отмените регистрацию сервисного работника и обновите страницу. Нажмите «Другая страница» , «Другая страница» и «Назад» .

Консоль снова показывает, что область действия service worker теперь http://localhost:8081/below/ , а журналы извлекают события только для another.html , another.css и another.js .

Объяснение

Можно задать произвольную область действия, передав дополнительный параметр при регистрации, например:

navigator.serviceWorker.register('/service-worker.js', {
  scope: '/kitten/'
});

В приведённом выше примере область действия сервис-воркера установлена на /kitten/ . Сервис-воркер перехватывает запросы со страниц в каталогах /kitten/ и /kitten/lower/ , но не со страниц типа /kitten или / .

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

Для получения дополнительной информации

Код решения

Чтобы получить копию рабочего кода, перейдите в папку solution/ .

Теперь у вас есть простой работающий сервисный работник и вы понимаете жизненный цикл сервисного работника.

Для получения дополнительной информации

Жизненный цикл работника сферы услуг

Чтобы увидеть все практические работы в учебном курсе PWA, ознакомьтесь с приветственными практическими работами для курса.