Эта практическая работа является частью учебного курса «Разработка прогрессивных веб-приложений», разработанного командой 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, ознакомьтесь с приветственными практическими работами для курса.