ข้ามไปยังเนื้อหา

Static และ Dynamic Rendering

Next.js prerender ทุก route เป็น static HTML ตอน build โดย default เว้นแต่ route นั้นต้องใช้ data ตอน request — พอถึงจุดนั้น route จะกลายเป็น dynamic และ render ใหม่ทุก request

route ที่ไม่มี input ตอน request จะถูก render ครั้งเดียวตอน build แล้วเสิร์ฟเป็น static HTML ไม่มีอะไรรันต่อ request เลย ทุกคนได้ bytes ชุดเดียวกัน

// app/about/page.tsx — no dynamic APIs, so this is prerendered at build time
export default function AboutPage() {
return <h1>About us</h1>;
}

นี่คือเส้นทางที่เร็วที่สุด HTML วางอยู่บน CDN แล้วตอบกลับทันที หน้า marketing, docs และ content ส่วนใหญ่ควรอยู่ตรงนี้

route จะสลับไปเป็น dynamic rendering ทันทีที่พึ่งพาบางอย่างที่รู้ได้เฉพาะตอน request อย่างใดอย่างหนึ่งต่อไปนี้ทำให้ route flip —

  • Dynamic APIcookies(), headers(), draftMode() หรือการอ่าน searchParams / params Promise ตอน request
  • uncached data requestfetch() ที่ใส่ cache: 'no-store' (หรือ fetch ใด ๆ ภายใต้ default ของ Next.js 15+ ที่คุณยังไม่ opt-in cache)
  • การ export const dynamic = 'force-dynamic' แบบตรง ๆ
// app/dashboard/page.tsx — reading cookies() flips this route to dynamic
import { cookies } from 'next/headers';
export default async function Dashboard() {
const store = await cookies();
const theme = store.get('theme')?.value ?? 'light';
return <p>Active theme: {theme}</p>;
}

คุณบังคับ mode เองได้ด้วย segment config export —

// Force a route to render on every request, even with no dynamic API
export const dynamic = 'force-dynamic';

dynamic segment อย่าง [slug] ไม่มีค่าตายตัวตอน build generateStaticParams บอก Next.js ว่าค่าไหนบ้างที่ต้อง prerender เปลี่ยน dynamic route ให้เป็นชุดของ static page — เป็นตัวแทนของ getStaticPaths เดิมใน App Router

app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then((r) => r.json());
return posts.map((post) => ({ slug: post.slug }));
}
export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
return <article>Reading post: {slug}</article>;
}

slug แต่ละตัวที่ return ออกมาจะถูก build เป็น static HTML ไฟล์ของตัวเองตอน build

next build พิมพ์ legend ที่บอก mode ของทุก route จำสัญลักษณ์สามตัวได้แล้วคุณไม่ต้องเดาอีก —

Route (app) Rendering
○ /about Static prerendered as static HTML
ƒ /dashboard Dynamic server-rendered on each request
● /blog/[slug] SSG prerendered via generateStaticParams

ถ้า route ที่คุณคิดว่าเป็น static ขึ้น ƒ แปลว่ามีบางอย่างข้างในไปแตะ data ตอน request ให้ไล่กลับไปหา Dynamic API หรือ uncached fetch ที่เป็นต้นเหตุ

flowchart TD
  A[Incoming request] --> B{Dynamic API or uncached fetch?}
  B -- No --> C[Static render, prerendered at build]
  B -- Yes --> D[Dynamic render, on each request]
  E[generateStaticParams] --> C
How Next.js decides static vs dynamic
Next.js render route แบบไหนโดย default?
ข้อไหนทำให้ route flip ไปเป็น dynamic rendering?
generateStaticParams ทำอะไร?
ใน build output สัญลักษณ์ ƒ หมายถึงอะไร?