This module efficiently precaches assets for Progressive Web Apps and service workers.
—
Custom route and strategy classes for implementing specific caching behaviors and request handling patterns. These classes provide the building blocks for advanced precaching setups.
Route subclass that uses PrecacheController for matching and handling requests with full support for precache-specific URL matching options.
/**
* Route subclass that uses PrecacheController for matching and handling requests
* Extends workbox-routing.Route
*/
class PrecacheRoute extends Route {
/**
* Create a new PrecacheRoute instance
* @param precacheController - PrecacheController instance for matching and responding
* @param options - Route matching options
*/
constructor(
precacheController: PrecacheController,
options?: PrecacheRouteOptions
);
}Usage Examples:
import { PrecacheController, PrecacheRoute } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
// Create controller and route
const controller = new PrecacheController();
const precacheRoute = new PrecacheRoute(controller, {
directoryIndex: "index.html",
cleanURLs: true,
ignoreURLParametersMatching: [/^utm_/, /^ref$/]
});
// Register the route
registerRoute(precacheRoute);
// Add assets to precache
controller.precache([
{ url: "/index.html", revision: "v1.0" },
{ url: "/about.html", revision: "v1.1" }
]);Strategy implementation specifically designed for precaching with built-in plugins and optimizations for serving precached content.
/**
* Strategy implementation specifically designed for precaching
* Extends workbox-strategies.Strategy
*/
class PrecacheStrategy extends Strategy {
/**
* Create a new PrecacheStrategy instance
* @param options - Strategy configuration options
*/
constructor(options?: PrecacheStrategyOptions);
/** Default plugin for cache response validation */
static readonly defaultPrecacheCacheabilityPlugin: WorkboxPlugin;
/** Plugin for handling redirected responses */
static readonly copyRedirectedCacheableResponsesPlugin: WorkboxPlugin;
}Usage Examples:
import { PrecacheStrategy } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
// Basic precache strategy
const strategy = new PrecacheStrategy({
cacheName: "precache-v1",
plugins: [
{
cacheKeyWillBeUsed: async ({ request, mode }) => {
// Custom cache key generation
return `${request.url}?v=2024`;
}
}
]
});
// Use with custom route
registerRoute(
({ request }) => request.destination === 'document',
strategy
);
// Access built-in plugins
const cacheabilityPlugin = PrecacheStrategy.defaultPrecacheCacheabilityPlugin;
const redirectPlugin = PrecacheStrategy.copyRedirectedCacheableResponsesPlugin;interface PrecacheRouteOptions {
/** Default file for directory requests (default: 'index.html') */
directoryIndex?: string;
/** URL parameters to ignore when matching (default: [/^utm_/, /^fbclid$/]) */
ignoreURLParametersMatching?: RegExp[];
/** Whether to try .html extension for clean URLs (default: true) */
cleanURLs?: boolean;
/** Custom URL manipulation function for generating additional URL variations */
urlManipulation?: urlManipulation;
}
interface PrecacheStrategyOptions {
/** Cache name (extends StrategyOptions) */
cacheName?: string;
/** Plugins array (extends StrategyOptions) */
plugins?: WorkboxPlugin[];
/** Fetch options (extends StrategyOptions) */
fetchOptions?: RequestInit;
/** Cache match options (extends StrategyOptions) */
matchOptions?: CacheQueryOptions;
/** Whether to fall back to network when cache lookup fails */
fallbackToNetwork?: boolean;
}The following errors may be thrown by PrecacheStrategy operations:
WorkboxError('missing-precache-entry') - Thrown when fallbackToNetwork: false and no cached response is foundWorkboxError('bad-precaching-response') - Thrown during installation if a response cannot be cached properlyimport {
PrecacheController,
PrecacheRoute,
PrecacheStrategy
} from "workbox-precaching";
import { registerRoute } from "workbox-routing";
// Different controllers for different asset types
const shellController = new PrecacheController({
cacheName: "app-shell-v1"
});
const resourceController = new PrecacheController({
cacheName: "resources-v1"
});
// Custom routes for each controller
const shellRoute = new PrecacheRoute(shellController, {
directoryIndex: "app.html"
});
const resourceRoute = new PrecacheRoute(resourceController, {
cleanURLs: false,
ignoreURLParametersMatching: []
});
// Register routes
registerRoute(shellRoute);
registerRoute(resourceRoute);import { PrecacheStrategy } from "workbox-precaching";
const customStrategy = new PrecacheStrategy({
cacheName: "enhanced-precache",
plugins: [
// Use built-in plugins
PrecacheStrategy.defaultPrecacheCacheabilityPlugin,
PrecacheStrategy.copyRedirectedCacheableResponsesPlugin,
// Add custom plugin
{
requestWillFetch: async ({ request }) => {
// Add custom headers
const modifiedRequest = new Request(request, {
headers: {
...request.headers,
'X-Precache-Version': '1.0'
}
});
return modifiedRequest;
},
cacheDidUpdate: async ({ cacheName, request, oldResponse, newResponse }) => {
// Log cache updates
console.log(`Cache updated: ${request.url}`);
// Notify other tabs about updates
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage({
type: 'CACHE_UPDATED',
url: request.url
});
}
}
}
]
});import { PrecacheController, PrecacheRoute } from "workbox-precaching";
const controller = new PrecacheController();
const route = new PrecacheRoute(controller, {
cleanURLs: true,
directoryIndex: "index.html",
// Custom URL manipulation for SPA routing
urlManipulation: ({ url }) => {
const additionalURLs: URL[] = [];
// For SPA routes, also try the root index.html
if (url.pathname.startsWith('/app/')) {
const rootUrl = new URL(url);
rootUrl.pathname = '/app/index.html';
additionalURLs.push(rootUrl);
}
// Try variations with/without trailing slashes
if (url.pathname.endsWith('/')) {
const withoutSlash = new URL(url);
withoutSlash.pathname = withoutSlash.pathname.slice(0, -1);
additionalURLs.push(withoutSlash);
} else {
const withSlash = new URL(url);
withSlash.pathname += '/';
additionalURLs.push(withSlash);
}
return additionalURLs;
}
});import { PrecacheStrategy } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
// Strategy for HTML documents
const documentStrategy = new PrecacheStrategy({
cacheName: "documents-precache",
plugins: [
{
cacheWillUpdate: async ({ response }) => {
// Only cache successful HTML responses
return response.status === 200 &&
response.headers.get('content-type')?.includes('text/html')
? response
: null;
}
}
]
});
// Strategy for static assets
const assetStrategy = new PrecacheStrategy({
cacheName: "assets-precache",
plugins: [
{
cacheWillUpdate: async ({ response }) => {
// Cache assets for longer periods
return response.status === 200 ? response : null;
}
}
]
});
// Register routes with different strategies
registerRoute(
({ request }) => request.destination === 'document',
documentStrategy
);
registerRoute(
({ request }) => ['style', 'script', 'image'].includes(request.destination),
assetStrategy
);import {
PrecacheController,
PrecacheRoute,
PrecacheStrategy
} from "workbox-precaching";
import { registerRoute } from "workbox-routing";
// 1. Create controller
const controller = new PrecacheController({
cacheName: "my-app-precache-v1"
});
// 2. Create custom strategy
const strategy = new PrecacheStrategy({
cacheName: "my-app-precache-v1",
plugins: [
PrecacheStrategy.defaultPrecacheCacheabilityPlugin,
{
cacheDidUpdate: async ({ cacheName, request }) => {
console.log(`Updated ${request.url} in ${cacheName}`);
}
}
]
});
// 3. Create and register route
const route = new PrecacheRoute(controller, {
directoryIndex: "index.html",
cleanURLs: true
});
registerRoute(route);
// 4. Add assets to precache
controller.precache([
{ url: "/", revision: "v1.0.0" },
{ url: "/about.html", revision: "v1.0.1" },
{ url: "/contact.html", revision: "v1.0.0" }
]);Install with Tessl CLI
npx tessl i tessl/npm-workbox-precaching