Comparison (更新: 2026/6/2)

SSR vs SSG 比较: 用 Claude Code 选择 Next.js/Astro 渲染策略

用 Claude Code 对比 Next.js/Astro 的 SSR、SSG、ISR 与静态导出,含可运行代码、验证命令和设计提示词。

SSR vs SSG 比较: 用 Claude Code 选择 Next.js/Astro 渲染策略

先统一概念

SSR 和 SSG 的选择,不只是“哪个更快”。SSR 是 server-side rendering,也就是用户请求到达时,由服务器生成 HTML。SSG 是 static site generation,也就是构建阶段先生成 HTML,再交给 CDN 或静态主机分发。ISR 是 Incremental Static Regeneration,可以先按静态页面分发,再按时间或事件重新生成。

新手常见误解是:Next.js App Router 里的 Server Component 并不等于每次请求都 SSR。当前官方 Dynamic Route Segments 的 TypeScript 示例把 params 写成 Promise。如果页面没有使用常见的请求时 API,但你希望明确等到真实请求再渲染,可以使用官方 connection

如果只让 Claude Code “把页面变快”,它可能把页面静态化得太多,导致库存、搜索结果或会员信息过期。如果全部改成 SSR,又可能增加 TTFB 和服务器费用。更稳妥的做法,是先让 Claude Code 输出路由矩阵:数据新鲜度、是否个性化、更新频率、变现页面影响、验证命令。

对比表与真实场景

问题SSGISRSSR
HTML 生成时机构建阶段构建与重新验证阶段请求到达时
适合页面文章、文档、落地页商品、分类、新闻列表仪表盘、搜索、购物车
数据新鲜度构建时快照按时间或事件更新接近实时
分发成本中等通常更高
常见问题构建变长、内容过期短时间内可能看到旧内容不缓存会变慢

场景一是博客或文档。正文、OGP、内部链接和 CTA 在发布时固定,就优先选 SSG。文章修改时重新构建即可。如果还要减少 JavaScript 体积,可以结合Claude Code 代码分割指南

场景二是电商商品页。价格、库存、分类排序可能几分钟更新一次,但访问者仍然需要很快的静态响应。ISR 更适合这种页面。Next.js 官方 ISR 指南说明,ISR 支持 Node.js runtime,但不支持静态导出。

场景三是会员仪表盘。Cookie、权限、账单状态、未读通知、私人推荐都和请求有关,应该按 SSR 设计,并明确缓存头。若团队还在评估边缘部署,可以在策略确定后阅读Claude Code 边缘计算指南

Next.js 的 SSR 示例

下面的例子可以直接放进 Next.js App Router 项目。它使用 dummyjson.com,不需要 API key。connection()cache: "no-store" 一起出现,是为了让评审时明确知道这个页面按请求渲染。

// app/products/[id]/page.tsx
import { notFound } from "next/navigation";
import { connection } from "next/server";

type Product = {
  id: number;
  title: string;
  price: number;
  stock: number;
  updatedAt: string;
};

async function getProduct(id: string): Promise<Product | null> {
  await connection();

  const res = await fetch(`https://dummyjson.com/products/${id}`, {
    cache: "no-store",
  });

  if (res.status === 404) return null;
  if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);

  const data = (await res.json()) as {
    id: number;
    title: string;
    price: number;
    stock: number;
    meta?: { updatedAt?: string };
  };

  return {
    id: data.id,
    title: data.title,
    price: data.price,
    stock: data.stock,
    updatedAt: data.meta?.updatedAt ?? new Date().toISOString(),
  };
}

export default async function ProductPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const product = await getProduct(id);

  if (!product) notFound();

  return (
    <main>
      <h1>{product.title}</h1>
      <p>Price: ${product.price.toLocaleString("en-US")}</p>
      <p>Stock: {product.stock}</p>
      <p>Updated: {new Date(product.updatedAt).toLocaleString("zh-CN")}</p>
    </main>
  );
}

这里最容易踩的坑,是把 cookies()headers() 放进共享 layout。它看起来只是取主题或地区,实际却可能让一组页面变成动态渲染。如果这个 layout 包住文章页,本来可静态分发的页面也会受影响。让 Claude Code 在改动前列出受影响路由,比事后看性能报告更可靠。

区分 SSG、ISR 与静态导出

SSG 和 ISR 对访问者都像静态页面,但运维方式不同。SSG 在构建时生成,ISR 在时间窗口或事件后重新生成。完全静态导出则通过 output: "export" 生成 out 目录,不需要 Node.js 服务器。官方 Static Exports 说明,next build 可以为每个路由生成 HTML 文件并用于静态托管。

// app/catalog/[id]/page.tsx
import { notFound } from "next/navigation";

export const revalidate = 3600;

type Product = {
  id: number;
  title: string;
  description: string;
};

export async function generateStaticParams() {
  return ["1", "2", "3"].map((id) => ({ id }));
}

async function getProduct(id: string): Promise<Product | null> {
  const res = await fetch(`https://dummyjson.com/products/${id}`, {
    next: { revalidate: 3600, tags: [`product:${id}`] },
  });

  if (res.status === 404) return null;
  if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);

  return (await res.json()) as Product;
}

