Шаг первый — сделать… на самом деле, подождать. До этого есть шаг. Шаг нулевой. Запустите свой сайт на HTTPS, если это еще не сделано. Вы не сможете использовать сервис-воркер, если все не будет обслуживаться через HTTPS, что имеет смысл, если учесть потрясающую мощь, которой обладает сервис-воркер.
Если вы разрабатываете локально, сервис-воркеры будут нормально работать для localhost
даже без HTTPS. Но для живого сайта HTTPS обязателен.
Сделать офлайн-страницу
Хорошо, предположим, что ваш сайт обслуживается через HTTPS, тогда первый шаг — создать автономную страницу. Сделайте это настолько серьезным или причудливым, насколько это подходит для вашего конкретного бренда. Если веб-сайт предназначен для ресторана, возможно, вы могли бы разместить номер телефона и адрес ресторана на пользовательской офлайн-странице (непрошеный совет: вы также можете разместить это на домашней странице, знаете ли). Вот пример индивидуальной офлайн-страницы для конференции Ampersand в этом году.
Когда вы закончите, опубликуйте автономную страницу с подходящим образным URL-адресом, например, скажем, /offline.html
.
Предварительно кэшируйте свою офлайн-страницу
Теперь создайте файл JavaScript с именем serviceworker.js
. Это сценарий, на который браузер будет обращать внимание при возникновении определенных событий. Первое событие, которое нужно обработать, — это то, что делать, когда сервис-воркер установлен на устройстве пользователя. Когда это происходит, запускается событие с именем install
. Вы можете прослушать это событие, используя addEventListener
:
addEventListener('install', installEvent => {
// put your instructions here.
}); // end addEventListener
В этом случае вы хотите убедиться, что ваша любовно созданная пользовательская офлайн-страница помещена в хороший безопасный кеш. Для этого можно использовать Cache API. Вы можете создать столько кешей, сколько захотите, и можете называть их как хотите. Здесь я назову кеш Johnny
только для того, чтобы в коде я мог обращаться к нему как JohnnyCache
:
addEventListener('install', installEvent => {
installEvent.waitUntil(
caches.open('Johnny')
.then( JohnnyCache => {
JohnnyCache.addAll([
'/offline.html'
]); // end addAll
}) // end open.then
); // end waitUntil
}); // end addEventListener
Могу поспорить, что ваша прекрасная офлайн-страница ссылается на файл CSS, может быть, на изображение или два и, возможно, на JavaScript. Вы можете кэшировать все это на этом этапе:
addEventListener('install', installEvent => {
installEvent.waitUntil(
caches.open('Johnny')
.then( JohnnyCache => {
JohnnyCache.addAll([
'/offline.html',
'/path/to/stylesheet.css',
'/path/to/javascript.js',
'/path/to/image.jpg'
]); // end addAll
}) // end open.then
); // end waitUntil
}); // end addEventListener
Убедитесь, что URL-адреса указаны правильно. Если хотя бы один из URL-адресов в списке не может быть разрешен, ни один из элементов в списке не будет кэширован.
Перехват запросов
Следующее событие, которое вы хотите прослушать, — это событие fetch
. Это, пожалуй, самая мощная — и, будем честны, самая жуткая — функция сервис-воркера. После установки сервис-воркер прячется на устройстве пользователя, ожидая любых запросов к вашему сайту. Каждый раз, когда пользователь запрашивает веб-страницу с вашего сайта, срабатывает событие fetch
. Каждый раз, когда эта страница запрашивает таблицу стилей или изображение, срабатывает событие fetch
. Вы можете предоставить инструкции о том, что должно происходить каждый раз:
addEventListener('fetch', fetchEvent => {
// What happens next is up to you!
}); // end addEventListener
Напишем достаточно консервативный скрипт со следующей логикой:
- Всякий раз, когда запрашивается файл,
- Во-первых, попробуйте получить его из сети,
- Но если не получится, попробуй найти в кеше,
- Но если это не работает, и это запрос на веб-страницу, вместо этого покажите пользовательскую автономную страницу.
Вот как это переводится в JavaScript:
// Whenever a file is requested
addEventListener('fetch', fetchEvent => {
const request = fetchEvent.request;
fetchEvent.respondWith(
// First, try to fetch it from the network
fetch(request)
.then( responseFromFetch => {
return responseFromFetch;
}) // end fetch.then
// But if that doesn't work
.catch( fetchError => {
// try to find it in the cache
caches.match(request)
.then( responseFromCache => {
if (responseFromCache) {
return responseFromCache;
// But if that doesn't work
} else {
// and it's a request for a web page
if (request.headers.get('Accept').includes('text/html')) {
// show the custom offline page instead
return caches.match('/offline.html');
} // end if
} // end if/else
}) // end match.then
}) // end fetch.catch
); // end respondWith
}); // end addEventListener
Я полностью осознаю, что, возможно, нарисовал там какую-то сову. Если вам нужна более подробная разбивка того, что происходит в каждой точке кода, я написал для вас целую книгу. Это идеальный подарок для Мерфимы.
Подключите свой скрипт сервисного работника
Вы можете опубликовать свой скрипт сервис-воркера по адресу /serviceworker.js
, но вам все равно нужно указать браузеру, где его искать. Вы можете сделать это с помощью JavaScript. Поместите это в существующий файл JavaScript, который вы вызываете на каждой странице вашего сайта, или добавьте это в элемент script
в конце HTML-кода каждой страницы:
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js');
}
Это говорит браузеру начать установку сервис-воркера, но не без предварительной проверки того, что браузер понимает, что такое сервис-воркер. Когда дело доходит до JavaScript, обнаружение функций — ваш друг.
Возможно, у вас уже есть несколько файлов JavaScript в такой папке, как /assets/js/
, и у вас может возникнуть соблазн поместить туда свой скрипт сервисного работника. Не делай этого. Если вы это сделаете, сервис-воркер сможет обрабатывать запросы к файлам только в пределах /assets/js/
. Поместив сценарий сервис-воркера в корневой каталог, вы гарантируете, что каждый запрос может быть перехвачен.
Идти дальше!
Отлично сделано! Вы позаботились о том, чтобы, если — нет, когда — посетитель не смог попасть на ваш веб-сайт, он попадет на вашу офлайн-страницу, созданную вручную. Вы временно победили силы хаоса! Вы недолго боролись с волной энтропии! Вы сделали маленький, но в конечном итоге тщетный жест против неизбежной тепловой смерти Вселенной!
Это только начало. Вы можете сделать больше с сервисными работниками.
Что если каждый раз, когда вы загружаете страницу из сети, вы сохраняете копию этой страницы в кэше? Затем, если этот человек попытается открыть эту страницу позже, но он не в сети, вы можете показать ему кешированную версию.
Или что, если вместо того, чтобы сначала обращаться к сети, вы сначала проверяете, находится ли файл в кеше? Вы могли бы обслуживать эту кешированную версию — что было бы молниеносно быстро — и при этом получать свежую версию из сети в фоновом режиме, чтобы использовать кеш в следующий раз. Это может быть хорошей стратегией для изображений.
Столько вариантов! Сложность заключается не в написании кода, а в определении шагов, которые вы хотите предпринять. После того, как вы записали эти шаги, нужно перевести их в JavaScript.
Неизбежно на этом пути будут некоторые препятствия — обычно это неуместная фигурная скобка или отсутствующая скобка. Не будьте слишком строги к себе, если ваш код сначала не работает. Это просто закон Мерфи в действии.
Изначально это было опубликовано на моем собственном сайте.