前言

大家好,我是曦远。

本来是想发昨晚写好的 starblog 管理后台重构文章的

结果打开 blog 才发现忘记提交了😂

所以写一篇新的吧

正好最近正在大量使用 Next.js

我发现部署后的首次渲染很慢,才意识到「预热」这个问题

当然这是后话了

这个框架里有大量的官方约定

这些在官方文档里都有的,就是比较分散,本文主要是概括一下这些约定

Next.js框架更新得很快,不一样的地方以官方文档为主。

缓存和渲染相关

// 控制页面重新验证的时间间隔(秒)
export const revalidate = 60; // 60秒后重新验证
export const revalidate = 0;  // 禁用缓存
export const revalidate = false; // 永久缓存

// 控制页面的渲染模式
export const dynamic = 'auto';          // 默认,自动选择
export const dynamic = 'force-dynamic'; // 强制动态渲染
export const dynamic = 'force-static';  // 强制静态渲染
export const dynamic = 'error';         // 如果使用动态函数则报错

// 控制动态段的行为
export const dynamicParams = true;  // 允许动态参数(默认)
export const dynamicParams = false; // 不允许动态参数

运行时配置

// 指定运行时环境
export const runtime = 'nodejs';    // Node.js 运行时(默认)
export const runtime = 'edge';      // Edge 运行时

// 设置最大执行时间(秒)
export const maxDuration = 30; // 最多执行30秒

获取数据相关

// 控制 fetch 请求的缓存行为
export const fetchCache = 'auto';           // 默认缓存行为
export const fetchCache = 'default-cache';  // 默认缓存
export const fetchCache = 'only-cache';     // 只使用缓存
export const fetchCache = 'force-cache';    // 强制缓存
export const fetchCache = 'default-no-store'; // 默认不缓存
export const fetchCache = 'only-no-store';  // 只允许不缓存
export const fetchCache = 'force-no-store'; // 强制不缓存

元数据和SEO

元数据

动态生成元数据

import type { Metadata } from 'next'

export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
  // 根据动态参数获取数据
  const post = await getPost(params.slug)
  
  return {
    title: post.title,
    description: post.description,
    openGraph: {
      title: post.title,
      description: post.description,
      images: [post.image],
    },
  }
}

定义静态元数据

// 静态元数据
export const metadata: Metadata = {
  title: 'My Page',
  description: 'This is my page description',
  keywords: ['next.js', 'react', 'typescript'],
  openGraph: {
    title: 'My Page',
    description: 'This is my page description',
  },
}

使用场景

静态 Metadata 适用于:

  • 内容固定的页面(如关于我们、联系我们)
  • 不需要根据路由参数变化的页面
  • 简单的静态页面

动态 Metadata 适用于:

  • 博客文章详情页(根据文章 slug 获取标题、描述)
  • 产品详情页(根据产品 ID 获取信息)
  • 用户个人资料页(根据用户 ID 获取信息)
  • 任何需要根据路由参数或外部数据动态生成 metadata 的页面

静态参数

// 生成静态参数(用于动态路由)
export async function generateStaticParams() {
  return [
    { slug: 'post-1' },
    { slug: 'post-2' },
  ];
}

常用组合示例

完全静态页面

export const dynamic = 'force-static';
export const revalidate = false;

实时动态页面

export const dynamic = 'force-dynamic';
export const revalidate = 0;

定时更新页面

export const revalidate = 3600; // 每小时更新一次

Edge 运行时优化

export const runtime = 'edge';
export const dynamic = 'force-dynamic';

API 路由配置

// 在 API 路由中也可以使用
export const runtime = 'edge';
export const maxDuration = 10;

使用场景建议

配置 适用场景
revalidate = 0 实时数据展示,如股票价格、聊天应用
revalidate = 60 定期更新的内容,如新闻、博客
dynamic = 'force-static' 完全静态的页面,如关于我们
dynamic = 'force-dynamic' 个性化内容,如用户仪表板
runtime = 'edge' 需要低延迟的全球分发
fetchCache = 'force-no-store' 敏感数据,不允许缓存

注意事项

  1. 只能在页面或布局文件中使用 :这些配置只在 page.tsx 、 layout.tsx 或 route.ts 文件中有效
  2. 这些配置选项只能在 Server Component Pages、Layouts 或 Route Handlers 中使用
  3. 必须是具名导出 :必须使用 export const 语法
  4. 配置值必须是 静态可分析的 (例如 revalidate = 600 有效,但 revalidate = 60 * 10 无效)
  5. 类型安全 :TypeScript 会检查这些配置的类型
  6. 优先级 :子路由的配置会覆盖父路由的配置

这些配置选项让 Next.js 能够精确控制每个页面的渲染和缓存行为,是 App Router 架构的核心特性之一

官方文档

Route Segment Config(路由段配置)

相关文档页面

  1. Dynamic Routes(动态路由)

  2. Data Fetching and Caching(数据获取和缓存)

  3. Rendering(渲染)