export default async function CatalogPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const product = await getProduct(id);

  if (!product) notFound();

  return (
    <article>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </article>
  );
}
// next.config.mjs
const nextConfig = {
  output: "export",
  images: {
    unoptimized: true,
  },
};

export default nextConfig;
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "export:check": "next build && npx serve out"
  }
}

不要把静态导出和 ISR 当成可以随意混用的方案。静态导出适合纯静态托管。如果需要 Cookie、按需重新验证、Server Function 或真实 SSR,就要准备服务器运行时。给 Claude Code 的任务里应先写清楚部署目标:Cloudflare Pages 静态托管、Node 容器、Vercel、Netlify,还是其他平台。

Astro 的静态与按需渲染

Astro 默认偏向静态生成。官方 Astro on-demand rendering 文档说明,页面、路由和 API endpoint 默认在构建阶段预渲染;安装对应 adapter 后,可以对单个路由写 export const prerender = false,让它按请求渲染。

---
// src/pages/docs/[slug].astro
export async function getStaticPaths() {
  const docs = [
    { slug: "ssr", title: "SSR guide" },
    { slug: "ssg", title: "SSG guide" },
  ];

  return docs.map((doc) => ({
    params: { slug: doc.slug },
    props: { doc },
  }));
}

const { doc } = Astro.props;
---

<html lang="zh-CN">
  <body>
    <article>
      <h1>{doc.title}</h1>
      <p>This page was generated at build time.</p>
    </article>
  </body>
</html>
---
// src/pages/account.astro
export const prerender = false;

const session = Astro.cookies.get("session")?.value;
const name = session ? "Masa" : "Guest";

Astro.response.headers.set("Cache-Control", "private, no-store");
---

<html lang="zh-CN">
  <body>
    <h1>Account</h1>
    <p>Hello, {name}.</p>
  </body>
</html>

Astro 的常见问题是忘记 adapter。页面在本地看起来正常,但生产环境的按需渲染需要服务器运行时。让 Claude Code 检查 astro.config.mjs、部署平台和每个 prerender 覆盖项,可以减少上线后的异常。

验证命令与 Claude Code 提示词

渲染策略不能只靠读代码确认。要看构建结果、响应头、缓存日志和性能指标。Next.js ISR 官方也建议通过 next buildnext start 验证生产行为。

# Next.js: production behavior
npm run build
npm run start

# In another terminal
curl -I http://localhost:3000/catalog/1
curl -I http://localhost:3000/products/1

# ISR cache debugging
NEXT_PRIVATE_DEBUG_CACHE=1 npm run start

# Astro
npm run build
npm run preview

给 Claude Code 的提示词不要只要求代码,要要求判断记录:

Goal: classify every route in a Next.js/Astro site as SSR, SSG, ISR, or static export.

Inspect:
- app/ or src/pages/ routes
- cookies(), headers(), searchParams, connection(), cache: "no-store"
- generateStaticParams(), revalidate, output: "export", Astro prerender
- monetization pages, member pages, articles, product pages, and search pages

Constraints:
- Do not break SEO metadata or internal links
- Keep npm run build passing before and after
- Return a table with the chosen strategy, reason, touched files, and verification command

具体坑点

第一,把用户专属内容放进静态文章。会员名、私人推荐、隐藏价格不应写入 SSG HTML。文章正文保持静态,个性化部分放到客户端组件或明确的动态区域。

第二,把 ISR 时间设得太短。revalidate = 1 往往只是把成本重新交给服务器。需要精确更新时用按需重新验证,需要实时数据时用 SSR。

第三,选择静态导出后又补充服务器能力。认证、Cookie UI、Server Route Handler、ISR 都需要运行时。静态托管很好,但不能替代服务器。

第四,只因为 Claude Code 的方案“看起来最快”就采用。对变现内容站来说,性能只是质量的一部分。OGP、结构化数据、内部链接、广告位置、CTA 计量、LCP、CLS 都要看。渲染策略确定后,可以用Claude Code 性能优化继续检查。

结合变现的建议

ClaudeCodeLab 这类内容业务,默认应把文章、教程、比较页和漏斗入口做成 SSG。商品目录、分类页、新闻式列表用 ISR。会员页、搜索、购物车、结账上下文和任何依赖私人请求数据的页面用 SSR。

如果想先建立日常流程,可以领取免费 Claude Code 速查表。需要模板和实用包,可以查看产品页面。如果团队要一起整理路由策略、权限、代码评审、分析与上线训练,可以从Claude Code 培训与咨询开始。

实际验证结果

这次更新时,我核对了 Next.js Dynamic Route Segments、connection、ISR、Static Exports、Astro on-demand rendering 和 Claude Code overview。Masa 的内容运营经验里,文章用 SSG、商品和分类列表用 ISR、账号和搜索用 SSR 是最稳定的分法。最有用的 Claude Code 步骤不是马上改代码,而是先生成路由分类表。它能提前暴露静态页面误用 Cookie 的问题,也让每个路由的理由和验证命令在评审时一眼可见。

#Claude Code #SSR #SSG #Next.js #Astro #performance
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。