如何修复Next.js 15动态路由预渲染错误
问题背景
我有一个未使用use cache的动态路由页面,代码如下:
// /search/[query]/page.tsx import { Suspense } from "react"; import SearchQuery from "@/components/Search/Query"; import { Skeleton } from "@/components/ui/skeleton"; export default async function SearchPage({ params, }: { params: Promise<{ query: string }>; }) { const queries = params.then(param => param.query); return ( <Suspense fallback={<Skeleton className="h-[140px] w-full" />}> {/* @ts-expect-error Async Server Component */} <SearchQuery queries={queries} /> </Suspense> ); }
构建项目时触发预渲染错误:
Route "/search/[query]": A component accessed data, headers, params, searchParams, or a short-lived cache without a Suspense boundary nor a "use cache" above it. We don't have the exact line number added to error messages yet but you can see which component in the stack below.
即便添加use cache,甚至使用Next.js官方示例代码,仍会抛出相同错误:
export default async function Page({ params, }: { params: Promise<{ slug: string }> }) { const { slug } = await params return <h1>Blog Post: {slug}</h1> }
我的next.config.mjs配置:
import path from "path"; const __dirname = path.resolve(); /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { reactCompiler: true, dynamicIO: true, }, sassOptions: { includePaths: [path.join(__dirname, "components")], prependData: `@use "@/assets/mixins" as *;`, }, transpilePackages: ["@web3-name-sdk/core"], }; export default nextConfig;
使用的Next.js版本为^15.1.1-canary.7。
原因分析
该错误由开启experimental.dynamicIO实验特性导致。Next.js 15预览版中,dynamicIO会改变服务器组件处理动态参数(如params)的逻辑,强制要求所有访问动态数据的操作必须包裹在use cache或Suspense边界内,但当前canary版本存在兼容性bug,即便按要求操作仍会触发错误。
解决方案
方案一:临时关闭dynamicIO实验特性
在next.config.mjs中移除dynamicIO: true配置,这是最直接的修复方式:
// 修改后的nextConfig const nextConfig = { experimental: { reactCompiler: true, // 移除dynamicIO配置 }, sassOptions: { includePaths: [path.join(__dirname, "components")], prependData: `@use "@/assets/mixins" as *;`, }, transpilePackages: ["@web3-name-sdk/core"], };
方案二:规范使用use cache并调整参数传递逻辑
确保在页面组件顶部声明use cache,且在页面内先await拿到params的实际值,再传递给子组件:
// /search/[query]/page.tsx import { Suspense } from "react"; import SearchQuery from "@/components/Search/Query"; import { Skeleton } from "@/components/ui/skeleton"; // 在组件最顶部声明use cache use cache; export default async function SearchPage({ params, }: { params: Promise<{ query: string }>; }) { // 直接await获取实际参数值,避免传递Promise给子组件 const { query: queries } = await params; return ( <Suspense fallback={<Skeleton className="h-[140px] w-full" />}> <SearchQuery queries={queries} /> </Suspense> ); }
方案三:升级到最新Next.js 15预览版
由于使用的是canary版本,该bug可能已在后续更新中修复,执行以下命令升级:
npm install next@latest-canary # 或使用yarn/pnpm yarn add next@latest-canary pnpm add next@latest-canary
内容的提问来源于stack exchange,提问作者oynozan

