Workbox предоставляет мощный и гибкий механизм для создания
сервис-воркеров, а также управления кэшированием и стратегиями получения
ресурсов. Одним из ключевых аспектов является возможность определения
кастомных стратегий, которые выходят за рамки
стандартных стратегий (CacheFirst,
NetworkFirst, StaleWhileRevalidate и т.д.).
Для крупных проектов и проектов на TypeScript важна строгая
типизация этих стратегий, чтобы обеспечить корректность
кода и удобство автодополнения.
Кастомная стратегия в Workbox строится на наследовании от
базового класса Strategy:
import { Strategy } from 'workbox-strategies';
class CustomStrategy extends Strategy {
async _handle(request, handler) {
// request – объект Request
// handler – объект StrategyHandler
const response = await handler.fetch(request);
return response;
}
}
_handle является центральным элементом кастомной
стратегии.request — это объект класса
Request, который представляет HTTP-запрос.handler предоставляет доступ к стандартным
методам стратегии (fetch, cacheMatch,
cachePut), что позволяет комбинировать кэширование и
сетевые запросы.Для строгой типизации кастомных стратегий можно определить
интерфейс параметров стратегии и типизацию метода
_handle. В Workbox базовые типы экспортируются из пакета
workbox-core и workbox-strategies.
import { Strategy, StrategyHandler } from 'workbox-strategies';
interface CustomStrategyOptions {
cacheName?: string;
maxAgeSeconds?: number;
}
class TypedCustomStrategy extends Strategy {
private options: CustomStrategyOptions;
constructor(options: CustomStrategyOptions) {
super();
this.options = options;
}
protected async _handle(
request: Request,
handler: StrategyHandler
): Promise<Response> {
const cachedResponse = await handler.cacheMatch(request);
if (cachedResponse) {
return cachedResponse;
}
const response = await handler.fetch(request);
await handler.cachePut(request, response.clone());
return response;
}
}
_handle возвращает
Promise<Response>, что соответствует стандарту работы
с асинхронными сетевыми операциями.handler.cacheMatch(request) проверяет наличие ресурса в
кэше, а handler.cachePut(request, response) добавляет его в
кэш.Для интеграции кастомной стратегии с роутингом Workbox важно, чтобы
стратегия соответствовала интерфейсу RouteHandler. Пример
регистрации маршрута с кастомной стратегией:
import { registerRoute } from 'workbox-routing';
const strategy = new TypedCustomStrategy({ cacheName: 'custom-cache', maxAgeSeconds: 3600 });
registerRoute(
({ request }) => request.destination === 'script',
strategy
);
Strategy, автоматически
реализует интерфейс RouteHandler.CacheFirst,
NetworkFirst).Если стратегия использует дополнительные методы, например, фильтрацию по заголовкам или динамическое управление кэшем, полезно расширять интерфейсы:
interface AdvancedStrategyOptions extends CustomStrategyOptions {
filterHeaders?: string[];
}
class AdvancedCustomStrategy extends Strategy {
private options: AdvancedStrategyOptions;
constructor(options: AdvancedStrategyOptions) {
super();
this.options = options;
}
protected async _handle(request: Request, handler: StrategyHandler): Promise<Response> {
let response = await handler.fetch(request);
if (this.options.filterHeaders) {
const filteredResponse = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: this.filterResponseHeaders(response.headers),
});
response = filteredResponse;
}
await handler.cachePut(request, response.clone());
return response;
}
private filterResponseHeaders(headers: Headers): Headers {
const filtered = new Headers();
this.options.filterHeaders?.forEach(header => {
const value = headers.get(header);
if (value) filtered.set(header, value);
});
return filtered;
}
}
filterResponseHeaders возвращает объект
Headers, сохраняя строгую типизацию.StrategyHandler с корректными
generic-типами — повышает безопасность работы с кэшем и
сетевыми запросами.Strategy — сохраняет совместимость с остальной
инфраструктурой Workbox.Эти подходы позволяют строить масштабируемые и безопасные сервис-воркеры, где каждая кастомная стратегия полностью типизирована и легко интегрируется с существующими маршрутами и стандартными стратегиями.