Отвечайте на запросы навигации, не дожидаясь сети, с помощью сервисного работника.
Запросы навигации – это запросы HTML-документов, которые браузер отправляет, когда вы вводите новый URL в адресной строке или переходите по ссылке на странице. Именно здесь сервисные работники оказывают наибольшее влияние на производительность: если вы используете сервисного работника для ответа на запросы навигации, не дожидаясь сети, вы можете гарантировать, что навигация будет надежно быстрой, а также устойчивой, когда сеть недоступна. Это самое большое преимущество сервисного работника по сравнению с кешированием HTTP.
Как описано в руководстве Как определить ресурсы, загруженные из сети, запрос на переход – это первый из потенциально многих запросов, сделанных в каскаде сетевого трафика. HTML-код, который вы загружаете с помощью запроса навигации, запускает поток всех остальных запросов на подресурсы, такие как изображения, скрипты и стили.
В обработчике событий fetch сервисного скрипта вы можете определить, является ли запрос навигацией, проверив свойство request.mode в FetchEvent. Если установлено значение 'navigate', то это запрос навигации.
Как правило, не следует использовать долгоживущие Cache-Control headers для кеширования HTML-ответа на запрос навигации. Обычно они должны удовлетворяться через сеть с помощью Cache-Control: no-cache, чтобы гарантировать, что HTML вместе с цепочкой последующих сетевых запросов (разумно) свеж. Если при каждом переходе на новую страницу отправлять запрос в сеть, то может снизиться скорость загрузки. По крайней мере, это означает, что он не будет надежно быстрым.
Различные подходы к архитектуре
Понять, как отвечать на запросы навигации, избегая сети, может быть непросто. Выбор подхода зависит от архитектуры сайта и количества уникальных URL, по которым могут переходить пользователи.
Универсального решения не существует, но приведенные ниже общие рекомендации помогут вам выбрать наиболее подходящий подход.
Небольшие статические сайты
Если ваше веб-приложение состоит из относительно небольшого количества (например, пары десятков) уникальных URL-адресов и каждый из этих URL-адресов соответствует отдельному статическому HTML-файлу, то один из жизнеспособных подходов – просто кэшировать все эти HTML-файлы и отвечать на запросы навигации с помощью соответствующего кэшированного HTML.
С помощью предварительного кеширования вы можете кешировать HTML-код заранее, как только будет установлен сервисный скрипт, и обновлять кешированный HTML-код каждый раз, когда вы перестраиваете свой сайт и повторно развертываете сервисный скрипт.
Если вы не хотите предварительно кешировать весь HTML-код (например, потому что пользователи обычно переходят только по некоторым URL на вашем сайте), можно использовать стратегию кеширования во время выполнения stale-while-revalidate. Однако будьте осторожны, поскольку каждый HTML-документ кешируется и обновляется отдельно. Использовать кеширование во время выполнения для HTML целесообразно, если у вас есть небольшое количество URL, которые часто посещают одни и те же пользователи, и если вы не против того, чтобы эти URL проверялись независимо друг от друга.
Одностраничные приложения
Одностраничная архитектура часто используется в современных веб-приложениях. В этом случае клиентский код JavaScript изменяет HTML-код в ответ на действия пользователя. В этой модели используется History API, чтобы изменять текущий URL по мере того, как пользователь взаимодействует с веб-приложением. Это приводит к тому, что навигация фактически имитируется. Хотя последующие переходы могут быть "поддельными", начальный переход является реальным, и по-прежнему важно убедиться, что он не заблокирован в сети.
К счастью, если вы используете архитектуру одностраничного приложения, существует простой шаблон для обслуживания начальной навигации из кеша: оболочка приложения. В этой модели сервисный работник отвечает на запросы навигации, возвращая один и тот же HTML-файл, который уже был предварительно кэширован, независимо от запрашиваемого URL-адреса. Этот HTML-код должен быть максимально простым и содержать, например, стандартный индикатор загрузки или скелетный контент. После того как браузер загрузит этот HTML-код из кеша, существующий клиентский код JavaScript возьмет на себя управление и отрисует правильный HTML-контент для URL из исходного запроса навигации.
В Workbox есть инструменты, необходимые для реализации этого подхода. navigateFallback
option позволяет указать, какой HTML-документ использовать в качестве оболочки приложения, а также задать необязательный белый и черный список, чтобы ограничить такое поведение для подмножества URL.
Многостраничные приложения
Если ваш веб-сервер генерирует HTML-код вашего сайта динамически или если у вас более нескольких десятков уникальных страниц, то избежать сети при обработке запросов навигации гораздо сложнее. Вам могут подойти советы из раздела Другие случаи.
Однако для некоторых многостраничных приложений можно реализовать сервис-воркер, который полностью воспроизводит логику, используемую веб-сервером для создания HTML. Этот подход лучше всего работает, если вы можете передавать информацию о маршрутизации и шаблонах между сервером и сервис-воркером, и особенно если ваш веб-сервер использует JavaScript (не полагаясь на функции, специфичные для Node.js, такие как доступ к файловой системе).
Если ваш веб-сервер относится к этой категории и вы хотите изучить один из подходов к переносу генерации HTML из сети в сервис-воркер, вам поможет руководство Beyond SPAs: alternative architectures for your PWA (Помимо одностраничных приложений: альтернативные архитектуры для вашего PWA).
Прочие
Если вы не можете отвечать на запросы навигации с помощью кешированного HTML, вы должны предпринять шаги, чтобы добавление сервисного работника на ваш сайт (для обработки других запросов, не связанных с HTML) не привело к замедлению вашей навигации. Запуск сервисного скрипта без использования его для ответа на запрос навигации приведет к небольшой задержке (как описано в статье Создание более быстрых и устойчивых приложений с помощью сервисного скрипта). Чтобы уменьшить эту задержку, включите предварительную загрузку навигации, а затем используйте ответ сети, который был предварительно загружен в обработчик событий fetch.
В Workbox есть вспомогательная библиотека, которая определяет, поддерживается ли предварительная загрузка навигации, и если да, то упрощает процесс передачи указания сервис-воркеру использовать ответ сети.