{"id":17974,"library":"swrev","title":"SWRev","description":"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.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","typescript"],"install":[{"cmd":"npm install swrev","lang":"bash","label":"npm"},{"cmd":"yarn add swrev","lang":"bash","label":"yarn"},{"cmd":"pnpm add swrev","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"SWRev is primarily designed for modern JavaScript environments and ES Modules. While CommonJS `require` might technically work via transpilation, native ESM imports are the idiomatic way to consume it.","wrong":"const createSwr = require('swrev');","symbol":"createSwr","correct":"import { createSwr } from 'swrev';"},{"note":"Configuration utilities are typically named exports, not default. Ensure named import for `SWRConfig`.","wrong":"import SWRConfig from 'swrev';","symbol":"SWRConfig","correct":"import { SWRConfig } from 'swrev';"},{"note":"The `mutate` function is used for programmatic cache invalidation and updates. It is a named export.","symbol":"mutate","correct":"import { mutate } from 'swrev';"}],"quickstart":{"code":"import { createSwr, SWRConfig, mutate } from 'swrev';\n\ninterface UserData {\n  id: number;\n  name: string;\n  email: string;\n}\n\n// A generic fetcher function\nconst fetcher = async (url: string): Promise<UserData> => {\n  const response = await fetch(url);\n  if (!response.ok) {\n    throw new Error('Failed to fetch data');\n  }\n  return response.json();\n};\n\n// Create an SWR instance with a default config\nconst { useSwr } = createSwr({\n  fetcher: fetcher,\n  revalidateOnFocus: true,\n  revalidateIfStale: true,\n  // Custom cache implementation (optional)\n  // cache: new Map()\n});\n\nasync function simulateDataFetching() {\n  const userId = 1;\n  const userUrl = `https://jsonplaceholder.typicode.com/users/${userId}`;\n\n  console.log('Fetching user data with SWR...');\n\n  // First call: data will be fetched and cached\n  const { data: initialData, error: initialError, isValidating: initialValidating } = await useSwr<UserData>(userUrl);\n  if (initialError) {\n    console.error('Initial fetch error:', initialError);\n  } else {\n    console.log('Initial data:', initialData?.name);\n  }\n\n  // Simulate a subsequent read (should return stale data immediately if cached, then revalidate)\n  console.log('Fetching again (should be fast if cached)...');\n  const { data: subsequentData, isValidating: subsequentValidating } = await useSwr<UserData>(userUrl);\n  console.log('Subsequent data (stale or fresh):', subsequentData?.name);\n  if (subsequentValidating) {\n    console.log('Revalidating in background...');\n    // In a real app, you'd have a way to observe changes (e.g., framework hooks)\n    // For this example, we'll just wait a bit.\n    await new Promise(resolve => setTimeout(resolve, 1000));\n    const { data: freshData } = await useSwr<UserData>(userUrl);\n    console.log('Data after revalidation:', freshData?.name);\n  }\n\n  // Manually mutate the cache for a different key\n  const postId = 10;\n  const postUrl = `https://jsonplaceholder.typicode.com/posts/${postId}`;\n  console.log('Mutating cache for a post...');\n  await mutate(postUrl, { id: postId, title: 'Mutated Title', body: 'Mutated Body', userId: 1 });\n  const { data: mutatedPost } = await createSwr().useSwr(postUrl);\n  console.log('Mutated post data:', (mutatedPost as any)?.title);\n\n  console.log('\\nDemonstrating global configuration:');\n  // You can also use a global SWRConfig for all instances\n  SWRConfig.setDefault({\n    fetcher: async (key: string) => {\n      console.log(`Global fetcher for: ${key}`);\n      const res = await fetch(key);\n      return res.json();\n    }\n  });\n\n  const anotherUserUrl = `https://jsonplaceholder.typicode.com/users/2`;\n  const { data: user2 } = await createSwr().useSwr<UserData>(anotherUserUrl);\n  console.log('User 2 fetched with global config:', user2?.name);\n}\n\nsimulateDataFetching();","lang":"typescript","description":"This quickstart demonstrates how to initialize SWRev, perform data fetching using the SWR pattern, and manually mutate the cache. It showcases both direct SWR instance creation and global configuration."},"warnings":[{"fix":"Manually integrate the `useSwr` function within your framework's component lifecycle methods or reactive primitives to trigger UI updates when data or `isValidating` status changes.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"No direct fix available. Evaluate your project's needs for cutting-edge features or active support. If continuous maintenance and latest feature adoption are critical, consider alternative actively maintained SWR libraries or prepare to fork/contribute.","message":"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.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Ensure your `fetcher` function consistently returns a Promise that resolves to the expected data type or explicitly throws an error for failed requests. Implement robust error handling within the fetcher.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"The `useSwr` function is created by calling `createSwr()`. Correct usage is `const { useSwr } = createSwr();` or `const { useSwr } = createSwr({ /* config */ });`.","cause":"Attempting to import `useSwr` directly as a named export from 'swrev' instead of destructuring it from the object returned by `createSwr()`.","error":"TypeError: (0 , swrev__WEBPACK_IMPORTED_MODULE_0__.useSwr) is not a function"},{"fix":"Provide a generic type argument to `useSwr` to inform TypeScript about the expected data structure, e.g., `const { data } = useSwr<UserData>(key, fetcher);`.","cause":"TypeScript error when accessing properties on `data` without proper type assertion or generic type parameter in `useSwr`.","error":"Property 'name' does not exist on type 'unknown'."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}