next app router ---- cache 替代方案

106 阅读1分钟

初始化项目(Node.js 18.18 or later)

nextjs.org/docs/app/ap…

npx create-next-app@latest [project-name] [options]

官方cache 替代方案:

nextjs.org/docs/app/bu…

export default async function Page() {
  // This request should be cached until manually invalidated.
  // Similar to `getStaticProps`.
  // `force-cache` is the default and can be omitted.
  const staticData = await fetch(`https://...`, { cache: 'force-cache' })
  // This request should be refetched on every request.
  // Similar to `getServerSideProps`.
  const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
  // This request should be cached with a lifetime of 10 seconds.
  // Similar to `getStaticProps` with the `revalidate` option.
  const revalidatedData = await fetch(`https://...`, {
    next: { revalidate: 10 },
  })
  return <div>...</div>
}
  • fetch api 默认缓存方式 { cache: 'force-cache' }

  • 使用 { cache: 'force-cache' } 替代getStaticProps (build之后数据就定了,生成了包含指定数据的页面)

  • 使用 { cache: 'no-store' } 替代getServerSideProps (每次请求都会重新获取新的数据)

  • 使用 { next: { revalidate: 10 } } 搭配 { cache: 'force-cache' } (实现在一定时间进行缓存刷新)

import { getCacheList } from '@/service'
export default async () => {
    const data = await getCacheList({}, {
        // cache: 'force-cache' // fetch api 默认的缓存行为 构建时运行一次 (getStaticProps)
        // cache: 'no-store' // 不缓存 每次都会执行 (getServerSideProps)
        next: { revalidate: 20 }, // api缓存 20s 刷新一次
    })
    console.log('getCacheList', data);
    return <div>
        {
            data.map(item => <div key={item.id}>{item.title}</div>)
        }
    </div>
}

getStaticPaths 替代方案:generateStaticParams

  • build 时页面就定了 如果新增了路径需要重新build 部署

  • 使用以下代码解决这个问题(重定向到404)

try {

      data = await getData(params.id)

  } catch (error) {

      redirect('/not-found');

  }

import { getCacheDetail, getCacheList } from '@/service'
import { redirect } from 'next/navigation';
export async function generateMetadata(context) {
    const params = await context.params
    const id = params.id
    return {
        title: '我是一个详情页面' + id,
        description: '我是一个详情页面',
    };
}  

export async function generateStaticParams() {
    const data = await getCacheList({}, {
        cache: 'no-store'
    })
    return data.map((item) => ({
        id: String(item.id),
    }))
}

async function getData(id) {
    const res = await getCacheDetail({
        id,
    }, {
        cache: 'no-store'
    })
    return res
}

export default async (context) => {
    const params = await context.params
    let data;
    try {
        data = await getData(params.id)
    } catch (error) {
        redirect('/not-found');
    }
    return <div className='bg-red-500 text-[50px] text-[#fff] flex align-center justify-center'>
        <div className='text-[blue]'>cache-detail: </div>
        <div dangerouslySetInnerHTML={{ __html: data && data.title }}></div>
    </div>
}

demo地址 feng/next15-app