SWRev
raw JSON →SWRev is a lightweight, framework-agnostic library implementing the Stale-While-Revalidate (SWR) data fetching strategy. It allows applications to instantly display cached data (stale) while simultaneously revalidating that data with a fresh network request in the background, providing a fast and resilient user experience. Unlike framework-specific SWR implementations (e.g., Vercel's `swr` for React), SWRev focuses on core SWR logic, making it suitable for use with any JavaScript framework or even vanilla JavaScript projects. The current stable version is 4.0.0. The package has a slow release cadence, with its latest version published approximately three years ago, suggesting a mature and stable codebase that requires infrequent updates. It notably has zero runtime dependencies, which contributes to its lightweight nature.
Common errors
error TypeError: (0 , swrev__WEBPACK_IMPORTED_MODULE_0__.useSwr) is not a function ↓
useSwr function is created by calling createSwr(). Correct usage is const { useSwr } = createSwr(); or const { useSwr } = createSwr({ /* config */ });. error Property 'name' does not exist on type 'unknown'. ↓
useSwr to inform TypeScript about the expected data structure, e.g., const { data } = useSwr<UserData>(key, fetcher);. Warnings
gotcha SWRev is framework-agnostic, meaning it does not provide built-in hooks for specific UI libraries like React or Vue. Users must integrate its core logic (e.g., `useSwr` function provided by `createSwr`) into their framework's lifecycle (e.g., with `useEffect` in React or `onMounted` in Vue) to manage component re-renders based on data changes. ↓
breaking The package `swrev` has had no updates for approximately 3 years since version 4.0.0. While this might indicate stability, it also means it may not actively incorporate the latest JavaScript features, security patches, or performance optimizations, nor is it likely to address new community requests or bugs promptly. Consider this a factor in long-term project planning. ↓
gotcha Incorrect `fetcher` function implementation can lead to silent failures or unexpected caching behavior. The `fetcher` should always return a Promise that resolves with the data or rejects with an error. If it doesn't, SWR might not properly handle loading or error states. ↓
Install
npm install swrev yarn add swrev pnpm add swrev Imports
- createSwr wrong
const createSwr = require('swrev');correctimport { createSwr } from 'swrev'; - SWRConfig wrong
import SWRConfig from 'swrev';correctimport { SWRConfig } from 'swrev'; - mutate
import { mutate } from 'swrev';
Quickstart
import { createSwr, SWRConfig, mutate } from 'swrev';
interface UserData {
id: number;
name: string;
email: string;
}
// A generic fetcher function
const fetcher = async (url: string): Promise<UserData> => {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Failed to fetch data');
}
return response.json();
};
// Create an SWR instance with a default config
const { useSwr } = createSwr({
fetcher: fetcher,
revalidateOnFocus: true,
revalidateIfStale: true,
// Custom cache implementation (optional)
// cache: new Map()
});
async function simulateDataFetching() {
const userId = 1;
const userUrl = `https://jsonplaceholder.typicode.com/users/${userId}`;
console.log('Fetching user data with SWR...');
// First call: data will be fetched and cached
const { data: initialData, error: initialError, isValidating: initialValidating } = await useSwr<UserData>(userUrl);
if (initialError) {
console.error('Initial fetch error:', initialError);
} else {
console.log('Initial data:', initialData?.name);
}
// Simulate a subsequent read (should return stale data immediately if cached, then revalidate)
console.log('Fetching again (should be fast if cached)...');
const { data: subsequentData, isValidating: subsequentValidating } = await useSwr<UserData>(userUrl);
console.log('Subsequent data (stale or fresh):', subsequentData?.name);
if (subsequentValidating) {
console.log('Revalidating in background...');
// In a real app, you'd have a way to observe changes (e.g., framework hooks)
// For this example, we'll just wait a bit.
await new Promise(resolve => setTimeout(resolve, 1000));
const { data: freshData } = await useSwr<UserData>(userUrl);
console.log('Data after revalidation:', freshData?.name);
}
// Manually mutate the cache for a different key
const postId = 10;
const postUrl = `https://jsonplaceholder.typicode.com/posts/${postId}`;
console.log('Mutating cache for a post...');
await mutate(postUrl, { id: postId, title: 'Mutated Title', body: 'Mutated Body', userId: 1 });
const { data: mutatedPost } = await createSwr().useSwr(postUrl);
console.log('Mutated post data:', (mutatedPost as any)?.title);
console.log('\nDemonstrating global configuration:');
// You can also use a global SWRConfig for all instances
SWRConfig.setDefault({
fetcher: async (key: string) => {
console.log(`Global fetcher for: ${key}`);
const res = await fetch(key);
return res.json();
}
});
const anotherUserUrl = `https://jsonplaceholder.typicode.com/users/2`;
const { data: user2 } = await createSwr().useSwr<UserData>(anotherUserUrl);
console.log('User 2 fetched with global config:', user2?.name);
}
simulateDataFetching();