NextJS 提供了一种新的缓存方式 use chche 指令,可以用来缓存函数、组件以及整个路由

与 unstable_cache 的区别

  • unstable_cache 是实验性的不稳定缓存,它只能缓存 JSON 数据, use cache 可以缓存任何可序列化的数据
  • use cache 可以在多个级别进行缓存
    • 功能级别
    • 组件级别
    • 路由级别(整个文件)
  • 自动缓存: 当将 use cache 指令添加到文件顶部时,该文件内的所有内容都会被缓存

精细控制缓存行为

缓存标签

import { unstable_cacheTag as cacheTag } from "next/cache"
 
export async function fetchProducts() {
  "use cache"
  cacheTag("product-details")
 
  const response = await fetch("https://api.mockapi.io/products")
  return response.json()
}

上面的代码为函数 fetchProducts 设置缓存,并添加了缓存标签 product-details,这样可以进行选择性重新验证,可以在特定时间后 使特定缓存失效或重新验证

缓存寿命

import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from "next/cache"
 
export async function fetchProducts() {
  "use cache"
 
  cacheLife("hours")
  cacheTag("product-details")
 
  const response = await fetch("https://api.mockapi.io/products")
  return response.json()
}

上面的代码通过 cacheLife 设置缓存的有效期为 1小时, 1 小时后缓存自动失效

清理缓存

"use server"
import { revalidateTag } from "next/cache"
 
export async function purgeProductDetailsCache() {
  revalidateTag("product-details")
}

要清除或重新验证缓存数据,您可以使用服务器操作revalidateTag功能。

就像你可以使用 函数清除组件的缓存一样revalidateTag,当缓存被标记{ next: { tags: [‘a’, ‘b’, ‘c’] } }为参数时,可以使用 函数fetch清除路由的缓存。然后,你可以使用 函数清除路由的缓存revalidateTag。

在 的情况下use cache,您使用cacheTag函数来标记缓存,并且仍然使用该revalidateTag函数来清除缓存。

因此,revalidateTag这是一个可用于清除组件或路由缓存的函数。

缓存组件

import Image from "next/image"
import { Dog } from "@/types"
import DogCard from "@/components/dog-card"
 
// Simulate an API call with caching
export async function fetchDogs(): Promise<Dog[]> {
  const urls = [
    "https://http.dog/100.json",
    "https://http.dog/200.json",
    "https://http.dog/401.json",
  ]
  const responses = await Promise.all(urls.map((url) => fetch(url)))
  const data = await Promise.all(responses.map((response) => response.json()))
 
  console.log("Hi Fetching Dogs")
  return data
}
 
export default async function DogList() {
  "use cache"
  const dogs = await fetchDogs()
 
  return (
    <div className="max-w-2xl mx-auto p-6 bg-pink-200 shadow-md rounded-lg">
      <h1 className="text-3xl font-bold text-left mb-6">Dogs</h1>
      <ul className="grid grid-cols-3 gap-4">
        {dogs.map((dog: Dog) => (
          <DogCard key={dog.id} dog={dog} />
        ))}
      </ul>
    </div>
  )
}

只要一个组件的 props 是可以序列化的,那么这个组件就可以通过 use cache 指令进行缓存

路由级缓存

"use cache"
 
import DogList from "@/components/dog-list"
import ProductsList from "@/components/products-list"
import { Suspense } from "react"
 
export default async function Page() {
  return (
    <div className="p-12">
      <DogList />
      <Suspense fallback={<div>Loading...</div>}>
        <ProductsList />
      </Suspense>
    </div>
  )
}

page.ts 文件的顶部添加 use cache 指令,整个文件内的内容都将被缓存,包括文件中的组件以及组件的子组件

注意事项

  • use cache仍是一个实验性功能,因此请关注官方 Next.js 文档以获取更新。
  • 在路由级别进行缓存时,请注意客户端交互性和重新渲染需求。
  • 如果未指定,默认缓存持续时间为 15 分钟。
  • 缓存动态内容或经常变化的数据时要小心谨慎。
  • 通过利用use cache,您可以减少不必要的计算和网络请求,从而显著提高 Next.js 应用程序的性能。然而,精心实施缓存对于确保应用程序中数据的新鲜度和正确性至关重要。

参考资料