Кеширование

Хранилище кэша — мощный инструмент. Оно снижает зависимость ваших приложений от состояния сети. Грамотное использование кэша позволяет сделать ваше веб-приложение доступным офлайн и предоставлять ресурсы максимально быстро при любых условиях сети. Как упоминалось в разделе «Активы и данные», вы можете выбрать оптимальную стратегию кэширования необходимых ресурсов. Для управления кэшем ваш сервис-воркер взаимодействует с API хранилища кэша .

Browser Support

  • Хром: 43.
  • Край: 16.
  • Firefox: 41.
  • Сафари: 11.1.

Source

API хранилища кэша доступен из различных контекстов:

  • Контекст окна (основной поток вашего PWA).
  • Работник сферы услуг.
  • Любые другие работники, которых вы используете.

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

Что кэшировать

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

Эти ресурсы должны включать:

  • HTML-код главной страницы (start_url вашего приложения).
  • Таблицы стилей CSS, необходимые для основного пользовательского интерфейса.
  • Изображения, используемые в пользовательском интерфейсе.
  • Файлы JavaScript, необходимые для визуализации пользовательского интерфейса.
  • Данные, такие как JSON-файл, необходимые для отображения базового опыта.
  • Веб-шрифты.
  • В многостраничном приложении — другие HTML-документы, которые вы хотите отдать быстро или в автономном режиме.

Готово к работе в автономном режиме

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

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

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

Использование API

Используйте API Cache Storage для определения набора кэшей в вашем источнике, каждый из которых идентифицируется строковым именем, которое вы можете задать. Доступ к API осуществляется через объект caches , а метод open позволяет создать или открыть уже созданный кэш. Метод open возвращает обещание для объекта кэша.

caches.open("pwa-assets")
.then(cache => {
  // you can download and store, delete or update resources with cache arguments
});

Загрузка и хранение активов

Чтобы запросить у браузера загрузку и сохранение ресурсов, используйте методы add или addAll . Метод add отправляет запрос и сохраняет один HTTP-ответ, а addAll группу HTTP-ответов в виде транзакции, основанной на массиве запросов или URL-адресов.

caches.open("pwa-assets")
.then(cache => {
  cache.add("styles.css"); // it stores only one resource
  cache.addAll(["styles.css", "app.js"]); // it stores two resources
});

Интерфейс кэширования хранит весь ответ, включая заголовки и тело. Таким образом, вы можете получить его позже, используя HTTP-запрос или URL в качестве ключа. Как это сделать, описано в главе «Обслуживание» .

Когда кэшировать

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

Вам не нужно кэшировать все активы одновременно, вы можете кэшировать активы много раз в течение жизненного цикла вашего PWA, например:

  • По установке сервисного работника.
  • После загрузки первой страницы.
  • Когда пользователь переходит к разделу или маршруту.
  • Когда сеть простаивает.

Вы можете запросить кэширование новых файлов в основном потоке или в контексте сервис-воркера.

Кэширование ресурсов в сервис-воркере

Один из наиболее распространённых сценариев — кэширование минимального набора ресурсов при установке сервис-воркера. Для этого можно использовать интерфейс кэширования в событии install сервис-воркера.

Поскольку поток Service Worker может быть остановлен в любой момент, вы можете указать браузеру дождаться завершения выполнения addAll , чтобы увеличить вероятность сохранения всех ресурсов и поддержания согласованности приложения. В следующем примере показано, как это сделать, используя метод waitUntil аргумента события, полученного в прослушивателе событий Service Worker.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
   event.waitUntil(
      caches.open("pwa-assets")
      .then(cache => {
         return cache.addAll(urlsToCache);
      });
   );
});

Метод waitUntil() получает обещание и просит браузер дождаться завершения задачи из обещания (выполнения или сбоя), прежде чем завершить процесс Service Worker. Возможно, потребуется объединить обещания в цепочку и вернуть вызовы add() или addAll() чтобы метод waitUntil() получал один результат.

Вы также можете обрабатывать обещания, используя синтаксис async/await. В этом случае вам необходимо создать асинхронную функцию, которая может вызывать await и возвращать обещание в waitUntil() после своего вызова, как в следующем примере:

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
   let cacheUrls = async () => {
      const cache = await caches.open("pwa-assets");
      return cache.addAll(urlsToCache);
   };
   event.waitUntil(cacheUrls());
});

Междоменные запросы и непрозрачные ответы

Ваш PWA может загружать и кэшировать ресурсы из вашего источника и кросс-доменных источников, например, контент из сторонних CDN. В кросс-доменном приложении взаимодействие с кэшем очень похоже на запросы из одного источника. Запрос выполняется, и копия ответа сохраняется в вашем кэше. Как и другие кэшированные ресурсы, он доступен для использования только в источнике вашего приложения.

Ресурс будет сохранён как непрозрачный ответ , что означает, что ваш код не сможет видеть или изменять содержимое или заголовки этого ответа. Кроме того, непрозрачные ответы не отображают свой фактический размер в API хранилища, что влияет на квоты. Некоторые браузеры отображают большие объёмы, например, 7 МБ, даже если файл всего 1 КБ.

Обновление и удаление активов

Вы можете обновлять активы с помощью cache.put(request, response) и удалять активы с помощью delete(request) .

Более подробную информацию смотрите в документации по объекту Cache .

Отладка кэш-хранилища

Во многих браузерах есть возможность отладки содержимого кэша на вкладке «Приложение» в DevTools. Там можно увидеть содержимое каждого кэша в текущем источнике. Подробнее об этих инструментах мы расскажем в главе «Инструменты и отладка» .

Отладка содержимого кэш-хранилища с помощью Chrome DevTools.

Ресурсы