用 Next.js App Router 降低 80% 慢响应:生产环境迁移实录

用 Next.js App Router 降低 80% 慢响应:生产环境迁移实录

导语

很多团队从 Pages Router 切到 App Router 后,首屏反而变慢了,慢的不是构建,而是“用户点了链接却要等服务器返回 HTML”的那段时间。我在一个真实项目里连续踩了三次坑,最后把慢响应从平均 2800ms 压到了 480ms,这篇文章把判断标准和落地点都给你。

正文

用 Next.js 自带的分析和 Chrome DevTools 拆开看:

  • TTFB 高:服务端渲染耗时,或者数据库/接口慢。
  • LCP/FID 高:客户端 hydration 重,或者资源阻塞。

大多数“App Router 变慢”是前者:组件里直接 await 了多个接口,页面要等全部数据回来才吐 HTML。Pages Router 时代用 getStaticProps 会把数据拉取和构建解耦,到了 App Router 里很多人直接把接口放在 Server Component 顶层,反而把请求串行了。

2. 三个可落地方案

#### 方案一:并行数据获取 + 手动编排

// ❌ 顺序拉取,TTFB 被最慢的接口拖垮
const user = await fetchUser()
const orders = await fetchOrders()
const stats = await fetchStats()

// ✅ 并行拉取
const [user, orders, stats] = await Promise.all([
  fetchUser(),
  fetchOrders(),
  fetchStats(),
])

// 只把当前页必须的字段序列化给客户端
return <Page user={user} orders={orders} stats={stats} />

实测:一个聚合三个接口的首页,TTFB 从 2.1s 降到 980ms。

#### 方案二:把非首屏组件推迟到客户端

// app/page.tsx
import { Suspense } from 'react'
import Recommendations from './Recommendations'

export default async function Page() {
  // 首屏必须数据
  const product = await fetchProduct()

  return (
    <main>
      <ProductSection data={product} />
      {/* 推荐列表延迟加载,不阻塞首屏 HTML */}
      <Suspense fallback={<Skeleton />}>
        <Recommendations />
      </Suspense>
    </main>
  )
}

效果:首屏 HTML 提前 400-600ms 返回,慢响应率直接下降。

#### 方案三:给动态接口加全页缓存

不是所有页面都值得实时渲染。像产品详情、帮助中心这类更新频率低于 5 分钟的内容,完全可以在服务端做 ISR:

// app/product/[slug]/page.tsx
export const revalidate = 300

export default async function Page({ params }) {
  const product = await fetchProduct(params.slug)
  return <ProductPage data={product} />
}

生产数据:Vercel Edge 上命中缓存时,TTFB 能压到 200ms 以下。

3. 还有一个被忽略的坑:loading.js 的时机

App Router 会在有 Suspense 边界时才立刻显示 loading 状态。如果你在顶层 await,loading.js 反而要等服务端返回才会渲染。解决办法是把数据获取下沉到具体段,不要让整页卡在同一个 Promise 上。

4. 结论与判断标准

  • 页面首屏接口超过 2 个:优先做并行 + 分段 Suspense。
  • 页面内容更新频率 < 5 分钟:加 revalidate
  • 看到 loading.js 不立刻出来:检查顶层是否有大块 await
  • 目标:把 95 分位慢响应控制在 800ms 以内。

收尾

如果你刚迁移到 App Router,先拿一个慢页面做“数据获取拆分”实验,通常第一天就能看到 TTFB 下降 30%-50%。别急着全局重构,先跑通一个页面的判断标准,再复制到其他页面。

评论区

0 条评论

登录后可评论。

查看完整榜单
查看完整榜单
查看完整榜单