原本不需要 Next.js 的内容站,第一天看不出问题。第三个月才暴露——build 变慢、bundle 变大、部署事故变多、CMS 重建流程本可以是一次静态 export。下面给出基准测试命令和迁移计划,确认错配就上路。
问题背景
Next.js 是为 App + 内容混合面优化的。没有 App、没有按用户状态、动态部分只有搜索和联系表单时,Next.js 高级特性要么没用上要么挡你的路。Astro / Hugo / Eleventy 甚至裸 HTML,bundle 更小、心智更简单。
判断标准
- 三个月了你一个
'use client'组件都没写。 next build比你过去三个 Astro 项目加起来都慢。- 你从来没用过 server action、route handler 或 middleware。
- 托管账单大头是带宽不是函数执行——也就是说在给 Vercel 付 Cloudflare Pages / Firebase Hosting 更便宜的钱。
- Lighthouse 提示一篇博客文章发了 200 KB 以上的 JS。
快速结论
上面信号符合 3 条以上,你就是把 Next.js 当 SSG 在用。要原班 DX 的更小产物迁 Astro,根本不需要组件模型就用 Hugo / Eleventy。
开始前准备
- 动手前先把当前 build 时间、LCP、bundle 大小记下来。
- 选一篇最典型的文章作为对比页。
- 留半天做并行 Astro 实验。
实操步骤
- 盘点动态面。 grep 说真话:
# 客户端组件 / 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 极少。
- 当前状态基准。 build 时间 + bundle:
time npm run build
# real: ?m ?s
# 典型文章页加载什么?
ls -lh .next/static/chunks/ | sort -k5 -h | tail
# 单页加载的最大 chunks
- 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。
- 并行起 Astro 项目,搬一篇文章 + 列表页。 从零:
npm create astro@latest blog-spike -- --template minimal --install --yes
cd blog-spike
npm install @astrojs/mdx @astrojs/sitemap
# astro.config.mjs 加 site、sitemap;放一篇 .mdx 文章
npm run build
ls dist/articles/sample-slug/ # 确认产物
- 对比:
# Astro build 时间
time npm run build
# 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,总字节大幅下降。
- 分阶段迁移计划:
阶段 1(1-2 周):博客 Astro 项目对等
阶段 2(1 周):营销页迁移
阶段 3(3-5 天):旧 Next.js URL 301 到新
阶段 4(1 天):切 DNS / 托管;Next.js 仓库冻结
- 新 host 配置里写 301。 Vercel
vercel.json:
{
"redirects": [
{ "source": "/old/(.*)", "destination": "/articles/$1", "permanent": true }
]
}
Cloudflare Pages / Netlify 的 _redirects:
/old/* /articles/:splat 301
- 上线后验 SEO。 2-4 周后 Search Console URL Inspection + Performance 对比。平均位置应稳或升;LCP/INP 明显改善。
执行检查清单
- 迁移前已录入清单 + 基准。
- Astro 实验完成且 Lighthouse 有可量化提升。
- 迁移计划分阶段写出来,含回滚路径。
- 旧 URL 集 1:1 映射到新 URL 的 301。
- 旧 Next.js 仓库冻结但不删,保留 30+ 天。
上线后验证
- 典型文章页 LCP 降 ≥ 30%。
- 无客户端 island 的文章页总字节降 60%+。
- Search Console “Indexed” 数 4-8 周内回到基线。
- Search Console 没有旧 URL 404(301 都接住了)。
容易踩的坑
- 为了一次慢 build 迁移,结果发现慢是图片流水线问题——任何框架都一样慢。
- 选了 Astro 后把每个 island 都
client:load——等于慢动作重建 Next.js。 - 低估 URL 迁移成本——旧 URL 每条都要 301,否则丢排名。
- 上线前换工具——选一个先上线,数据支持再换。
- 旧 Next.js 仓库删太早——保留 30+ 天作为回滚选项。
FAQ
- 迁移会丢 SEO 吗?: 只在 URL 变了没做 301、或者 Core Web Vitals 退化时丢。规划好的 Next.js 到 Astro 通常一个月内排名反而提升。
- Astro 真的比 Next.js 跑内容快吗?: 默认零 JS 让内容页 LCP / INP 有可测差距,build 通常也更快。
- 迁移能保留 MDX 吗?: 能。Astro 原生支持 MDX。多数 frontmatter 和组件小改即可迁过去。
- 托管怎么办?: Astro 静态产物哪都能跑——Cloudflare Pages、Firebase Hosting、Vercel、Netlify、S3。不再为没用上的 SSR 付费。
- 典型迁移要多久?: 100-200 篇站点 2-4 周兼职。多数时间花在内容 QA 和 301,不是框架代码。