Skip to content
Обучение Измерение Блог Case studies О сайте
Содержание
  • Резервная страница для автономного режима с адаптированным служебным сценарием
    • Регистрация служебного сценария
    • Код служебного сценария
    • Резервная страница для автономного режима
  • Демонстрация
    • Примечание о том, как добавить поддержку установки для приложения
    • Примечание о том, как передавать резервную страницу для автономного режима с помощью Workbox.js

Создание резервной страницы для автономного режима

Sep 24, 2020 — Обновлено May 19, 2021
Available in: Español, 日本語, 한국어, Português, 中文, English
Appears in: Прогрессивные веб-приложения
Thomas Steiner
Thomas Steiner
TwitterGitHubGlitchHomepage
Pete LePage
Pete LePage
TwitterGitHubGlitchHomepage
Содержание
  • Резервная страница для автономного режима с адаптированным служебным сценарием
    • Регистрация служебного сценария
    • Код служебного сценария
    • Резервная страница для автономного режима
  • Демонстрация
    • Примечание о том, как добавить поддержку установки для приложения
    • Примечание о том, как передавать резервную страницу для автономного режима с помощью Workbox.js

Что общего у приложений Google Assistant, Slack и Zoom, а также почти у всех других приложений, созданных для определенных платформ, на телефоне или компьютере? Да, они всегда предоставляют хоть какие-то возможности. Даже если нет подключения к сети, вы все равно можете открыть приложение Assistant, войти в приложение Slack или запустить приложение Zoom. Возможно, вы не получите ничего особенно значимого или даже не сможете сделать то, что хотели, но, по крайней мере, вам будет доступен хотя бы минимальный набор функций и вы сможете управлять приложением.

Мобильное приложение Google Assistant, работающее в автономном режиме.
Google Assistant.
Мобильное приложение Slack, работающее в автономном режиме.
Slack.
Мобильное приложение Zoom, работающее в автономном режиме.
Zoom.
Если вы используете приложения, созданные для определенной платформы, вы всегда получаете хоть какие-то возможности, даже если нет подключения к сети.

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

Мобильное приложение Google Chrome, в котором отображается оффлайн-игра с динозавром.
Google Chrome для iOS.
Приложение Google Chrome для компьютеров, в котором отображается оффлайн-игра с динозавром.
Google Chrome для macOS.
Если у вас нет подключения к сети, то по умолчанию вам недоступны никакие возможности в Интернете.

Резервная страница для автономного режима с адаптированным служебным сценарием #

Тем не менее всё необязательно должно быть именно так. С помощью служебных сценариев и Cache Storage API вы можете предоставить своим пользователям адаптированный интерфейс для работы в автономном режиме. Возможно, это будет простая страница с фирменной символикой и информацией о том, что в данный момент пользователь не подключен к сети. Но это может быть и более творческое решение, как, например, знаменитая оффлайн-игра Trivago с лабиринтом с кнопкой ручного повторного подключения к сети и автоматическим таймером, отсчитывающим время до следующей попытки подключения к сети.

Страница Trivago для автономного режима, на которой отображается оффлайн-игра с лабиринтом.
Оффлайн-игра Trivago с лабиринтом.

Регистрация служебного сценария #

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

window.addEventListener("load", () => {
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js");
}
});

Код служебного сценария #

На первый взгляд содержимое реального файла служебного сценария кажется немного запутанным, но с помощью комментариев в приведенном ниже примере можно разобраться в ситуации. Основная идея состоит в том, чтобы предварительно кэшировать файл offline.html, который передается только при неудачных запросах на переход между страницами, и позволить браузеру обрабатывать все остальные случаи:

/*
© Google LLC, 2015, 2019, 2020, 2021. Все права защищены.
Данный файл лицензирован на условиях лицензии Apache License 2.0 ("Лицензия");
использовать этот файл разрешено только в соответствии с Лицензией.
Текст Лицензии можно получить по адресу
http://www.apache.org/licenses/LICENSE-2.0
За исключением случаев, предусмотренных действующим законодательством или согласованных в письменной форме, программное обеспечение,
распространяемое на условиях Лицензии, предоставляется на УСЛОВИЯХ "КАК ЕСТЬ",
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ ИЛИ УСЛОВИЙ, явных или подразумеваемых.
Сведения об основных разрешениях и ограничениях в рамках Лицензии для определенных языков
см. в тексте Лицензии.
*/


// Если увеличить значение переменной OFFLINE_VERSION, будет создано событие установки и
// ранее кэшированные ресурсы будут обновлены из сети.
// Эта переменная намеренно объявлена и не используется.
// Если нужно, добавьте комментарий для своего анализатора кода:
// eslint-disable-next-line no-unused-vars
const OFFLINE_VERSION = 1;
const CACHE_NAME = "offline";
// При необходимости укажите здесь другой URL-адрес.
const OFFLINE_URL = "offline.html";

self.addEventListener("install", (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
// Если настроить {cache: 'reload'} в новом запросе,
// ответ гарантированно не будет получен из кэша HTTP; т. е. он будет получен из
// сети.
await cache.add(new Request(OFFLINE_URL, { cache: "reload" }));
})()
);
// Принудительный перевод ожидающего служебного сценария в активное состояние.
self.skipWaiting();
});

