@sozialhelden/fetch-cache
v2.0.1
Published
A cached WhatWG fetch with URLs as cache keys, featuring eviction based on LRU, maximal item count and/or TTL.
Downloads
74
Readme
fetch-cache 🐕
A cache for WhatWG fetch calls.
- Supports TypeScript
- Uses normalized URLs as cache keys
- Can normalize URLs for better performance (you can configure how)
- Does not request the same resource twice if the first request is still loading
- Customizable TTLs per request, dependent on HTTP status code or in case of network errors
- Supports all Hamster Cache features, e.g. eviction based on LRU, maximal cached item count and/or per-item TTL.
- Runs in NodeJS, but should be isometric && browser-compatible (not tested yet! try at your own risk 🙃)
Installation
npm install --save @sozialhelden/fetch-cache
#or
yarn add @sozialhelden/fetch-cache
Usage examples
Initialization
Bring your own fetch
- for example:
- your modern browser's fetch function
- node-fetch, a NodeJS implementation
- fetch-retry for automatic request retrying with exponential backoff
- isomorphic-unfetch, an isometric implementation for browsers (legacy and modern) and Node.js
Configure the cache and use cache.fetch()
as if you would call fetch()
directly:
import FetchCache from '@sozialhelden/fetch-cache';
const fetch = require('node-fetch'); // in NodeJS
// or
const fetch = window.fetch; // in newer browsers
const fetchCache = new FetchCache({
fetch,
cacheOptions: {
// Don't save more than 100 responses in the cache. Allows infinite responses by default
maximalItemCount: 100,
// When should the cache evict responses when its full?
evictExceedingItemsBy: 'lru', // Valid values: 'lru' or 'age'
// ...see https://github.com/sozialhelden/hamster-cache for all possible options
},
});
// either fetches a response over the network,
// or returns a cached promise with the same URL (if available)
const url = 'https://jsonplaceholder.typicode.com/todos/1';
fetchCache
.fetch(url, fetchOptions)
.then(response => response.body())
.then(console.log)
.catch(console.log);
Basic caching operations
// Add an external response promise and cache it for 10 seconds
const response = fetch('https://api.example.com');
// Insert a response you got from somewhere else
fetchCache.cache.set('http://example.com', response);
// Set a custom TTL of 10 seconds for this specific response
fetchCache.cache.set('http://example.com', response, { ttl: 10000 });
// gets the cached response without side effects
fetchCache.cache.peek(url);
// `true` if a response exists in the cache, `false` otherwise
fetchCache.cache.has(url);
// same as `peek`, but returns response with meta information
fetchCache.cache.peekItem(url);
// same as `get`, but returns response with meta information
fetchCache.cache.getItem(url);
// Let the cache collect garbage to save memory, for example in fixed time intervals
fetchCache.cache.evictExpiredItems();
// removes a response from the cache
fetchCache.cache.delete(url);
// forgets all cached responses
fetchCache.cache.clear();
Vary TTLs depending on HTTP response code, headers, and more
While the cache tries to guess working TTLs for most use cases, you might want to customize how long a response (or rejected promise) should stay in the cache before it makes a new request when you fetch the same URL again.
For example, you could set the TTL to one second, no matter if a request succeeds or fails (please don't really do this, except you have a good reason):
const fetchCache = new FetchCache({ fetch, ttl: () => 1000 });
…or configure varying TTLs for specific HTTP response status codes (better):
const fetchCache = new FetchCache({
fetch,
ttl: ({ response, state, error }) => {
// state is 'running', 'resolved' or 'rejected' here.
if (response) {
// If a response is successful, keep it in the cache for 2 minutes
if (response.status === 200) return 2 * 60 * 1000;
// If a response is successful, keep it in the cache for 10 seconds so it shows up if the
// resource begins to exist in the meantime
if (response.status === 404) return 10 * 1000;
}
// If you return `undefined` here, the cache will use default TTL values for all other cases.
},
});
For an overview about more cases, consult the default implementation.
Normalize URLs
You can improve caching performance by letting the cache know if more than one URL points to the
same server-side resource. For this, provide a normalizeURL
function that builds a canonical URL
from a given one.
The cache will only hold one response per canonical URL then. This saves memory and network bandwidth.
normalize-url
is a helpful NPM package implementing real-world normalization rules like SSL
enforcement and www.
vs. non-www.
-domain names. You can use it as normalization function:
# Install the package with
npm install normalize-url
# or
yarn add normalize-url
import normalizeURL from 'normalize-url';
import fetch from 'node-fetch';
// See https://github.com/sindresorhus/normalize-url#readme for all available normalization options
const cache = new FetchCache({
fetch,
normalizeURL(url) {
return normalizeURL(url, { forceHttps: true });
},
});
Contributors
Supported by
.