什么情况下内容站不该用 Next.js

用可直接复制的基准命令、真实的 bundle / 成本对比表,以及分阶段的 Astro 6 迁移方案,识别 Next.js 在内容站上的错配并安全迁移、保住 SEO。

原本不需要 Next.js 的内容站,第一天和真正需要它的站点长得一模一样。错配要到第三个月才暴露:build 变慢、一篇 95% 是文字的页面却发了 200 KB 以上的 JavaScript、托管账单被你调不动的带宽吃掉、本该一次静态 export 的事却变成了 CMS 改一次重建一次。这篇给你确认错配的具体命令、一张真实的成本与 bundle 对比表,以及一套保住排名的分阶段 Astro 迁移方案。

一句话总结

  • Next.js 16(截至 2026 年 5 月为 16.2.6 LTS)是为 App + 内容混合面设计的。如果你一个 'use client' 组件、一个 server action、一条 middleware 都没有,那你就是在一个 React 运行时上跑静态站生成器。
  • Astro 6(2026 年 3 月起稳定)默认零 JavaScript,是大多数团队搬内容站的首选。Astro 项目已于 2026 年 1 月被 Cloudflare 收购,仍保持 MIT 开源协议。
  • 跑下面四组基准命令。命中 3 条及以上,迁移就值得:bundle 更小、build 更快、托管更便宜。
  • 用 301 做 URL 一对一迁移。SEO 风险在 URL 映射,不在框架本身。

错配到底在哪

Next.js 16 优化的是 App 和内容混在一起的场景:按用户的后台、登录态流程、server action、流式渲染,以及新的 Cache Components 模型(部分预渲染 PPR 加 use cache)。这些特性正是框架的价值所在。可一旦是营销站或博客,动态部分只有一个搜索框和一个联系表单,这些特性谁都用不上,却每一个都在增加 build 复杂度和发出去的字节。

代价很具体。默认的 Next.js App Router 页面即便没有任何可交互内容,也会 hydrate React 运行时。Astro 反过来:组件在 build 时渲染成 HTML,除非你显式标记为 island,否则不发任何客户端 JavaScript。落到实处,就是首屏 200 KB+ bundle 和近乎为零之间的差别。

怎么判断你正撞上错配

五个信号,命中 3 条及以上,基本就是在白交 Next.js 的税:

  • 过去三个月你一个 'use client' 组件都没写。
  • next build 比你过去三个 Astro 项目加起来还慢。
  • 你从来没上过 server action、route handler 或 middleware 文件。
  • 托管账单大头是带宽而不是函数执行——也就是在给 Vercel 付 Cloudflare Pages 或 Firebase Hosting 更便宜(往往免费)就能做的事。
  • Lighthouse 提示一篇普通文章页发了 200 KB+ 的 JavaScript,而且大半没用到。

你到底能换来什么

这一段是大多数「Astro vs Next.js」文章跳过的部分——给真实数字,不讲玄学。下面是内容页的典型结果和截至 2026 年 6 月的公开定价;用后文的命令测自己的页面。

维度Next.js 16(内容页)Astro 6(内容页)
文字文章的客户端 JSReact 运行时 hydrate,常见 150-250 KB默认零;只有标记的 island 才发 JS
Lighthouse 性能分随 hydration 开销波动Astro 站点通常 95-100 分
Markdown build 速度内容多时偏慢比 Astro 5 快约 5 倍;100 篇站点重建约 200 毫秒
Core Web Vitals 通过率看调优Astro 是唯一一个超过 50% 站点通过 CrUX 的框架
免费商用托管Vercel Hobby 不允许商用静态产物可免费跑在 Cloudflare Pages(允许商用)

最关键的是第一行:内容页根本不需要一棵 hydrate 过的 React 树,发出去就是纯开销,砸的正好是 Google 真正拿来排名的那个指标。

托管成本的真相(2026 年 6 月)

带宽这条信号最多人算错,所以决定前先把账算清楚:

托管免费额度免费层能商用吗付费带宽
VercelHobby:100 GB Fast Data Transfer/月不能(Hobby 仅非商用)Pro $20/席,含 1 TB,超出 $0.15/GB
Cloudflare Pages带宽无限,500 次 build/月实质无限;不卡流量、不计超额
Firebase HostingSpark:约 10 GB 存储 + 约 10 GB 流量/月Blaze:按量付费

如果你的站点是静态且流量大,用 Cloudflare Pages 托管 Astro 产物几乎无敌:带宽无限、允许商用、没有按 GB 的出口计费。Next.js 应用跑在 Vercel Pro 上一旦超出 1 TB,就要在 $20 席位费之外按 $0.15/GB 付——而这些字节静态托管是免费送的。

迁移前:先记下基线

没有对比数字之前别动手开搬。现在花五分钟,省下日后一场争论。

  • 记下当前最有代表性那篇文章的 build 时间、LCP 和首屏 JS。
  • 选一篇典型文章 + 列表页作为迁移试验对象。
  • 留半天做一次并行 Astro 实验——够搬一个页面并测出来就行。

实操步骤

1. 盘点动态面

几条 grep 就能告诉你 Next.js 你实际用了多少:

# 客户端组件 / server action / middleware / route handler 数量
grep -rl "^'use client'" app/ | wc -l
grep -rl "^'use server'" app/ | wc -l
ls middleware.* 2>/dev/null
find app -name 'route.ts' -o -name 'route.tsx' | wc -l

纯内容站应当几乎没有 'use server'、没有 middleware.*route.ts 极少。如果这些数都很高,到此为止——你有的是一个真正的 App,Next.js 就是对的工具。

2. 基准测 build 和 bundle

