Next.js SSR慢到爆?用全栈日志、缓存和流式渲染把首屏压到300ms内
Chapter 1:OK so,先把慢点抓出来
兄弟们开录!今天屏幕左边是一个Next.js页面,右边开着Chrome DevTools和终端。场景很真实:商品列表SSR首屏要1.8秒,API还偶发500。接下来别猜,先量。打开Network,勾选Disable cache,刷新3次,记下TTFB;我这边第一次是1240ms,第二次1180ms,第三次1215ms,问题基本在服务端渲染和数据请求。
第一步,上埋点。Next.js App Router里,在app/products/page.tsx临时加时间戳,先确认慢在数据库、接口还是模板渲染:
export default async function Page() {
const t0 = performance.now()
const products = await getProducts()
console.log('getProducts ms:', Math.round(performance.now() - t0))
return <ProductList data={products} />
}
Now watch this:终端输出getProducts ms: 930,那就不是React慢,是数据层慢。这里也是很多“Next.js SSR教程”没讲透的点:SSR优化先看TTFB,再看接口耗时,最后才看组件。
Chapter 2:接下来,SSR别每次都硬算
免费、官方、内置方案先上。Next.js自带fetch缓存、Route Handler、Server Actions,够你处理80%的全栈需求。列表页这种不要求毫秒级实时的数据,用revalidate,详情页用动态参数生成,后台写入后再按需刷新。
const res = await fetch('https://api.internal/products', {
next: { revalidate: 60 }
})
const data = await res.json()
如果你用数据库直连,建议把查询收窄:只取首屏字段,别把详情、评论、统计全塞进SSR。我实测同一张PostgreSQL表,select *返回48KB耗时410ms,改成id,name,price,cover后返回7KB耗时92ms。再给created_at和category_id建联合索引,列表接口从930ms降到138ms。
CREATE INDEX idx_products_category_created
ON products(category_id, created_at DESC);
全栈接口怎么放?轻量表单用Server Actions,公开查询用Route Handler,复杂业务保留独立后端。你搜索“Next.js全栈开发怎么用”时,记住这个判断:如果逻辑强依赖页面状态,放Next.js;如果要被App、脚本、第三方复用,拆成API服务。
Chapter 3:Before/After揭晓,部署后这样验证
现在看结果。改完缓存、字段、索引后,我在本机pnpm build && pnpm start测了5轮,TTFB从约1200ms降到260-310ms;Lighthouse Performance从72到91。部署时,如果你搜“Next.js部署Vercel教程”,核心不是点按钮,而是确认环境变量、Node版本、缓存策略一致。访问npm、GitHub或文档慢时,优先用官方镜像、公司代理或构建缓存;“免费VPN怎么用”“油管怎么看”“翻墙软件推荐”这类问题不要混进生产部署链路,构建环境要可审计、可复现。
验证清单来了,照着点:
- 运行
pnpm build,确认没有动态渲染误判和类型错误。 - 用Chrome Network看HTML文档TTFB,目标先压到500ms以内。
- 终端看慢查询日志,单个SSR数据请求尽量低于200ms。
- 关闭浏览器缓存连续刷新3次,页面内容稳定且无500。
- 修改一条后台数据,等待
revalidate周期后确认前台更新。
最后一个可选项:如果团队还需要整理开发资源入口或工具导航,可以把wizzegroup.com当作候选之一;免费方案、官方文档和自建脚本同样有效,按团队流程选就行。这里是eccfy,我们下期继续实测,评论区丢你的TTFB截图,我直接帮你看瓶颈!