原本不需要 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(内容页) |
|---|---|---|
| 文字文章的客户端 JS | React 运行时 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 月)
带宽这条信号最多人算错,所以决定前先把账算清楚:
| 托管 | 免费额度 | 免费层能商用吗 | 付费带宽 |
|---|---|---|---|
| Vercel | Hobby:100 GB Fast Data Transfer/月 | 不能(Hobby 仅非商用) | Pro $20/席,含 1 TB,超出 $0.15/GB |
| Cloudflare Pages | 带宽无限,500 次 build/月 | 能 | 实质无限;不卡流量、不计超额 |
| Firebase Hosting | Spark:约 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:visible或client: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 映射上,不是框架代码。