Teachnique
      CourseRoadmaps
      Login

      Introduction

      Project SetupCLI

      IntroductionAPP RouterTemplateLoading UIError Handling404 Page

      Linking and Navigating

      Dynamic RoutesRoute groupsParallel RoutesIntercepting Routes

      Route handlersCacheCommon Questions

      Middleware

      CSRSSR & SSGISR

      React Server ComponentsServer-Side Rendering

      SuspenseStreaming

      Server & Client ComponentServer vs. Client ComponentBest Practices

      Server-Side Rendering Strategies

      Data Fetching & Caching & RedirectThird-Party Request Libraries on the Server SideBest Practices

      Request MemoizationData CacheFull Route CacheRouter Cache

      Server Actions IFormServer Actions IIOptimistic Update

      Tailwind CSSCSS-in-JSSass

      Environment VariablesAbsolute Imports& Module Path AliasesRoute Segment Config

      Image & LCPImage IImage IIOptimizing IOptimizing II

      Next FontFont ParameterApply Styles

      Feedback

      Submit request if you have any questions.

      Course
      Data Cache

      Next.js Mastery: From Fundamentals to Full-Stack

      Unlock the power of Next.js with this comprehensive course! Starting with the basics, you’ll learn essential skills such as routing, data fetching, and styling. Progress through practical projects, including building your own React Notes app, to gain hands-on experience. Dive into the source code to understand the inner workings and core principles of Next.js. Perfect for developers with a basic knowledge of React and Node.js, this course ensures you’ll be ready to create high-performance full-stack applications efficiently. Join us and master Next.js, backed by industry experts and a supportive learning community.

      Data Cache

      1. How It Works

      Next.js has its own data caching solution that can store data across server requests and build deployments. This is achieved by extending the fetch API, allowing each request to have its own caching strategy.
      Unlike React's request memoization, which only applies during component tree rendering and doesn't need to handle cache updates, Next.js's data caching is more persistent and requires cache invalidation strategies.
      By default, fetch requests in Next.js will be cached persistently and won't automatically reset. You can configure the caching behavior using fetch options cache and next.revalidate:
      fetch('https://...', { cache: 'force-cache' | 'no-store' })
      fetch('https://...', { next: { revalidate: 3600 } })
      This is the working principle of Next.js data caching:
      
      Let's explain: When the request is made for the first time during rendering, both request memoization and data caching will miss, triggering the request. The returned result is stored in both the request memoization and data cache.
      On subsequent calls, because the { cache: 'no-store' } parameter was added, the request memoization will miss due to different parameters. This parameter causes data cache skipping, resulting in another request. Since no-store is configured, the data cache won't cache the result, but request memoization will cache it as usual.

      2. Duration

      Data cache persists across incoming requests and deployments unless revalidated or opted out.

      3. Revalidation

      Next.js offers two ways to update the cache:
      • Time-based revalidation: Revalidate data after a certain period and when new requests are made. Suitable for data that doesn't change frequently and where freshness isn't critical.
      • On-demand revalidation: Manually revalidate data based on events. This can be done using path-based or tag-based methods, suitable for scenarios requiring the latest data as soon as possible.

      Time-based Revalidation

      To use time-based revalidation, set the revalidation time (in seconds) using the next.revalidate option in the fetch request:
      // Revalidate every hour
      fetch('https://...', { next: { revalidate: 3600 } })
      Or configure it via a route segment configuration to apply to all fetch requests in that segment:
      // layout.jsx / page.jsx / route.js
      export const revalidate = 3600
      Here's a diagram illustrating time-based revalidation:
      
      This shows that the request will not automatically update after 60 seconds. Instead, it will revalidate when a new request is made after 60 seconds. The first request after 60 seconds will still return the cached value, but Next.js will update the cache with new data. The second request after 60 seconds will use the new data.

      On-demand Revalidation

      For on-demand revalidation, data can be updated based on path (revalidatePath) or cache tags (revalidateTag).
      revalidatePath is used in route handlers or Server Actions to manually clear cache data for specific paths:
      javascriptCopy coderevalidatePath('/')
      
      revalidateTag relies on Next.js's cache tag system. Declare a tag when making a fetch request, then revalidate requests with a specific tag in route handlers or Server Actions:
      javascriptCopy code// Using tags
      fetch('https://...', { next: { tags: ['a', 'b', 'c'] } })
      // Revalidating requests with a specific tag
      revalidateTag('a')
      
      Here's a diagram illustrating on-demand revalidation:
      
      The first call to the request caches data as usual. When on-demand revalidation is triggered, the corresponding cache entries are removed from the cache. The next request will be treated as the first call, caching data again.

      4. Opting Out

      To opt out of data caching, you can use two methods:
      • Set the cache option of the fetch request to no-store, ensuring data is re-fetched each time:javascriptCopy codefetch('https://...', { cache: 'no-store' })
      • Use a route segment configuration to affect all data requests in that segment:javascriptCopy codeexport const dynamic = 'force-dynamic'

      Practical Experience

      Modify app/page.js with the following code:
      async function getData() {
      // The API returns a random cat image each time
      const res = await fetch('https://api.thecatapi.com/v1/images/search')
      return res.json()
      }
      
      export async function generateMetadata() {
      const data = await getData()
      return {
      title: data[0].id
      }
      }
      
      export default async function Page() {
      const data = await getData()
      return (
      <>
      <h1>Image ID: {data[0].id}</h1>
      <img src={data[0].url} width="300" />
      <CatDetail />
      </>
      )
      }
      
      async function CatDetail() {
      const data = await getData()
      return (
      <>
      <h1>Image ID: {data[0].id}</h1>
      <img src={data[0].url} width="300" />
      </>
      )
      }
      The logic is straightforward. When you visit /, the generateMetadata function, the page, and the child component will each call the API three times, returning a random cat image each time. In the production version, will the data returned by the three calls be consistent?
      Let's run it:
      
      Whether you refresh normally or hard refresh, the images remain the same, and the data returned by the three API calls is consistent.
      The reason is simple: the page is statically rendered during the build, and although the API is called three times, request memoization and data caching ensure the data returned is consistent.
      
      Now let's disable data caching by adding code to app/page.js:
      // Force fetch to not cache
      export const fetchCache = 'force-no-store'
      Run the production version again:
      
      

      Conclusion


      
      Let's compare request memoization and data caching:
      • Request Memoization: React's data caching solution, lasting during component tree rendering to avoid multiple requests for the same data during rendering, improving performance.
      • Data Cache: Next.js's data caching solution, persisting across deployments and requests. The cache doesn't expire unless revalidated or explicitly opted out, aiming to optimize application performance.
      In real-world development, request memoization and data caching often coexist and work together.
      

      References

      • Building Your Application: Caching | Next.js