You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13.4中如何为数据库调用添加revalidateTag标签?

解决Next.js 13.4数据库更新后页面缓存同步问题

针对你遇到的逐个调用revalidatePath过于繁琐、偶尔需要手动刷新的问题,用revalidateTag配合缓存标签是更高效的方案,以下是具体实现步骤:

1. 为数据库查询添加缓存标签

Next.js的unstable_cache函数可以为直接的数据库查询(非fetch请求)添加缓存标签,后续就能通过revalidateTag批量失效相关缓存:

示例:封装带缓存标签的数据库查询

import { unstable_cache } from 'next/cache';
import { kysely } from '@/db'; // 你的Kysely实例

// 任务列表查询:关联'tasks'标签
const getTasks = unstable_cache(
  async () => {
    return await kysely.selectFrom('task').selectAll().execute();
  },
  ['tasks-all'], // 唯一缓存键
  { tags: ['tasks'] } // 绑定的缓存标签
);

// 单个任务查询:关联'tasks'和'task-{id}'标签
const getTaskById = unstable_cache(
  async (taskId: number) => {
    return await kysely
      .selectFrom('task')
      .selectAll()
      .where('id', '=', taskId)
      .executeTakeFirst();
  },
  (taskId) => [`task-detail-${taskId}`], // 动态生成缓存键
  { tags: (taskId) => ['tasks', `task-${taskId}`] } // 绑定多个标签
);

// 在Server Component中使用这些查询函数
export default async function TasksPage() {
  const tasks = await getTasks();
  // 渲染任务列表...
}

2. 在更新操作中使用revalidateTag替换多个revalidatePath

修改你的Server Action,不用逐个验证路由,直接调用revalidateTag失效所有关联标签的缓存:

export default async function TaskEditPage({ params }: TaskPageProps) {
    async function editTask(formData: FormData) {
        "use server";

        // 数据验证逻辑...
        const data = {
          title: formData.get('title') as string,
          description: formData.get('description') as string,
          priority: formData.get('priority') as string,
          finished_at: formData.get('finished_at') ? new Date(formData.get('finished_at') as string) : null,
        };

        await kysely
            .updateTable("task")
            .set(data)
            .where("id", "=", Number(params.id))
            .execute();

        // 仅需两行,替代多个revalidatePath
        revalidateTag('tasks'); // 失效所有任务列表相关缓存
        revalidateTag(`task-${params.id}`); // 失效当前任务的详情/编辑页缓存

        // 注意:检查路径是否正确,原代码中是/ssr/task/${params.id},可能应为/ssr/tasks/${params.id}
        redirect(`/ssr/tasks/${params.id}`);
    }

    // 渲染编辑页面...
}

其他可选方案

  • 定时ISR刷新:如你提到的,在页面组件中添加export const revalidate = 60;,让页面每60秒自动重新验证,但这种方式不如revalidateTag精准,可能会有延迟。
  • 强制动态渲染:如果不需要缓存,可以在页面组件中添加export const dynamic = 'force-dynamic';,这样每次请求都会重新查询数据库,但会牺牲缓存带来的性能优势。

注意事项

  • unstable_cache虽然带有unstable前缀,但在Next.js 13.4+版本中已经被广泛使用,后续大概率会稳定为正式API。
  • 确保所有使用任务数据的Server Component都通过封装后的查询函数获取数据,这样缓存标签才能生效。

内容的提问来源于stack exchange,提问作者manasseh stam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:02:42