time npm run build
# real: ?m ?s

# 典型文章页加载了什么?
ls -lh .next/static/chunks/ | sort -k5 -h | tail
# 单页加载的最大 chunks

3. 对典型文章跑 Lighthouse

npx lighthouse https://yourdomain.com/articles/sample-slug/ \
  --only-categories=performance,seo \
  --chrome-flags="--headless" --quiet --output=json --output-path=./lh-next.json

jq '.audits."largest-contentful-paint".numericValue,
    .audits."total-blocking-time".numericValue,
    .audits."total-byte-weight".numericValue,
    .audits."unused-javascript".details.overallSavingsBytes' lh-next.json

记下 LCP(ms)、TBT(ms)、总字节、未用 JS。未用 JavaScript 这个数是铁证:内容页本该接近零,而 Next.js 博客通常不是。

4. 并行起一个 Astro 6 实验

从零搬一篇文章加列表页:

npm create astro@latest blog-spike -- --template minimal --install --yes
cd blog-spike
npm install @astrojs/mdx @astrojs/sitemap
# astro.config.mjs 里加 site + sitemap;往 src/content 放一篇 .mdx 文章
npm run build
ls dist/articles/sample-slug/   # 确认产物

Astro 6 用的是 Content Layer:每个集合用一个 loader 定义内容来自哪里(本地文件、API 或 headless CMS),并带类型安全的 schema。多数现有 MDX frontmatter 只需改 schema 就能迁过去。

5. 对比两次 build

# Astro build 时间
time npm run build

# 同一篇文章 URL 上跑 Astro 的 Lighthouse
npx lighthouse http://localhost:4321/articles/sample-slug/ \
  --only-categories=performance --chrome-flags="--headless" --output=json \
  --output-path=./lh-astro.json
jq '.audits."largest-contentful-paint".numericValue,
    .audits."total-byte-weight".numericValue' lh-astro.json

Astro 内容页应当近乎零 JS,总字节相比 Next.js 页面大幅下降。

6. 分阶段规划迁移

每一步都留好回滚路径的可行顺序:

阶段 1(1-2 周):Astro 项目做到博客对等
阶段 2(1 周):营销页迁移
阶段 3(3-5 天):把旧 Next.js URL 的 301 映射写出来
阶段 4(1 天):切 DNS / 托管;冻结(别删)Next.js 仓库

7. 写 301 重定向

Vercel,写在 vercel.json

{
  "redirects": [
    { "source": "/old/(.*)", "destination": "/articles/$1", "permanent": true }
  ]
}

Cloudflare Pages 或 Netlify,写在 _redirects 文件:

/old/*  /articles/:splat  301

每条旧 URL 只映射到一条新 URL。重定向链(旧 → 临时 → 新)会漏权重,所以保持一跳到位。

8. 上线后验证 SEO

上线后 2-4 周,用 Search Console 的 URL Inspection 加 Performance 报告。平均位置应稳住或上升,文章页的 LCP/INP 应明显改善。如果一批 URL 掉出索引,检查它们的 301 是不是一跳到位、是否返回的是 301(而不是 302)。

上线后检查清单

  • 典型文章页 LCP 下降 30% 以上。
  • 无客户端 island 的文章页总字节下降 60%+。
  • Search Console「已编入索引」数量 4-8 周内回到基线。
  • Search Console 没有出现旧 URL 的新 404——301 都接住了。
  • 旧 Next.js 仓库冻结而非删除,至少保留 30 天作为回滚选项。

常见坑

  • 为了一次慢 build 就迁移。 先做性能剖析——慢往往是糟糕的图片流水线,换任何框架都一样慢。先修它,别急着怪 Next.js。
  • 在 Astro 里重建 Next.js。 把每个 island 都标 client:load,等于把你想甩掉的 JavaScript 又发了一遍。改用 client:visibleclient:idle,且只用在真正需要交互的组件上。
  • 低估 URL 映射。 每条旧 URL 都要一个 301 指向新位置,否则那些页面挣来的排名就丢了。
  • 上线途中换工具。 选一个框架先上线,数据支持再换。
  • 太早删旧仓库。 保留 30+ 天,万一流量崩了能一个下午切回 DNS。

FAQ

  • 迁移会丢 SEO 吗?:只在 URL 变了却没做 301,或者 Core Web Vitals 退化时才丢。规划得当的 Next.js 到 Astro 迁移通常一个月内排名稳住甚至提升,因为内容页加载更快了。
  • Astro 跑内容真的比 Next.js 快吗?:文字多的页面,是的——默认零 JavaScript 去掉了拉高 TBT 和 INP 的 hydration 开销。Astro 也是唯一一个超过 50% 线上站点通过 Google Core Web Vitals 评估的框架。
  • 迁移时能保留 MDX 吗?:能。Astro 6 通过 @astrojs/mdx 原生支持 MDX。多数 frontmatter 和组件只需在 Content Layer 的集合定义里改一下 schema 就能迁过来。
  • 迁移后托管怎么选?:Astro 静态产物哪都能跑——Cloudflare Pages(免费层带宽无限、允许商用)、Firebase Hosting、Vercel、Netlify,或者裸 S3。你不再为没用上的 SSR 付费。
  • Next.js 16 加了 Cache Components,要不要等等看?:Cache Components(PPR 加 use cache)加速的是动态、像 App 一样的页面。静态内容站在请求时没有什么可缓存的,所以它不改变结论。
  • 典型迁移要多久?:100-200 篇的站点,兼职 2-4 周。多数时间花在内容 QA 和 301 映射上,不是框架代码。

相关阅读

标签: #独立开发 #Next.js #对比 #建站策划