You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js SSR模式下如何指定特定组件在服务端渲染

Next.js SSR 首屏指定组件服务端直出方案

完全可行,核心思路是拆分首屏关键内容和非关键内容的渲染、水合边界,让above-the-fold的关键内容随SSR响应直接输出可直接绘制的HTML,不被非必要的JS加载、数据请求、水合逻辑阻塞。

常见误区:Next.js 不管是Pages Router的getServerSideProps模式,还是App Router的服务端组件模式,默认都会把服务端执行生成的HTML字符串直接返回给浏览器,浏览器拿到HTML片段就可以直接解析绘制,不需要等客户端JS执行。你遇到的关键内容要等JS加载完才显示的问题,基本都是渲染边界拆分不合理、非关键逻辑阻塞了关键内容输出导致的,不是框架本身不支持。

1. App Router 场景(推荐)

App Router的React Server Components(RSC)能力天然适配这个需求,不需要额外引入复杂配置:

  • 把所有首屏关键内容写成默认的服务端组件(不需要加'use client'标记),这部分内容会在服务端直接生成静态HTML,随首次响应的第一块数据直接返回,浏览器拿到就能绘制,完全不依赖客户端JS。
  • 非首屏、需要客户端交互的重型组件,统一标记'use client',配合动态导入和Suspense做懒加载、延迟水合,不要让这部分组件进入首屏关键渲染路径:
    import { Suspense, lazy } from 'react'
    import HeavyListSkeleton from '@/components/skeletons/HeavyList'
    // 懒加载非关键客户端组件
    const HeavyBelowTheFold = lazy(() => import('@/components/HeavyBelowTheFold'))
    
    export default function Page() {
      return (
        <main>
          {/* 首屏关键内容,服务端直出,无JS依赖 */}
          <AboveTheFoldHero />
          <AboveTheFoldProductInfo />
          
          {/* 非首屏内容,懒加载+骨架占位,不阻塞首屏 */}
          <Suspense fallback={<HeavyListSkeleton />}>
            <HeavyBelowTheFold />
          </Suspense>
        </main>
      )
    }
    
  • 配合Next.js默认的流式渲染能力,服务端不需要等所有非关键组件、非关键接口请求完成,就可以先把首屏关键内容的HTML返回给浏览器,非关键内容渲染完成后再通过分块传输推送到前端,能大幅降低LCP等待时间。
  • 注意不要在首屏关键路径的服务端组件里直接引入重型客户端组件,否则这部分组件的JS会被打包进初始加载包,拖慢水合节奏。

2. Pages Router 场景

如果暂时无法迁移到App Router,用getServerSideProps也可以实现同等效果:

  • 首屏关键展示内容直接写在页面根组件的顶层,不要加任何typeof window !== 'undefined'的客户端判断、不要放在useEffect里渲染,这部分内容会随SSR响应直接生成HTML返回。
  • 所有非首屏的重型组件,统一用next/dynamic做动态导入,配合骨架屏占位,避免阻塞首屏:
    import dynamic from 'next/dynamic'
    import ReviewListSkeleton from '@/components/skeletons/ReviewList'
    
    // 懒加载非首屏评论组件,不需要首屏直出的可以直接关ssr减少服务端压力
    const ReviewList = dynamic(() => import('@/components/ReviewList'), {
      loading: () => <ReviewListSkeleton />,
      ssr: false
    })
    
    export default function ProductPage({ product }) {
      return (
        <main>
          {/* 首屏关键内容,SSR直出 */}
          <h1>{product.name}</h1>
          <img src={product.cover} alt={product.name} />
          <div>{product.desc}</div>
    
          {/* 非首屏内容懒加载 */}
          <ReviewList productId={product.id} />
        </main>
      )
    }
    
    export async function getServerSideProps(ctx) {
      // 只在根级请求首屏关键内容的数据,非关键数据下沉到组件内部请求
      const product = await fetchProduct(ctx.params.id)
      return { props: { product } }
    }
    
  • 对于需要交互的首屏组件,可以配合延迟水合方案,只给关键交互组件绑定水合逻辑,非关键组件等浏览器空闲、或者滚动到视口范围内再触发水合,减少初始JS执行的阻塞时间。

3. 关键避坑点

  • 不要在SSR根级等待所有接口返回后再响应,首屏不需要的非关键数据全部下沉到组件内部请求,配合流式渲染优先输出关键内容。
  • 首屏纯展示类内容不要加客户端侧的条件渲染判断,否则会出现水合前内容闪白、必须等JS执行才能显示的问题。
  • 给懒加载的非关键组件提前设置和实际内容高度一致的骨架占位,避免布局偏移影响LCP评分。

内容的提问来源于stack exchange,提问作者opticon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:51:22