Мгновенная навигация

Дополнение традиционных методов предварительной выборки сервисными работниками.

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

С технической точки зрения перемещение по разным страницам означает выполнение запроса на навигацию . Как правило, вы не хотите использовать долгоживущие заголовки Cache-Control для кэширования ответа HTML на запрос навигации. Обычно их следует выполнять через сеть с помощью Cache-Control: no-cache , чтобы гарантировать, что HTML вместе с цепочкой последующих сетевых запросов является (достаточно) свежим. К сожалению, необходимость идти вразрез с сетью каждый раз, когда пользователь переходит на новую страницу, означает, что каждая навигация может быть медленной — по крайней мере, это означает, что она не будет надежно быстрой.

Чтобы ускорить эти запросы, если вы можете предвидеть действия пользователя, вы можете заранее запросить эти страницы и ресурсы и сохранить их в кеше в течение короткого периода времени, пока пользователь не нажмет на эти ссылки. Этот метод называется предварительной выборкой и обычно реализуется путем добавления на страницы тегов <link rel="prefetch"> , указывающих ресурс для предварительной выборки.

В этом руководстве мы рассмотрим различные способы использования сервис-воркеров в качестве дополнения к традиционным методам предварительной выборки.

Производственные кейсы

MercadoLibre — крупнейший сайт электронной коммерции в Латинской Америке. Чтобы ускорить навигацию, они динамически внедряют теги <link rel="prefetch"> в некоторые части потока. Например, на страницах списков они выбирают следующую страницу результатов, как только пользователь прокручивает список до конца:

Снимок экрана: первая и вторая страницы листинга MercadoLibre, а также тег Link Prefetch, соединяющий обе.

Предварительно загруженные файлы запрашиваются с «самым низким» приоритетом и сохраняются в кеше HTTP или кеше памяти (в зависимости от того, кэшируется ресурс или нет) в течение периода времени, который зависит от браузера. Например, в Chrome 85 это значение составляет 5 минут. Ресурсы хранятся в течение пяти минут, после чего применяются обычные правила Cache-Control для ресурса.

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

Например, итальянский спортивный портал Virgilio Sport использует сервис-воркеров для предварительной загрузки самых популярных публикаций на своей домашней странице. Они также используют API сетевой информации , чтобы избежать предварительной выборки для пользователей, находящихся в соединении 2G.

Логотип Вирджилио Спорт.

В результате за 3 недели наблюдения Virgilio Sport стал свидетелем того, как время загрузки для навигации по статьям улучшилось на 78% , а количество показов статей увеличилось на 45% .

Скриншот домашней страницы и страниц статей Virgilio Sport с показателями воздействия после предварительной загрузки.

Внедрение предварительного кэширования с помощью Workbox

В следующем разделе мы будем использовать Workbox, чтобы показать, как реализовать различные методы кэширования в сервисном работнике, которые можно использовать в качестве дополнения к <link rel="prefetch"> или даже замены ему, полностью делегируя эту задачу. работнику сервиса.

1. Предварительное кэширование статических страниц и подресурсов страниц.

Предварительное кэширование — это возможность сервисного работника сохранять файлы в кэше во время установки.

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

Предварительное кэширование статических страниц

Для страниц, которые создаются во время сборки (например, about.html , contact.html ) или на полностью статических сайтах, можно просто добавить документы сайта в список предварительного кэширования, чтобы они уже были доступны в кеше каждый раз, когда пользователь обращается к ним. их:

workbox.precaching.precacheAndRoute([
  {url: '/about.html', revision: 'abcd1234'},
  // ... other entries ...
]);

Предварительное кэширование подресурсов страницы

Предварительное кэширование статических ресурсов, которые могут использовать различные разделы сайта (например, JavaScript, CSS и т. д.), является общей рекомендуемой практикой и может дать дополнительный импульс в сценариях предварительной загрузки.

Чтобы ускорить навигацию на сайте электронной коммерции, вы можете использовать теги <link rel="prefetch"> на страницах списков для предварительной загрузки страниц с подробными сведениями о продуктах для первых нескольких продуктов на странице со списком. Если вы уже предварительно кэшировали подресурсы страницы продукта, это может сделать навигацию еще быстрее.

Чтобы реализовать это:

  • Добавьте на страницу тег <link rel="prefetch"> :
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • Добавьте подресурсы страницы в список прекэширования в сервис-воркере:
workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  // ... other entries ...
]);

2. Продлите срок службы ресурсов предварительной выборки.

Как упоминалось ранее, <link rel="prefetch"> извлекает и сохраняет ресурсы в HTTP-кеше в течение ограниченного периода времени, после чего применяются правила Cache-Control для ресурса. Начиная с Chrome 85, это значение составляет 5 минут.

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

В предыдущем примере можно было бы дополнить <link rel="prefetch"> используемый для предварительной загрузки страницы продукта, стратегией кэширования во время выполнения Workbox .

Чтобы реализовать это:

  • Добавьте на страницу тег <link rel="prefetch"> :
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • Реализуйте стратегию кэширования во время выполнения в сервис-воркере для следующих типов запросов:
new workbox.strategies.StaleWhileRevalidate({
  cacheName: 'document-cache',
  plugins: [
    new workbox.expiration.Plugin({
      maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
    }),
  ],
});

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

3. Делегируйте предварительную выборку сервисному работнику.

В большинстве случаев лучшим подходом является использование <link rel="prefetch"> . Тег представляет собой подсказку ресурса , призванную сделать предварительную выборку максимально эффективной.

Однако в некоторых случаях может быть лучше полностью делегировать эту задачу сервисному работнику. Например: чтобы предварительно загрузить первые несколько продуктов на странице со списком продуктов, отображаемой на стороне клиента, может потребоваться динамически внедрить на страницу несколько тегов <link rel="prefetch"> на основе ответа API. Это может на мгновение занять время в основном потоке страницы и затруднить реализацию.

В подобных случаях используйте «стратегию связи страницы с сервисным работником», чтобы полностью делегировать задачу предварительной загрузки сервисному работнику. Этот тип связи может быть достигнут с помощью worker.postMessage() :

Значок страницы, обеспечивающей двустороннюю связь с сервисным работником.

Пакет Workbox Window упрощает этот тип связи, абстрагируя многие детали выполняемого вызова.

Предварительную выборку с помощью Workbox Window можно реализовать следующим образом:

  • На странице: вызовите сервис-воркера, передав ему тип сообщения и список URL-адресов для предварительной выборки:
const wb = new Workbox('/sw.js');
wb.register();

const prefetchResponse = await wb.messageSW({type: 'PREFETCH_URLS', urls: […]});
  • В сервис-воркере: реализуйте обработчик сообщений для выдачи запроса fetch() для каждого URL-адреса для предварительной выборки:
addEventListener('message', (event) => {
  if (event.data.type === 'PREFETCH_URLS') {
    // Fetch URLs and store them in the cache
  }
});