It's fairly common to want to put restrictions on a cache in terms of how long
it should allow items to be stored in a cache or how many items should be kept
in a cache. Workbox provides this functionality through the
workbox-expiration
plugin that allows you to limit the number of
entries in a cache and / or remove entries that have been cached for a long
period of time.
Restrict the Number of Cache Entries
To restrict the number of entries stored in a cache, you can use the
maxEntries
option like so:
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'image-cache',
plugins: [
new ExpirationPlugin({
maxEntries: 20,
}),
],
})
);
With this, the Plugin will be added to this route. After a cached response is used or a new request is added to the cache, the plugin will look at the configured cache and ensure that the number of cached entries doesn't exceed the limit. If it does, the oldest entries will be removed.
Restrict the Age of Cached Entries
To restrict how long a request is cached for, you can define a max age in
seconds using the maxAgeSeconds
option like so:
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'image-cache',
plugins: [
new ExpirationPlugin({
maxAgeSeconds: 24 * 60 * 60,
}),
],
})
);
The plugin will check and remove entries after each request or cache update.
Advanced Usage
If you'd like to use the expiration logic separate from any other Workbox
module, you can do so with the
CacheExpiration
class.
To apply restrictions to a cache, you'd create an instance of CacheExpiration
for the cache you want to control like so:
import {CacheExpiration} from 'workbox-expiration';
const cacheName = 'my-cache';
const expirationManager = new CacheExpiration(cacheName, {
maxAgeSeconds: 24 * 60 * 60,
maxEntries: 20,
});
Whenever you update a cached entry, you need to call the updateTimestamp()
method so that its age is updated.
await openCache.put(request, response);
await expirationManager.updateTimestamp(request.url);
Then, whenever you want to expire a set of entries, you can call the
expireEntries()
method which will enforce the maxAgeSeconds
and
maxEntries
configuration.
await expirationManager.expireEntries();
Types
CacheExpiration
The CacheExpiration
class allows you define an expiration and / or
limit on the number of responses stored in a
Cache
.
Properties
-
constructor
void
To construct a new CacheExpiration instance you must provide at least one of the
config
properties.The
constructor
function looks like:(cacheName: string, config?: CacheExpirationConfig) => {...}
-
cacheName
string
Name of the cache to apply restrictions to.
-
config
CacheExpirationConfig optional
-
returns
-
-
delete
void
Removes the IndexedDB object store used to keep track of cache expiration metadata.
The
delete
function looks like:() => {...}
-
returns
Promise<void>
-
-
expireEntries
void
Expires entries for the given cache and given criteria.
The
expireEntries
function looks like:() => {...}
-
returns
Promise<void>
-
-
isURLExpired
void
Can be used to check if a URL has expired or not before it's used.
This requires a look up from IndexedDB, so can be slow.
Note: This method will not remove the cached entry, call
expireEntries()
to remove indexedDB and Cache entries.The
isURLExpired
function looks like:(url: string) => {...}
-
url
string
-
returns
Promise<boolean>
-
-
updateTimestamp
void
Update the timestamp for the given URL. This ensures the when removing entries based on maximum entries, most recently used is accurate or when expiring, the timestamp is up-to-date.
The
updateTimestamp
function looks like:(url: string) => {...}
-
url
string
-
returns
Promise<void>
-
ExpirationPlugin
This plugin can be used in a workbox-strategy
to regularly enforce a
limit on the age and / or the number of cached requests.
It can only be used with workbox-strategy
instances that have a
custom cacheName
property set.
In other words, it can't be used to expire entries in strategy that uses the
default runtime cache name.
Whenever a cached response is used or updated, this plugin will look at the associated cache and remove any old or extra responses.
When using maxAgeSeconds
, responses may be used once after expiring
because the expiration clean up will not have occurred until after the
cached response has been used. If the response has a "Date" header, then
a light weight expiration check is performed and the response will not be
used immediately.
When using maxEntries
, the entry least-recently requested will be removed
from the cache first.
Properties
-
constructor
void
The
constructor
function looks like:(config?: ExpirationPluginOptions) => {...}
-
config
ExpirationPluginOptions optional
-
returns
-
-
deleteCacheAndMetadata
void
This is a helper method that performs two operations:
- Deletes all the underlying Cache instances associated with this plugin instance, by calling caches.delete() on your behalf.
- Deletes the metadata from IndexedDB used to keep track of expiration details for each Cache instance.
When using cache expiration, calling this method is preferable to calling
caches.delete()
directly, since this will ensure that the IndexedDB metadata is also cleanly removed and open IndexedDB instances are deleted.Note that if you're not using cache expiration for a given cache, calling
caches.delete()
and passing in the cache's name should be sufficient. There is no Workbox-specific method needed for cleanup in that case.The
deleteCacheAndMetadata
function looks like:() => {...}
-
returns
Promise<void>
ExpirationPluginOptions
Properties
-
matchOptions
CacheQueryOptions optional
-
maxAgeSeconds
number optional
-
maxEntries
number optional
-
purgeOnQuotaError
boolean optional