Gathering detailed insights and metrics for axios-cache-adapter-fixed
Gathering detailed insights and metrics for axios-cache-adapter-fixed
Gathering detailed insights and metrics for axios-cache-adapter-fixed
Gathering detailed insights and metrics for axios-cache-adapter-fixed
Caching adapter for axios. Store request results in a configurable store to prevent unneeded network requests.
npm install axios-cache-adapter-fixed
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
1 Stars
385 Commits
1 Branches
1 Contributors
Updated on 14 Mar 2024
JavaScript (92.89%)
HTML (7.11%)
Cumulative downloads
Total Downloads
Last day
-17%
39
Compared to previous day
Last week
-45.1%
145
Compared to previous week
Last month
50.8%
739
Compared to previous month
Last year
65.5%
10,228
Compared to previous year
3
33
Caching adapter for axios. Store request results in a configurable store to prevent unneeded network requests.
Adapted from axios-cache-adapter
Using npm
1npm install --save axios-cache-adapter-fixed
Or bower
1bower install --save axios-cache-adapter-fixed
Or from a CDN like unpkg.com
1<script type="text/javascript" src="https://unpkg.com/axios-cache-adapter-fixed"></script>
Important note: Only GET
request results are cached by default. Executing a request using any method listed in exclude.methods
will invalidate the cache for the given URL.
You can instantiate the axios-cache-adapter-fixed
on its own using the setupCache()
method and then attach the adapter manually to an instance of axios
.
1// Import dependencies 2import axios from 'axios' 3import { setupCache } from 'axios-cache-adapter-fixed' 4 5// Create `axios-cache-adapter-fixed` instance 6const cache = setupCache({ 7 maxAge: 15 * 60 * 1000 8}) 9 10// Create `axios` instance passing the newly created `cache.adapter` 11const api = axios.create({ 12 adapter: cache.adapter 13}) 14 15// Send a GET request to some REST api 16api({ 17 url: 'http://some-rest.api/url', 18 method: 'get' 19}).then(async (response) => { 20 // Do something fantastic with response.data \o/ 21 console.log('Request response:', response) 22 23 // Interacting with the store, see `localForage` API. 24 const length = await cache.store.length() 25 26 console.log('Cache store length:', length) 27})
You can use the setup()
method to get an instance of axios
pre-configured with the axios-cache-adapter-fixed
. This will remove axios
as a direct dependency in your code.
1// Import dependencies 2import { setup } from 'axios-cache-adapter-fixed' 3 4// Create `axios` instance with pre-configured `axios-cache-adapter-fixed` attached to it 5const api = setup({ 6 // `axios` options 7 baseURL: 'http://some-rest.api', 8 9 // `axios-cache-adapter-fixed` options 10 cache: { 11 maxAge: 15 * 60 * 1000 12 } 13}) 14 15// Send a GET request to some REST api 16api.get('/url').then(async (response) => { 17 // Do something awesome with response.data \o/ 18 console.log('Request response:', response) 19 20 // Interacting with the store, see `localForage` API. 21 const length = await api.cache.length() 22 23 console.log('Cache store length:', length) 24})
After setting up axios-cache-adapter-fixed
with a specific cache configuration you can override parts of that configuration on individual requests.
1import { setup } from 'axios-cache-adapter-fixed' 2 3const api = setup({ 4 baseURL: 'https://httpbin.org', 5 6 cache: { 7 maxAge: 15 * 60 * 1000 8 } 9}) 10 11// Use global instance config 12api.get('/get').then((response) => { 13 // Do something awesome with response 14}) 15 16// Override `maxAge` and cache URLs with query parameters 17api.get('/get?with=query', { 18 cache: { 19 maxAge: 2 * 60 * 1000, // 2 min instead of 15 min 20 exclude: { query: false } 21 } 22}) 23 .then((response) => { 24 // Do something beautiful ;) 25 })
Note: Not all instance options can be overridden per request, see the API documentation at the end of this readme
You can allow axios-cache-adapter-fixed
to cache the results of a request using (almost) any HTTP method by modifying the exclude.methods
list.
1import { setup } from 'axios-cache-adapter-fixed 2 3const api = setup({ 4 baseURL: 'https://httpbin.org', 5 6 cache: { 7 exclude: { 8 // Only exclude PUT, PATCH and DELETE methods from cache 9 methods: ['put', 'patch', 'delete'] 10 } 11 } 12}) 13 14api.post('/post').then((response) => { 15 // POST request has been cached \o/ 16})
Note: the request method is not used in the cache store key by default, therefore with the above setup, making a GET
or POST
request will respond with the same cache.
You can give a localforage
instance to axios-cache-adapter-fixed
which will be used to store cache data instead of the default in memory store.
Note: This only works client-side because localforage
does not work in Node.js
1import localforage from 'localforage' 2import memoryDriver from 'localforage-memoryStorageDriver' 3import { setup } from 'axios-cache-adapter-fixed' 4 5// `async` wrapper to configure `localforage` and instantiate `axios` with `axios-cache-adapter-fixed` 6async function configure () { 7 // Register the custom `memoryDriver` to `localforage` 8 await localforage.defineDriver(memoryDriver) 9 10 // Create `localforage` instance 11 const forageStore = localforage.createInstance({ 12 // List of drivers used 13 driver: [ 14 localforage.INDEXEDDB, 15 localforage.LOCALSTORAGE, 16 memoryDriver._driver 17 ], 18 // Prefix all storage keys to prevent conflicts 19 name: 'my-cache' 20 }) 21 22 // Create `axios` instance with pre-configured `axios-cache-adapter-fixed` using a `localforage` store 23 return setup({ 24 // `axios` options 25 baseURL: 'http://some-rest.api', 26 27 // `axios-cache-adapter-fixed` options 28 cache: { 29 maxAge: 15 * 60 * 1000, 30 store: forageStore // Pass `localforage` store to `axios-cache-adapter-fixed` 31 } 32 }) 33} 34 35configure().then(async (api) => { 36 const response = await api.get('/url') 37 38 // Display something beautiful with `response.data` ;) 39})
You can give a RedisStore
instance to axios-cache-adapter-fixed
which will be used to store cache data instead of the default in memory store.
Note: This only works server-side
1const { setup, RedisStore } = require('axios-cache-adapter-fixed') 2const redis = require('redis') 3 4const client = redis.createClient({ 5 url: 'REDIS_URL', 6}) 7client.connect(); 8const store = new RedisStore(client) 9const api = setup({ 10 // `axios` options 11 baseURL: 'http://some-rest.api', 12 // `axios-cache-adapter-fixed` options 13 cache: { 14 maxAge: 15 * 60 * 1000, 15 store // Pass `RedisStore` store to `axios-cache-adapter-fixed` 16 } 17}) 18 19const response = await api.get('/url')
You can give a RedisDefaultStore
instance to axios-cache-adapter-fixed
which will be used to store cache data in Redis using the default commands instead of hash commands.
Note: This only works server-side
1const { setup, RedisDefaultStore } = require('axios-cache-adapter-fixed') 2const redis = require('redis') 3 4const client = redis.createClient({ 5 url: 'REDIS_URL', 6}) 7const store = new RedisDefaultStore(client, { 8 prefix: 'namespace_as_prefix' // optional 9}) 10const api = setup({ 11 // `axios` options 12 baseURL: 'http://some-rest.api', 13 // `axios-cache-adapter-fixed` options 14 cache: { 15 maxAge: 15 * 60 * 1000, 16 store // Pass `RedisDefaultStore` store to `axios-cache-adapter-fixed` 17 } 18}) 19 20const response = await api.get('/url')
When a response is served from cache a custom response.request
object is created with a fromCache
boolean.
1// Import dependencies 2import assert from 'assert' 3import { setup } from 'axios-cache-adapter-fixed' 4 5// Create `axios` instance with pre-configured `axios-cache-adapter-fixed` 6const api = setup({ 7 cache: { 8 maxAge: 15 * 60 * 1000 9 } 10}) 11 12// Wrap code in an `async` function 13async function exec () { 14 // First request will be served from network 15 const response = await api.get('http://some-rest.api/url') 16 17 // `response.request` will contain the origin `axios` request object 18 assert.ok(response.request.fromCache !== true) 19 20 // Second request to same endpoint will be served from cache 21 const anotherResponse = await api.get('http://some-rest.api/url') 22 23 // `response.request` will contain `fromCache` boolean 24 assert.ok(anotherResponse.request.fromCache === true) 25} 26 27// Execute our `async` wrapper 28exec()
You can tell axios-cache-adapter-fixed
to read stale cache data when a network error occurs using the readOnError
option.
readOnError
can either be a Boolean
telling cache adapter to attempt reading stale cache when any network error happens or a Function
which receives the error and request objects and then returns a Boolean
.
By default axios-cache-adapter-fixed
clears stale cache data automatically, this would conflict with activating the readOnError
option, so the clearOnStale
option should be set to false
.
1import { setup } from 'axios-cache-adapter-fixed' 2 3const api = setup({ 4 cache: { 5 // Attempt reading stale cache data when response status is either 4xx or 5xx 6 readOnError: (error, request) => { 7 return error.response.status >= 400 && error.response.status < 600 8 }, 9 // Deactivate `clearOnStale` option so that we can actually read stale cache data 10 clearOnStale: false 11 } 12}) 13 14// Make a first successful request which will store the response in cache 15api.get('https://httpbin.org/get').then(response => { 16 // Response will not come from cache 17 assert.ok(response.request.fromCache !== true) 18}) 19 20// Let's say that the stored data has become stale (default 15min max age has passed) 21// and we make the same request but it results in an internal server error (status=500) 22api.get('https://httpbin.org/get').then(response => { 23 // Response is served from cache 24 assert.ok(response.request.fromCache === true) 25 // We can check that it actually served stale cache data 26 assert.ok(response.request.stale === true) 27}).catch(err => { 28 // Will not execute this because stale cache data was returned 29 // If the attempt at reading stale cache fails, the network error will be thrown and this method executed 30})
Note: Passing a function to readOnError
is a smarter thing to do as you get to choose when a stale cache read should be attempted instead of doing it on all kind of errors
Using the default invalidation
method, a cache entry will be invalidated if a request is made using one of the methods listed in exclude.methods
.
1async function defaultInvalidate (config, request) { 2 const method = request.method.toLowerCase() 3 4 if (config.exclude.methods.includes(method)) { 5 await config.store.removeItem(config.uuid) 6 } 7}
You can customize how axios-cache-adapter-fixed
invalidates stored cache entries by providing a custom invalidate
function.
1import { setup } from 'axios-cache-adapter-fixed' 2 3// Create cached axios instance with custom invalidate method 4const api = setup({ 5 cache: { 6 // Invalidate only when a specific option is passed through config 7 invalidate: async (config, request) => { 8 if (request.clearCacheEntry) { 9 await config.store.removeItem(config.uuid) 10 } 11 } 12 } 13}) 14 15// Make a request that will get stored into cache 16api.get('https://httpbin.org/get').then(response => { 17 assert.ok(response.request.fromCache !== true) 18}) 19 20// Wait some time 21 22// Make another request to same end point but force cache invalidation 23api.get('https://httpbin.org/get', { clearCacheEntry: true }).then(response => { 24 // Response should not come from cache 25 assert.ok(response.request.fromCache !== true) 26})
maxAge
When you set the readHeaders
option to true
, the adapter will try to read cache-control
or expires
headers to automatically set the maxAge
option for the given request.
1import assert from 'assert' 2import { setup } from 'axios-cache-adapter-fixed' 3 4const api = setup({ 5 cache: { 6 // Tell adapter to attempt using response headers 7 readHeaders: true, 8 // For this example to work we disable query exclusion 9 exclude: { query: false } 10 } 11}) 12 13// Make a request which will respond with header `cache-control: max-age=60` 14api.get('https://httpbin.org/cache/60').then(response => { 15 // Cached `response` will expire one minute later 16}) 17 18// Make a request which responds with header `cache-control: no-cache` 19api.get('https://httpbin.org/response-headers?cache-control=no-cache').then(response => { 20 // Response will not come from cache 21 assert.ok(response.request.fromCache !== true) 22 23 // Check that query was excluded from cache 24 assert.ok(response.request.excludedFromCache === true) 25})
Note: For the cache-control
header, only the max-age
, no-cache
and no-store
values are interpreted.
Create a cache adapter instance. Takes an options
object to configure how the cached requests will be handled,
where they will be stored, etc.
1// Options passed to `setupCache()`. 2{ 3 // {Number} Maximum time for storing each request in milliseconds, 4 // defaults to 15 minutes when using `setup()`. 5 maxAge: 0, 6 // {Number} Maximum number of cached request (last in, first out queue system), 7 // defaults to `false` for no limit. *Cannot be overridden per request* 8 limit: false, 9 // {Object} An instance of localforage, defaults to a custom in memory store. 10 // *Cannot be overridden per request* 11 store: new MemoryStore(), 12 // {String|Function} Generate a unique cache key for the request. 13 // Will use request url and serialized params by default. 14 key: req => req.url + serializeQuery(req.params), 15 // {Function} Invalidate stored cache. By default will remove cache when 16 // making a request with method not `GET`, `POST`, `PUT`, `PATCH` or `DELETE` query. 17 invalidate: async (cfg, req) => { 18 const method = req.method.toLowerCase() 19 if (method !== 'get') { 20 await cfg.store.removeItem(cfg.uuid) 21 } 22 }, 23 // {Object} Define which kind of requests should be excluded from cache. 24 exclude: { 25 // {Array} List of regular expressions to match against request URLs. 26 paths: [], 27 // {Boolean} Exclude requests with query parameters. 28 query: true, 29 // {Function} Method which returns a `Boolean` to determine if request 30 // should be excluded from cache. 31 filter: null, 32 // {Array} HTTP methods which will be excluded from cache. 33 // Defaults to `['post', 'patch', 'put', 'delete']` 34 // Any methods listed will also trigger cache invalidation while using the default `config.invalidate` method. 35 // 36 // Note: the HEAD method is always excluded (hard coded). 37 // the OPTIONS method is ignored by this library as it is automatically handled by browsers/clients to resolve cross-site request permissions 38 methods: ['post', 'patch', 'put', 'delete'] 39 }, 40 // {Boolean} Clear cached item when it is stale. 41 clearOnStale: true, 42 // {Boolean} Clear all cache when a cache write error occurs 43 // (prevents size quota problems in `localStorage`). 44 clearOnError: true, 45 // {Function|Boolean} Determine if stale cache should be read when a network error occurs. 46 readOnError: false, 47 // {Boolean} Determine if response headers should be read to set `maxAge` automatically. 48 // Will try to parse `cache-control` or `expires` headers. 49 readHeaders: false, 50 // {Boolean} Ignore cache, will force to interpret cache reads as a `cache-miss`. 51 // Useful to bypass cache for a given request. 52 ignoreCache: false, 53 // {Function|Boolean} Print out debug log to console. 54 debug: false 55}
setupCache()
returns an object containing the configured adapter
, the cache store
and the config
that is applied to this instance.
Create an axios
instance pre-configured with the cache adapter. Takes an options
object to configure the cache and
axios at the same time.
1{ 2 cache: { 3 // Options passed to the `setupCache()` method 4 } 5 6 // Options passed to `axios.create()` method 7}
All the other parameters will be passed directly to the axios.create
method.
setup()
returns an instance of axios
pre-configured with the cache adapter.
The cache store
is conveniently attached to the axios
instance as instance.cache
for easy access.
RedisStore allow you to cache requests on server using redis.
Create a RedisStore
instance. Takes client
(RedisClient
) and optional hashKey
(name of hashSet to be used in redis).
1 // Using redis client https://github.com/NodeRedis/node_redis 2 // We have tested it with node_redis v.2.8.0 but it's supposed to work smoothly with the comming releases. 3 const redis = require("redis") 4 const client = redis.createClient()
new RedisStore()
returns an instance of RedisStore
to be passed to setupCache() as store
in config object.
Using the same object definition as the setup
method you can override cache options for individual requests.
1api.get('https://httpbin.org/get', { 2 cache: { 3 // Options override 4 } 5})
All options except limit
and store
can be overridden per request.
Also the following keys are used internally and therefore should not be set in the options: adapter
, uuid
, acceptStale
.
1npm run build
Webpack is used to build umd versions of the library that are placed in the dist
folder.
cache.js
cache.min.js
cache.node.js
cache.node.min.js
A different version of axios-cache-adapter-fixed
is generated for node and the browser due to how Webpack 4 uses a target
to change how the UMD wrapper is generated using global
or window
. If you are using the library in node or in your front-end code while using a module bundler (Webpack, rollup, etc) the correct version will be picked up automatically thanks to the "main"
and "browser"
fields in the package.json
.
axios-cache-adapter-fixed
is developped in ES6+ and uses async/await syntax. It is transpiled to ES5 using babel
with preset-env
.
Tests are executed using karma.
To launch a single run tests using ChromeHeadless:
1npm test
To launch tests in watch mode in Chrome for easier debugging with devtools:
1npm run watch
axios-cache-adapter-fixed
was designed to run in the browser. It does work in nodejs using the in memory store. But storing data in memory is not the greatests idea ever.
You can give a store
to override the in memory store but it has to comply with the localForage
API and localForage
does not work in nodejs for very good reasons that are better explained in this issue.
The better choice if you want to use axios-cache-adapter-fixed
server-side is to use a redis server with a RedisStore
instance as explained above in the API section.
MIT © Carl Ogren
No vulnerabilities found.
No security vulnerabilities found.