Некоторые ресурсы вашего веб-приложения могут использоваться нечасто, иметь очень большой размер или варьироваться в зависимости от устройства пользователя (например, адаптивные изображения) или языка. Это случаи, когда предварительное кэширование может быть антишаблоном , и вместо этого вам следует полагаться на кэширование во время выполнения.
В Workbox вы можете управлять кэшированием ресурсов во время выполнения с помощью модуля workbox-routing
для сопоставления маршрутов, а также управлять стратегиями кэширования для них с помощью модуля workbox-strategies
.
Стратегии кэширования
Вы можете обрабатывать большинство маршрутов для ресурсов с помощью одной из встроенных стратегий кэширования. Они подробно описаны ранее в этой документации , но вот некоторые из них, которые стоит повторить:
- Stale While Revalidate использует кэшированный ответ на запрос, если он доступен, и обновляет кеш в фоновом режиме ответом из сети. Следовательно, если ресурс не кэширован, он будет ждать ответа сети и использовать его. Это довольно безопасная стратегия, поскольку она регулярно обновляет записи кэша, которые на нее полагаются. Недостатком является то, что он всегда запрашивает актив из сети в фоновом режиме.
- Network First пытается сначала получить ответ от сети. Если получен ответ, он передает этот ответ браузеру и сохраняет его в кеше. Если сетевой запрос завершается неудачей, будет использован последний кэшированный ответ, обеспечивающий автономный доступ к активу.
- Cache First сначала проверяет кеш на наличие ответа и использует его, если он доступен. Если запрос отсутствует в кеше, используется сеть, и любой действительный ответ добавляется в кеш перед передачей в браузер.
- Только сеть заставляет ответ поступать из сети.
- Cache Only заставляет ответ поступать из кеша.
Вы можете применять эти стратегии для выбора запросов, используя методы, предлагаемые workbox-routing
.
Применение стратегий кэширования с сопоставлением маршрутов
workbox-routing
предоставляет метод registerRoute
для сопоставления маршрутов и обработки их с помощью стратегии кэширования. registerRoute
принимает объект Route
, который, в свою очередь, принимает два аргумента:
- Строка, регулярное выражение или обратный вызов сопоставления для указания критериев соответствия маршрута.
- Обработчик маршрута — обычно стратегия, предоставляемая
workbox-strategies
.
Обратные вызовы сопоставления предпочтительнее для сопоставления маршрутов, поскольку они предоставляют объект контекста, включающий объект Request
, строку URL-адреса запроса, событие выборки и логическое значение, указывающее, является ли запрос запросом того же источника.
Затем обработчик обрабатывает сопоставленный маршрут. В следующем примере создается новый маршрут, который соответствует поступающим запросам изображений того же источника, сначала применяя кэш, а затем возвращаясь к сетевой стратегии .
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
// A new route that matches same-origin image requests and handles
// them with the cache-first, falling back to network strategy:
const imageRoute = new Route(({ request, sameOrigin }) => {
return sameOrigin && request.destination === 'image'
}, new CacheFirst());
// Register the new route
registerRoute(imageRoute);
Использование нескольких кэшей
Workbox позволяет группировать кэшированные ответы в отдельные экземпляры Cache
, используя cacheName
, доступную в связанных стратегиях.
В следующем примере изображения используют стратегию «устаревшие при повторной проверке», тогда как ресурсы CSS и JavaScript используют стратегию «сначала кэширования», возвращающуюся к сетевой стратегии. Маршрут для каждого ресурса помещает ответы в отдельные кэши путем добавления свойства cacheName
.
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
// Handle images:
const imageRoute = new Route(({ request }) => {
return request.destination === 'image'
}, new StaleWhileRevalidate({
cacheName: 'images'
}));
// Handle scripts:
const scriptsRoute = new Route(({ request }) => {
return request.destination === 'script';
}, new CacheFirst({
cacheName: 'scripts'
}));
// Handle styles:
const stylesRoute = new Route(({ request }) => {
return request.destination === 'style';
}, new CacheFirst({
cacheName: 'styles'
}));
// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);
registerRoute(stylesRoute);
Установка срока действия для записей кэша
Помните о квотах хранилища при управлении кэшами Service Worker. ExpirationPlugin
упрощает обслуживание кэша и предоставляется с помощью workbox-expiration
. Чтобы использовать его, укажите его в конфигурации стратегии кэширования:
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
// Evict image cache entries older thirty days:
const imageRoute = new Route(({ request }) => {
return request.destination === 'image';
}, new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 30,
})
]
}));
// Evict the least-used script cache entries when
// the cache has more than 50 entries:
const scriptsRoute = new Route(({ request }) => {
return request.destination === 'script';
}, new CacheFirst({
cacheName: 'scripts',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
})
]
}));
// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);
Соблюдение квот хранения может быть сложным. Хорошей практикой является рассмотрение пользователей, которые могут испытывать нехватку места для хранения или хотят наиболее эффективно использовать свое хранилище. Пары ExpirationPlugin
Workbox могут помочь в достижении этой цели.
Соображения о перекрестном происхождении
Взаимодействие между вашим сервисным работником и ресурсами перекрестного происхождения значительно отличается от взаимодействия с активами одного происхождения. Совместное использование ресурсов между источниками (CORS) сложно, и эта сложность распространяется на то, как вы обрабатываете ресурсы из разных источников в сервисном работнике.
Непрозрачные ответы
При выполнении запроса между источниками в режиме no-cors
ответ может храниться в кеше сервисного работника и даже использоваться непосредственно браузером. Однако само тело ответа невозможно прочитать с помощью JavaScript. Это известно как непрозрачный ответ .
Непрозрачные ответы — это мера безопасности, призванная предотвратить проверку активов перекрестного происхождения. Вы по-прежнему можете делать запросы к ресурсам перекрестного происхождения и даже кэшировать их, вы просто не можете прочитать тело ответа или даже прочитать его код состояния !
Не забудьте включить режим CORS.
Даже если вы загружаете ресурсы с перекрестным происхождением, которые устанавливают разрешающие заголовки CORS, позволяющие вам читать ответы, тело ответа с перекрестным происхождением все равно может быть непрозрачным. Например, следующий HTML-код вызовет запросы no-cors
, которые приведут к непрозрачным ответам независимо от того, какие заголовки CORS установлены:
<link rel="stylesheet" href="https://example.com/path/to/style.css">
<img src="https://example.com/path/to/image.png">
Чтобы явно запустить запрос cors
, который приведет к непрозрачному ответу, вам необходимо явно выбрать режим CORS, добавив атрибут crossorigin
в ваш HTML:
<link crossorigin="anonymous" rel="stylesheet" href="https://example.com/path/to/style.css">
<img crossorigin="anonymous" src="https://example.com/path/to/image.png">
Это важно помнить, когда маршруты в подресурсах кэша вашего сервисного работника загружаются во время выполнения.
Workbox может не кэшировать непрозрачные ответы.
По умолчанию Workbox осторожно подходит к кэшированию непрозрачных ответов. Поскольку невозможно проверить код ответа на наличие непрозрачных ответов, кэширование ответа об ошибке может привести к постоянным сбоям в работе, если используется стратегия «сначала кэш» или «только кэш».
Если вам необходимо кэшировать непрозрачный ответ в Workbox, для его обработки следует использовать стратегию «сначала сеть» или «устаревшую во время проверки». Да, это означает, что ресурс по-прежнему будет запрашиваться из сети каждый раз, но это гарантирует, что неудавшиеся ответы не сохранятся и в конечном итоге будут заменены пригодными для использования ответами.
Если вы используете другую стратегию кэширования и возвращается непрозрачный ответ, Workbox предупредит вас, что ответ не был кэширован в режиме разработки .
Принудительное кэширование непрозрачных ответов
Если вы абсолютно уверены , что хотите кэшировать непрозрачный ответ, используя стратегию «сначала кэш» или «только кэш», вы можете заставить Workbox сделать это с помощью модуля workbox-cacheable-response
:
import {Route, registerRoute} from 'workbox-routing';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
const cdnRoute = new Route(({url}) => {
return url === 'https://cdn.google.com/example-script.min.js';
}, new CacheFirst({
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200]
})
]
}))
registerRoute(cdnRoute);
Непрозрачные ответы и API navigator.storage
Чтобы избежать утечки междоменной информации, к размеру непрозрачного ответа, используемого для расчета пределов квоты хранилища, добавляется значительное дополнение. Это влияет на то, как API navigator.storage
сообщает о квотах хранилища.
Это заполнение зависит от браузера, но для Chrome минимальный размер, который любой один кэшированный непрозрачный ответ вносит в общий объем используемого хранилища, составляет примерно 7 мегабайт . Вы должны помнить об этом при определении количества непрозрачных ответов, которые вы хотите кэшировать, поскольку вы можете легко превысить квоты хранилища гораздо раньше, чем в противном случае ожидали бы.