Как создать полезную офлайн-страницу для веб-приложения

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

Оригинал данной статьи на английском:Ada Rose Cannon: Making a useful ‘offline’ page for your web app

Web Development
Web Development

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

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

Если мы не предусмотрели это обстоятельство, то можем увидеть сообщение об отсутствии подключения к интернету.

Как создать полезную офлайн-страницу для веб-приложения

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

Как создать полезную офлайн-страницу для веб-приложения

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

Но возможности подобных страниц этим не ограничиваются. С их помощью также можно предложить пользователю какое-нибудь увлекательное занятие, например разгадывание кроссворда. Именно так вам предстоит провести время на офлайн-странице блога разработчиков “The Guardian” в момент потери соединения.

Кроссворд на офлайн-странице The Guardian
Кроссворд на офлайн-странице The Guardian

Создание полезной офлайн-страницы для большинства веб-приложений

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

Как создать полезную офлайн-страницу для веб-приложения

Здесь в качестве примера приложения приводится FeedReader, программа для чтения формата RSS, благодаря которой пользователь может прочитать текстовый контент RSS-канала по URL-адресу, например вот такому:

/feed/?url=https://ada.is/feed

Это приложение обрабатывается на сервере и возвращает все данные в формате HTML-страниц, которые кэшируются при помощи сервис-воркера. Если же ваше приложение использует для заполнения страниц на стороне клиента формат JSON, то этот метод по-прежнему будет работать при условии кэширования и JSON-ответов, и отображающих их страниц.

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

Шаг 1. Предварительное кэширование офлайн-страницы

Прежде всего, нам нужно сохранить офлайн-страницу при запуске приложения. С этой целью при старте были кэшированы HTML-файл /offline/ и его ресурсы /offline.js через заполнение кэша во время события install, выполняемого сервис-воркером.

const CACHE_NAME = "DENORSS-v1.0.0"; self.addEventListener("install", (event) => { event.waitUntil( caches .open(CACHE_NAME) .then((cache) => cache.addAll(["/", "/offline/", "/offline.js"]) ) .then(self.skipWaiting()) ); });

Шаг 2. Показ офлайн-страницы

Далее, когда пользователь пытается перейти на страницу, которой у нас нет, мы можем показать кэшированную страницу /offline/.

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

// Попытаться отобразить офлайн-страницу при навигации if (event.request.mode === "navigate") { const offlinePage = await caches.match("/offline/"); if (offlinePage) return offlinePage; }

Шаг 3. Получение списка кэшированных страниц

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

Как создать полезную офлайн-страницу для веб-приложения

Сначала необходимо открыть кэши веб-приложений для поиска страниц, к которым нужно получить доступ:

const cacheKeys = await window.caches.keys(); const caches = await Promise.all( cacheKeys.map((cacheName) => window.caches.open(cacheName)) );

Так мы получаем массив кэшей.

После этого требуется найти все кэшированные страницы из этого массива. С помощью cache.matchAll и ignoreSearch: true получим все результаты кэша в конечной точке /feed/.

const results = await Promise.all( caches.map((cache) => cache.matchAll("/feed/", { ignoreSearch: true, }) ) );

Я просмотрела лишь конечную точку /feed/, поскольку, по моим ощущениям, такие страницы, как /search/ с результатами поиска или /404.html с сообщениями об ошибках, не будут представлять практической ценности для пользователя. Что касается главных страниц, таких как домашняя страница /, то они уже привязаны ссылками в навигационной панели.

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

results.flat().forEach(async (response) => { // Здесь размещается код });

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

const params = new URLSearchParams(new URL(response.url).search); const urlParam = params.get('url'); if (!urlParam) return;

Без параметра запроса url страница не представляет интереса, поэтому мы ее не показываем.

Шаг 4. Отображение списка

На данном этапе мы располагаем URL-адресами страниц и необработанными параметрами запросов, но в таком виде они могут не понравиться пользователю. Можно показать более привлекательные ярлыки, если обратиться к самому кэшированному содержимому.

Для извлечения данных из ответа нам необходимо получить его текст:

const dataAsString = await response.text();

Если ваши данные хранятся в формате JSON, то JSON.parse будет достаточно для извлечения любой интересной информации, например заголовка хорошей страницы.

const data = JSON.parse(dataAsString);

const title = data.title;

Учитывая, что наш веб-сайт отображается на стороне сервера и использует HTML, я выполню парсинг HTML. К счастью, веб-браузеры прекрасно справляются с этой задачей. Мы преобразуем необработанный текст в фрагмент документа, который можно запросить с помощью обычных методов DOM.

В следующем примере прочитаем текст в теге . Другими подходящими элементами для запроса были бы <h1> или <h2>, позволяющие получить первый заголовок в документе.

const html = document .createRange() .createContextualFragment(dataAsString); const title = html .querySelector("title") .textContent.trim();

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

el.insertAdjacentHTML( "beforeend", `<li><a href="${response.url}">${title}</a></li>` );

Анимация ниже отражает принцип работы нашей офлайн-страницы и был создан при помощи Chrome, имитирующего отсутствие сетевого соединения.

Благодарю за внимание и надеюсь, что материал статьи будет вам полезен!

1
Начать дискуссию