self.addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
// Включение предварительной загрузки при переходе между страницами, если эта функция поддерживается.
// См. сведения по ссылке https://developers.google.com/web/updates/2017/02/navigation-preload
if ("navigationPreload" in self.registration) {
await self.registration.navigationPreload.enable();
}
})()
);

// Сообщаем активному служебному сценарию, что необходимо немедленно получить контроль над страницей.
self.clients.claim();
});

self.addEventListener("fetch", (event) => {
// Нам нужно вызвать функцию event.respondWith(), только если это запрос на переход между
// HTML-страницами.
if (event.request.mode === "navigate") {
event.respondWith(
(async () => {
try {
// Прежде всего попытаемся использовать ответ предварительной загрузки при переходе между страницами, если эта функция поддерживается.
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
return preloadResponse;
}

// Всегда сначала проверяйте сеть.
const networkResponse = await fetch(event.request);
return networkResponse;
} catch (error) {
// Событие catch появляется только при возникновении исключения, которое, вероятно,
// вызвано ошибкой сети.
// Если функция fetch() возвращает допустимый ответ HTTP с кодом ответа в
// диапазоне 4xx или 5xx, функция catch() НЕ будет вызвана.
console.log("Не удалось получить данные; вместо этого возвращаем страницу для автономного режима.", error);

const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(OFFLINE_URL);
return cachedResponse;
}
})()
);
}

// Если выражение в условии if() ложно, то этот обработчик операции получения данных не перехватит
// запрос. Если зарегистрированы любые другие обработчики операций получения данных, они
// смогут вызвать метод event.respondWith(). Если ни один обработчик операций получения данных не вызовет метод
// event.respondWith(), браузер обработает запрос таким образом, как если бы
// не были задействованы никакие служебные сценарии.
});

Резервная страница для автономного режима #

Работая с файлом offline.html, вы можете проявить свои творческие способности, адаптировать файл к своим потребностям и добавить фирменное оформление вашей компании. В приведенном ниже примере показан минимум из того, что можно сделать. Здесь продемонстрированы ручная перезагрузка при нажатии кнопки, автоматическая перезагрузка по событию online и регулярный опрос сервера.

Обратите внимание

Вам потребуется кэшировать все ресурсы страницы для автономного режима. Один из способов сделать это — встроить в нее все необходимые ресурсы. Именно это мы делаем в приведенном ниже примере.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<title>Отсутствует подключение к сети</title>

<!-- Встраиваем таблицу стилей страницы. -->
<style>
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
}

h1 {
font-style: italic;
color: #373fff;
}

p {
margin-block: 1rem;
}

button {
display: block;
}
</style>
</head>
<body>
<h1>Отсутствует подключение к сети</h1>

<p>Чтобы перезагрузить страницу, нажмите расположенную ниже кнопку.</p>
<button type="button">⤾ Перезагрузить</button>

<!-- Встраиваем файл JavaScript страницы. -->
<script>
// Функция ручной перезагрузки.
document.querySelector("button").addEventListener("click", () => {
window.location.reload();
});

// Прослушиваем изменения состояния сети, при подключении к сети перезагружаем страницу.
// Здесь мы обрабатываем случай, когда устройство полностью отключено от сети.
window.addEventListener('online', () => {
window.location.reload();
});

// Проверяем, отвечает ли сервер. Если он отвечает, перезагружаем страницу.
// Здесь мы обрабатываем случай, когда устройство подключено к сети, но сервер
// недоступен или работает неправильно.
async function checkNetworkAndReload() {
try {
const response = await fetch('.');
// Проверяем, что мы получили допустимый ответ с сервера
if (response.status >= 200 && response.status < 500) {
window.location.reload();
return;
}
} catch {
// Не удается подключиться к серверу, игнорируем.
}
window.setTimeout(checkNetworkAndReload, 2500);
}

checkNetworkAndReload();
</script>
</body>
</html>

Демонстрация #

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

Примечание о том, как добавить поддержку установки для приложения #

Теперь, когда на вашем сайте есть резервная страница для автономного режима, у вас может появиться вопрос, что делать дальше. Чтобы ваше приложение можно было установить, необходимо добавить манифест веб-приложения и (при желании) разработать стратегию установки.

Примечание о том, как передавать резервную страницу для автономного режима с помощью Workbox.js #

Возможно, вы слышали о Workbox.js. Workbox.js — это набор библиотек JavaScript для поддержки автономного режима в веб-приложениях. Если вы не хотите самостоятельно писать код служебного сценария, вы можете использовать рецепт Workbox.js только для оффлайн-страницы.

Далее узнайте, как разработать стратегию установки для приложения.

Прогрессивные веб-приложения
Последнее обновление: May 19, 2021 — Улучшить статью
Return to all articles
Поделиться
подписаться

Contribute

  • Сообщить об ошибке
  • Просмотреть исходный код

Дополнительная информация

  • developer.chrome.com
  • Новости Chrome
  • Web Fundamentals
  • Разборы конкретных случаев
  • Подкасты
  • Шоу

Соцсети

  • Twitter
  • YouTube
  • Google Developers
  • Chrome
  • Firebase
  • Google Cloud Platform
  • Все продукты
  • Условия и конфиденциальность
  • Правила сообщества

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies.