Next.js Pages Router静态内容判定?为何RecipeImg页面被标记为静态?
我正在开发一个T3应用,构建结构如下:
Route (pages) Size First Load JS ┌ ○ / 22.1 kB 160 kB ├ /_app 0 B 134 kB ├ ○ /404 182 B 134 kB ├ λ /api/auth/[...nextauth] 0 B 134 kB ├ λ /api/trpc/[trpc] 0 B 134 kB ├ ○ /RecipeImg 663 B 139 kB └ ○ /text 388 B 135 kB + First Load JS shared by all 143 kB ├ chunks/framework-d0154717f77ffdb3.js 66.8 kB ├ chunks/main-d06b34d932087d19.js 32.3 kB ├ chunks/pages/_app-d7d969eed6118a93.js 33.3 kB ├ chunks/webpack-bd27d4452b026a66.js 1.78 kB └ css/155085108fc313ab.css 9.34 kB ○ (Static) prerendered as static content λ (Dynamic) server-rendered on demand using Node.js
其中RecipeImg被标记为「预渲染为静态内容」,该页面代码如下:
import { type RouterOutputs } from "../utils/api"; import Image from "next/image"; import { api } from "~/utils/api"; import { useMainIngreds } from "../context/useMainIngreds"; export type Recipe = RouterOutputs["recipe"]["getIdeas"][0]; export default function RecipeImg() { const { mainIngreds } = useMainIngreds(); const recipes = api.recipe.getImg.useQuery(mainIngreds, { enabled: true }); if (!recipes.data?.[0]) return; const recipe = recipes.data[0]; if (!recipe) return; const imageUrl = `https://some-storage/${recipe.Image_Name}.jpg`; return ( <> <Image src={imageUrl} alt="" width={500} height={500} priority />; </> ); }
这个页面使用了基于Context API的自定义钩子useMainIngreds,mainIngreds的值由其他页面的用户操作决定,同时还需要向服务器请求以展示图片。我认为该页面至少有部分内容需要在请求时渲染,为何Next.js将其归类为「静态内容」?
Next.js标记页面为静态(○)的核心原因是这个页面在构建阶段没有触发任何需要服务器端动态渲染的条件,具体细节如下:
页面未配置动态渲染标识
你没有在RecipeImg页面中添加getServerSideProps、带动态参数的getStaticProps,也没有使用dynamic组件或export const dynamic = 'force-dynamic'这类强制动态渲染的配置。Next.js默认会将这类无特殊配置的页面视为静态页面,在构建阶段生成静态HTML文件。数据请求属于客户端行为
页面中通过tRPC useQuery发起的请求是在客户端浏览器中执行的,属于客户端侧数据获取。构建阶段Next.js只会生成一个基础的空框架HTML,数据加载、图片渲染全在客户端完成,不会影响页面本身的渲染类型判定。Context状态是客户端侧数据
useMainIngreds获取的mainIngreds是客户端Context维护的状态,完全不参与服务器端渲染流程。构建阶段Next.js无法感知客户端的状态变化,自然不会将页面标记为动态渲染。
如果需要将该页面改为动态渲染(λ),可以直接在页面文件中添加:
export const dynamic = 'force-dynamic';
或者通过getServerSideProps在服务器端处理数据请求(需注意将mainIngreds通过请求参数传递到服务器)。
内容的提问来源于stack exchange,提问作者Nia_H

