Привет, друзья. С Новым годом и Рождеством всех вас. Недавно моя девушка, работая с сайтом на CMS Битрикс, столкнулась с задачей вывести лендинг на странице поиска и попросила помочь. Я сначала подумал, что это какой-то бред, а потом оказалось, что речь идёт о локальном поиске на сайте и в шаблоне действительно есть возможность настроить продающую страничку и оформить ее под запрос клиента если товар действительно есть на сайте. А уже под мини-лендингом идут остальные результаты поиска.
Мне показалось это действительно крутой идеей, и я задумался над тем, как еще можно оптимизировать тот или иной момент с целью повышения конверсии, но уже на лендинге. Как применить что-то подобное и в своих проектах?
Да, есть всякие виджеты, есть всплывающее окно, которое появляется, когда посетитель пытается покинуть сайт (кстати, скоро сделаю такой виджет), но это все достаточно банально. Хотелось найти еще что-то и в голову пришла идея, что можно попробовать вернуть часть клиентов и даже предложить им что-то даже если у посетителя вдруг пропал интернет.
Я много слышал об офлайн версии сайта или о том, что можно показать особенную страницу или туже (закешированную), если у пользователя вдруг пропадает интернет-соединение, но понятия не имел как это реализовать. Обдумывая способ как еще можно влиять на конверсию на лендинге я решил зацепиться за эту идею и попробовать реализовать ее, а результатом поделиться в блоге. Об этом и пойдет речь в статье. Будем делать offline мини-лендинг для пользователей, у которых неожиданно пропадает интернет, и они больше не могут перемещаться по сайту. Согласитесь, что неплохо было бы вернуть часть таких пользователей. Вы, в свою очередь, можете сделать полноценную продающую страницу или еще как-то обыграть эту ситуацию.
Прежде чем начать
Так как для реализации задуманной идеи мы будем использовать service worker, то хотелось бы пояснить в двух словах что это такое.
Простым языком service worker это некий скрипт, который выполняется браузером в фоновом режиме. Он никак не взаимодействует со страницей, поэтому не влияет на скорость ее загрузки, выполняется в отдельном потоке и нужен для обработки сетевых запросов, работой с закешированными ресурсами, отправки push-уведомлений и другого.
Подробнее можно почитать тут: developer.mozilla.org. Для вас это все будет в виде готового скрипта, в котором нужно просто прописать пути к файлам, которые будут использоваться при потере интернет-соединения.
Несколько условий и условностей для работы
- Вся задумка заработает только при подключении https, так что если вы еще каким-то чудом не перешли на этот протокол, то давно пора.
- Скрипт service-worker размещаем в корне сайта, это связанно с особенностью его работы. Если разместить сервис-воркер, например, в папке «/js/», то он сможет обработать запросы только внутри этой директории.
Приступаем
Я подготовил для вас папку “offline” с исходником простейшего лендинга и файл “service-worker.js” которые нужно поместить в корень сайта.
Файлы для создания offline страницы сайта
Размер: 69 кб

Давайте разбираться подробнее. Как и говорил, на скриншоте пример обычного статического сайта, в корне которого есть файл service-worker.js и папка "offline" с лендингом, который будет показываться при потере интернета у пользователя. Я набросал скромный пример простой страницы больше похожей на модальное окно, но вы можете сделать полноценный лендинг.

Итак, скачайте архив, распакуйте его и поместите файл service-worker.js и папку "offline" в корень сайта.
Затем разместите следующий js-код в футере вашей посадочной страницы перед закрывающим тегом "body".
<script>
if ('serviceWorker' in navigator) {
console.log('CLIENT: service worker registration in progress.');
navigator.serviceWorker.register('/service-worker.js').then(function () {
console.log('CLIENT: service worker registration complete.');
}, function () {
console.log('CLIENT: service worker registration failure.');
});
} else {
console.log('CLIENT: service worker is not supported.');
}
</script>
Тут ничего менять не нужно, если не хотите изменить само название воркера.
Теперь можете перейти в папку "offline" и изменить мой пример лендинга под свои нужды. Я назвал файл "offline-landing.html". Вам не обязательно оставлять такое имя.

Когда закончите с версткой, откройте файл "service-worker.js" и пропишите пути к элементам, которые использовали на странице. Это те элементы, которые будут закешированы браузером и смогут подгрузиться, когда пропадет соединение с сетью. Я подготовил специальный массив для этого.

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

Чтобы посмотреть какие ресурсы были успешно закешированы перейдите во вкладку "Application" и выберите "Cache Storage".

Для отладки вам придется регулярно очищать кеш и другие данные. Проще всего это делать тут:

Чтобы тестировать все без отключения интернета, можно перейти в пункт "Service Workers", выбрать режим "offline" и обновить страницу. Так интернет-соединение пропадет только на этой вкладке.

На этом, пока, - все. Если у вас есть еще какие-то идеи как можно оптимизировать ту или иную ситуацию или элемент на сайте для повышения его эффективности, напишите пожалуйста в комментариях. Возможно, ваша идея станет поводом для новой статьи. Спасибо вам за отклик.
Посмотреть пример того, как это все работает можно и на примере моего блога. Сделал на основе этой статьи простую страничку и для своего сайта.
Полезные ссылки для погружения в тему:
- Статья на Хабре.
- Статья на css-tricks.com.
6 комментариев
Задумка интересная, но есть проблемы. В основном они выражаются в том, что на Android периодически отваливаются стили, а на iOS так вообще не удалось их подтянуть. Даже у вас на демо с девайсов на iOS выводится только содержимое html.
Владимир, здравствуйте. Да, пока, не все идеально. Сам тоже заметил.
Есть мысли как исправить? Такое ощущение, что проблемы кроются в кэшировании.
И еще такой момент. Для тестирования я взял ваш демо-исходник, заменил только текст в html и цвета в CSS, то есть правки были минимальны. Тем не менее даже на Android у меня проблема проявляется чаще чем у вас. Есть возможность скинуть исходник, используемый у вас на сайте? Наверняка он отличается от того, который опубликован в статье.
У меня на сайте такой же:
[javascript]
const CACHEVERSION = 1;
const CACHENAME = 'offline landing';
const OFFLINELANDINGURL = '/offline/offline-landing.html';
const OFFLINESTYLEURL = '/offline/css/offline.css';
const OFFLINESCRIPTSURL = '/offline/js/offline.js';
const OFFLINEIMGURL = '/offline/img/logo.png';
const OFFLINEFAVICONURL = '/favicon-16x16.png';
const OFFLINEFONTSURL = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700;900&display=swap';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(CACHENAME);
await cache.addAll([OFFLINELANDINGURL, OFFLINESTYLEURL, OFFLINESCRIPTSURL, OFFLINEFAVICONURL, OFFLINEFONTSURL, OFFLINEIMGURL]);
})());
});
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
if ('navigationPreload' in self.registration) {
await self.registration.navigationPreload.enable();
}
})());
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
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) {
console.log('Fetch failed; returning offline page instead.', error);
const cache = await caches.open(CACHENAME);
const cachedResponse = await cache.match(OFFLINELANDINGURL);
return cachedResponse;
}
})());
}
});
[javascript]
В примере код у вас другой. Заменил его на этот, стало работать более стабильно, но по какой-то неведомой мне причине не выводится logo.png
Попробовала сделать на сайте вордпресс, не получилось(