mirror of
https://github.com/arthurfiorette/axios-cache-interceptor.git
synced 2025-12-08 17:36:16 +00:00
docs: improved documentation
This commit is contained in:
parent
e97a51585a
commit
6bcd7dca08
@ -7,17 +7,21 @@
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
rk-embed {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1.not-found {
|
||||
display: inline-block;
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.3);
|
||||
padding-right: 1rem;
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 6rem;
|
||||
margin-top: 2.5rem !important;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1.not-found__text {
|
||||
display: inline-block;
|
||||
padding-right: 1rem;
|
||||
@ -34,10 +38,15 @@
|
||||
// Write some code in the meantime :)
|
||||
|
||||
const Axios = require('axios');
|
||||
const { setupCache, buildWebStorage } = require('axios-cache-interceptor');
|
||||
const { setupCache } = require('axios-cache-interceptor');
|
||||
|
||||
const axios = Axios.create({});
|
||||
setupCache(axios, {});
|
||||
const axios = Axios.create({
|
||||
//
|
||||
});
|
||||
|
||||
setupCache(axios, {
|
||||
//
|
||||
});
|
||||
|
||||
await axios.get('https://jsonplaceholder.typicode.com/posts/1');
|
||||
```
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
- Getting Started
|
||||
|
||||
- [Homepage](/ 'Homepage')
|
||||
- [Introduction](/ 'Introduction')
|
||||
- [Installing](pages/installing.md 'Installing')
|
||||
- [Configuration](pages/configuration.md 'Configuration')
|
||||
- [Storages](pages/storages.md 'Custom storages')
|
||||
- [Request Id](pages/request-id.md 'Request Id')
|
||||
- [Invalidating Cache](pages/invalidating-cache.md 'Invalidating Cache')
|
||||
- [Development mode](pages/development-mode.md 'Development mode')
|
||||
|
||||
- API Reference
|
||||
|
||||
@ -82,11 +82,14 @@
|
||||
<title>Axios Cache Interceptor</title>
|
||||
|
||||
<!-- Docsify styles -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/prism-themes@1/themes/prism-one-light.min.css"
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/prism-themes@1/themes/prism-one-light.min.css"
|
||||
/>
|
||||
|
||||
<link rel="stylesheet" href="css/index.css" />
|
||||
@ -117,6 +120,5 @@
|
||||
crossorigin
|
||||
src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-jsx.min.js"
|
||||
></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -3,7 +3,7 @@ window.$docsify = {
|
||||
|
||||
loadSidebar: 'config/sidebar.md',
|
||||
notFoundPage: 'config/404.md',
|
||||
homepage: 'pages/homepage.md',
|
||||
homepage: 'pages/introduction.md',
|
||||
|
||||
subMaxLevel: 2,
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
>
|
||||
> Please, don't hesitate to open an PR with your own examples and use cases.
|
||||
|
||||
## Nodejs server example
|
||||
## Nodejs Server
|
||||
|
||||
An **NodeJS** with **ExpressJS** example to return data from another api.
|
||||
|
||||
@ -60,32 +60,54 @@ app.get('/cache/:id/get', async (req, res) => {
|
||||
app.listen(3000);
|
||||
```
|
||||
|
||||
## Jsx component example
|
||||
## React Component
|
||||
|
||||
You shouldn't
|
||||
[store cache in state libraries](https://betterprogramming.pub/why-you-should-be-separating-your-server-cache-from-your-ui-state-1585a9ae8336),
|
||||
it even is a bad practice. And even if you do so, you probably will have to write a lot of
|
||||
code to handle cache invalidation, strategies and etc.
|
||||
> You shouldn't
|
||||
> [store cache in state libraries](https://betterprogramming.pub/why-you-should-be-separating-your-server-cache-from-your-ui-state-1585a9ae8336),
|
||||
> it even is a bad practice. And even if you do so, you are going to write a lot of error
|
||||
> prone code to handle cache invalidation, caching strategies and so on.
|
||||
|
||||
With this library, you can just call any axios method without worrying about requesting
|
||||
thousands of times for every component draw. Simple as that!
|
||||
I'm also the maintainer of
|
||||
[`Axios Cache Hooks`](https://tinylibs.js.org/packages/axios-cache-hooks/), a
|
||||
[**950B**](https://bundlephobia.com/package/axios-cache-hooks) library that just provide
|
||||
you a simple and complete react hook to use with your axios cached instance.
|
||||
|
||||
It is a super powerful hook, because it will share the same updatable piece of data for
|
||||
every request with the same [id](pages/request-id.md). By using a
|
||||
[web storage](pages/storages.md?id=Web-storage) with it, you are up to **share component
|
||||
level data in a micro frontend scale**.
|
||||
|
||||
```ts
|
||||
import Axios from 'axios';
|
||||
import { createAxiosHooks } from 'axios-cache-hooks';
|
||||
import { setupCache } from 'axios-cache-interceptor';
|
||||
|
||||
const axios = setupCache(Axios);
|
||||
const { useQuery, useMutation } = createAxiosHooks();
|
||||
|
||||
```jsx
|
||||
function Component() {
|
||||
// React component state (but can be from any other framework, library and etc)
|
||||
const [data, setData] = useState(null);
|
||||
const [user, { loading, error }] = useQuery<User>(() => axios.get('/users/123'));
|
||||
|
||||
// Calling this function every component redraw does not have any
|
||||
// problems, as the response is cached in the first request. This
|
||||
// even work with concurrent requests and for many components at
|
||||
// the same time
|
||||
axios.get('https://api.example.com').then((response) => {
|
||||
setData(response.data);
|
||||
});
|
||||
if (loading)
|
||||
return (
|
||||
<div class=":)">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<div class=":(">
|
||||
<p>Error!</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div class=":)">
|
||||
<div>{data}</div>
|
||||
<div>{user.name}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -10,3 +10,11 @@ Axios Cache Interceptor can be understood as an intermediary that will analyze e
|
||||
request made, check if no similar request has been made before, if so, return it, if not,
|
||||
wait for the response, warn other requests if they are waiting and return the response to
|
||||
the original caller.
|
||||
|
||||
## Where to start
|
||||
|
||||
- [Installing](pages/installing.md)
|
||||
- [Configuration](pages/configuration.md)
|
||||
- [Per request configuration](pages/per-request-configuration)
|
||||
- [A NodeJS Server example](pages/examples?id=nodejs-server)
|
||||
- [A React Component example](pages/examples?id=react-server)
|
||||
132
docs/pages/invalidating-cache.md
Normal file
132
docs/pages/invalidating-cache.md
Normal file
@ -0,0 +1,132 @@
|
||||
# Invalidating Cache
|
||||
|
||||
A common problem when using a cache-first approach in your client is that there will be
|
||||
times when your server has newer data, your user knows that it has, but their client
|
||||
doesn't.
|
||||
|
||||
Here's a simple step to step example of it.
|
||||
|
||||
1. User list all available posts, server return an empty array.
|
||||
2. User proceeds to create a new post, server returns 200 OK.
|
||||
3. Your frontend navigates to the post list page.
|
||||
4. The post list page still shows 0 posts because it has a fresh cache for that request.
|
||||
5. User gets angry that the post list page is empty, they click the refresh button.
|
||||
6. The in-memory cache is vanished and the post list page now shows the created post.
|
||||
|
||||
## How to fix it
|
||||
|
||||
> You should be familiar with the [Request ID](pages/request-id.md) concept.
|
||||
|
||||
There is a [`cache.update`](pages/per-request-configuration.md?id=cacheupdate) option
|
||||
available for every request that you make. You can resolve this problem in two "major"
|
||||
ways:
|
||||
|
||||
**In these examples, we'll wrap the `list-posts` and `create-post` calls inside known
|
||||
functions, thus, centralizing the api logic into a single function.**
|
||||
|
||||
### Updating the local cache
|
||||
|
||||
When you are calling a `create-post` endpoint, it's almost sure that, if the request
|
||||
succeed, your `list-posts` cache will get out of date.
|
||||
|
||||
You can update your `list-posts` cache by using the `cache.update` option in yours
|
||||
`create-post` requests.
|
||||
|
||||
By default, you only need to know the id of the `list-posts` request. There's many ways to
|
||||
get that information, either by saving the `response.id` in a object or manually defining
|
||||
the `config.id` in each request.
|
||||
|
||||
> This method only works when you are manually making a known request out of date by
|
||||
> calling another endpoint of your API. Similarly with a `list-posts` and a `create-post`
|
||||
> request.
|
||||
|
||||
```js
|
||||
function listPosts() {
|
||||
return axios.get('/posts', {
|
||||
id: 'list-posts'
|
||||
});
|
||||
}
|
||||
|
||||
function createPost(data) {
|
||||
return axios.post('/posts', data, {
|
||||
cache: {
|
||||
update: {
|
||||
// Will perform a cache update for the `list-posts` internal cache
|
||||
'list-posts': (cachedState, createPostResponse) => {
|
||||
// If the cache is not cached, we don't need to update it
|
||||
if (cachedState.state !== 'cached') {
|
||||
return 'ignore';
|
||||
}
|
||||
|
||||
// Imagine the server response for the `list-posts` request is: { posts: Post[]; }
|
||||
// And the `create-post` response comes with the newly created post.
|
||||
|
||||
// Add the current created post to the end of the post's list
|
||||
cachedState.data.posts.push(createPostResponse.data);
|
||||
|
||||
// Return the same cache state, but a updated one.
|
||||
return cachedState;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
If you want to update the cache for a specific request outside of the request config, you
|
||||
can use the storage api.
|
||||
|
||||
```ts
|
||||
if (someLogicThatShowsIfTheCacheShouldBeUpdated) {
|
||||
const cache = await axios.storage.get('list-posts');
|
||||
|
||||
// Edits the current cache
|
||||
cache.data = '...';
|
||||
|
||||
await axios.storage.set('list-posts', cache);
|
||||
}
|
||||
```
|
||||
|
||||
Then, every time you create a post, your listPosts function will - without contacting the
|
||||
server - return the updated list of posts.
|
||||
|
||||
### Invalidating the local cache
|
||||
|
||||
This method works by completely erasing the local cache and forcing the client, (whenever
|
||||
needed) request again to your endpoint.
|
||||
|
||||
There's about 3 situations that makes this method better than the previous one:
|
||||
|
||||
- When you cannot predict the entire data needed.
|
||||
- When you know that there is newer data available made by another user or service.
|
||||
- When the data is too bigger or complex to you handle it in your client without the need
|
||||
of duplicating hundreds of service classes.
|
||||
|
||||
```js
|
||||
function listPosts() {
|
||||
return axios.get('/posts', {
|
||||
id: 'list-posts
|
||||
});
|
||||
}
|
||||
|
||||
function createPost(data) {
|
||||
return axios.post('/posts', data, {
|
||||
cache: {
|
||||
update: {
|
||||
// Will erase the list-posts cache and force the client (when needed) request to the server again
|
||||
'list-posts': 'delete'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
If you want to invalidate the cache for a specific request outside of the request config,
|
||||
you can use the storage api.
|
||||
|
||||
```ts
|
||||
if (someLogicThatShowsIfTheCacheShouldBeInvalidated) {
|
||||
// Deletes the current cache
|
||||
await axios.storage.remove('list-posts');
|
||||
}
|
||||
```
|
||||
@ -1,14 +1,18 @@
|
||||
# Request id
|
||||
|
||||
A good thing to know is that every request passed through this interceptor, has an id.
|
||||
**This does not mean that is a unique id**. The id is used in a number of ways, but the
|
||||
most important is to bind a request to its cache.
|
||||
Every request passed through this interceptor, has an id. **This doesn't mean its a UNIQUE
|
||||
ID**.
|
||||
|
||||
Each request id are responsible for binding a request to its cache, for referencing (or
|
||||
invalidating) it later and to make the interceptor treat each request with the same id as
|
||||
the same request.
|
||||
|
||||
The id generation is good enough to generate the same id for theoretically sames requests.
|
||||
A simple example is a request with `{ baseURL: 'https://a.com/', url: '/b' }` results to
|
||||
the same id with `{ url: 'https://a.com/b/' }`.
|
||||
|
||||
Also, a custom id can be used to treat two requests as the same.
|
||||
> If you send two completely different requests with the same id, the interceptor will
|
||||
> treat them as the same request, sharing its cache and every other as.
|
||||
|
||||
```js #runkit
|
||||
const axios = require('axios');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user