# Stale While Revalidate (SWR)
SWR (Stale-While-Revalidate) is a data-fetching strategy used in web programming that optimizes user experience by serving stale (cached) data instantly while updating it in the background. This approach is popular in frameworks like Next.js to handle data fetching for React components, helping to achieve faster and more responsive applications.
# SWR in Web Programming
In a general web context, SWR is a caching and revalidation strategy where:
- Stale data (cached) is served immediately upon request, reducing load times and providing instant feedback to the user.
- While revalidating, a background fetch is triggered to update the cached data if it's outdated or missing. Once updated, the cache refreshes, and the latest data is available for future requests.
Key Points
The SWR pattern is common in situations where data does not change frequently or where the initial data doesn't need to be real-time accurate, such as dashboards, profiles, and product listings.
# SWR in Next.js with the swr
Library
In Next.js, SWR (opens new window) is implemented via the swr
library (opens new window), developed by Vercel (the creators of Next.js). The swr
library provides an easy way to manage data fetching with React hooks, using the SWR caching strategy under the hood. Here’s how it works in Next.js:
# Installation
npm install swr
# Usage Example
The useSWR
hook is used to fetch data, handle caching, and revalidation. Here’s an example:
import useSWR from 'swr';
// Define a fetcher function to handle data fetching
const fetcher = (url) => fetch(url).then((res) => res.json());
function UserProfile() {
// Pass the API endpoint and fetcher function to useSWR
const { data, error } = useSWR('/api/user', fetcher);
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return <div>Hello, {data.name}</div>;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
In this example:
useSWR
takes the URL and afetcher
function to handle the request.- It returns the
data
,error
, andloading
states for easy handling. - SWR pattern ensures that the data is served instantly from the cache while re-fetching in the background to keep it fresh.
# Benefits of SWR in Next.js
- Automatic Caching: Caches the result of each request and uses it for subsequent renders.
- Real-time Updates: Background revalidation keeps data up-to-date without blocking UI.
- Error Handling and Loading States: Handles error and loading states by default, simplifying code.
# When to Use SWR in Next.js
SWR is best used in client-side data fetching scenarios, such as:
- When displaying user profiles, comments, or posts where data changes infrequently.
- For cases where instant feedback is beneficial, even if the data isn't perfectly current.
For Next.js, SWR is a valuable tool for building responsive, fast, and user-friendly applications by optimizing how data is fetched and updated in real-time.
# SWR in Nextra
Here is a simple example of how to use SWR in a Nextra project:
First, in a file components/dcat.jsx
in our Nextra project we write this component:
import useSWR from 'swr'
import Image from 'next/image'
const catURL= "https://api.thecatapi.com/v1/images/search?size=full"
const key = catURL;
const fetcher = () => fetch(catURL).then((res) => res.json())
const options = { revalidateOnFocus: false }
export default function DCat() {
const { data, isLoading, error } = useSWR(key, fetcher, options);
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error}</div>
return <Image src={data[0].url} width={data[0].width} height={data[0].height}/>
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
The API of useSWR
is:
const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options)
The key
param in useSWR(key, fetcher, options)
it actually is a key.
It is a unique string that represents the data that is being fetched. If the key changes, the data will be refetched.
The fetcher
function is a function that fetches the data.
It should return a promise that resolves to the data, that is why we use
fetch(catURL).then((res) => res.json())
.
The options
object is an optional object (opens new window) that can be used to configure the behavior of the SWR hook.
Here we set revalidateOnFocus
to false
to avoid revalidating the data when the window regains focus.
The return Values are:
data
: data for the given key resolved by fetcher (orundefined
if not loaded)error
: error thrown by fetcher (orundefined
)isLoading
: if there's an ongoing request and no "loaded data". Fallback data and previous data are not considered "loaded data"isValidating
: if there's a request or revalidation loadingmutate(data?, options?)
: function to mutate the cached data (details (opens new window))
More information can be found here (opens new window).
Once we have defined the DCat
component, we can use it in a Nextra MDX file:
## SWR
import DCat from '@/components/dcat'
<DCat />
2
3
4
5
6
# External Images and Next.js
Protecting External Images
To protect your application from malicious users, Next requires additional configuration in order to use external images. This ensures that only external images from your account can be served from the Next.js Image Optimization API. These external images can be configured with the remotePatterns (opens new window) property in your next.config.js
file, as shown below:
File next.config.js
:
import nextra from 'nextra'
const withNextra = nextra({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.jsx',
latex: true,
search: true
})
let nextConfig = withNextra()
nextConfig.images = {
remotePatterns: [ // See https://nextjs.org/docs/pages/api-reference/components/image#remotepatterns
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com',
//port: '80',
pathname: '/u/**',
},
{
protocol: 'https',
hostname: 'cdn2.thecatapi.com',
//port: '80',
pathname: '/images/**',
},
],
domains: ['avatars.githubusercontent.com'],
};
export default nextConfig
// If you have other Next.js configurations, you can pass them as the parameter:
// export default withNextra({ /* other next.js config */ })
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Good to know
The example above will ensure the src
property of next/image
must start with
https://cdn2.thecatapi.com/images/
. Any other protocol, hostname, port, or unmatched path will respond with
400 Bad Request.