导读:本期聚焦于张立峰创作的《React预渲染怎么做?SSR与SSG混合使用的场景与实现方案》,敬请观看详情。页面加载慢、SEO收录差,往往是渲染策略没选对。React生态中SSR按请求动态渲染,SSG在构建期生成静态HTML,两者各有适用边界。本文围绕电商详情页、博客列表、后台仪表盘等真实场景,分析什么页面该用SSG、什么页面必须上SSR,以及如何在Next.js这类框架里对同一路由做增量静态再生和fallback按需渲染。内容涵盖getStaticProps与getServerSideProps的取舍、混合渲染带来的CDN缓存与服务器压力差异、动态参数页面用fallback策略优化的实践,帮助你用最小成本同时拿到静态化的速度和服务端渲染的灵活性。

React应用默认在浏览器端完成渲染,这意味着用户拿到的是一份几乎空白的HTML外壳,再由JavaScript接管页面生成。这种方式对交互型后台没问题,但面对内容页、商品页这类需要SEO和首屏速度的场景就力不从心了。React生态给出的答案是预渲染,也就是在请求到达之前或请求发生时,由服务端先产出一份完整的HTML。预渲染主要分两条路线:SSR(服务器端渲染)在每次请求时动态生成HTML,SSG(静态站点生成)则在构建阶段一次性生成所有HTML文件。实际项目中,一个站点往往同时存在静态内容和动态内容,单一策略很难覆盖全部需求,因此SSR与SSG的混合使用成为React工程中的常见实践。

React预渲染怎么做?SSR与SSG混合使用的场景与实现方案

SSR与SSG的核心差异在哪里

要理解混合策略,先要弄清两种渲染方式的本质区别。SSG发生在构建时刻,构建脚本会遍历所有可能的页面路径,把每个页面渲染成独立的HTML文件,部署后这些文件可以直接放在CDN上,用户请求时几乎零计算开销。SSR则发生在请求时刻,服务器收到请求后执行React组件的渲染逻辑,可能还要去数据库或接口拉取最新数据,再把拼好的HTML返回给浏览器。

两者的差异直接体现在三个维度。第一是数据时效性:SSG的页面内容在构建时就固定了,数据更新需要重新构建;SSR每次请求都能拿到最新数据。第二是服务器压力:SSG部署后是纯静态资源,可以用任何静态服务器托管;SSR需要常驻的Node.js进程,请求量大时要考虑扩容。第三是首屏性能:SSG配合CDN能做到极快的响应,SSR虽然省去了客户端请求数据的等待,但渲染本身消耗服务器时间,高并发下反而可能变慢。

用一个简单的类比来理解:SSG像提前印好的报纸,印刷完成那一刻内容就定了,分发速度极快;SSR像现场打印的定制报告,内容永远最新,但每一份都要现做。理解了这一点,混合策略的思路就清晰了——把页面按内容更新频率分类,静态的走SSG,动态的走SSR,处于中间状态的用增量再生来平衡。

如何判断页面该用哪种渲染策略

选择渲染策略的核心依据是数据变化频率和个性化程度。对于营销首页、帮助文档、博客文章这类内容,更新频率低且对所有用户一致,SSG是毫无疑问的最优解。构建一次,全球CDN分发,首屏性能和SEO都能拉满。而对于用户个人中心、购物车、实时行情这类强个性化或强实时页面,SSR是唯一选择,因为构建时根本无法预知每个用户会看到什么。

真正麻烦的是中间地带。比如电商商品详情页,全站可能有几百万个SKU,构建时全部静态化会导致构建时间长达数小时,但如果全部走SSR,服务器又要承担巨大的渲染压力。再比如新闻资讯站,列表页需要相对及时,但也不必精确到秒级。针对这类场景,Next.js提供了两个折中手段:增量静态再生(ISR)允许静态页面在指定时间间隔后自动重新生成,以及动态参数的fallback模式,让未被静态化的路径在首次请求时按需生成,之后复用静态缓存。

一个实用的判断流程是:先问页面数据是否与用户身份相关,相关则SSR;再问页面数量是否可控且更新频率是否低于每日级别,是则纯SSG;如果页面数量庞大或更新频繁但不需要每次都最新,用ISR设置合理的再验证时间;只有确实要求每次请求都是最新数据的页面,才落到SSR。这套分层能覆盖绝大多数业务场景。

Next.js中混合渲染的代码实践

下面通过一个电商站点的例子展示混合渲染的写法。商品列表页数据更新不频繁,用ISR每60秒再生一次;商品详情页数量庞大,用fallback按需静态化;用户订单页强个性化,走SSR。

// pages/products/index.js
// 商品列表页:增量静态再生,60秒后后台刷新
export async function getStaticProps() {
  const products = await fetch('https://api.ipipp.com/products?limit=20')
    .then(res => res.json());

  return {
    props: { products },
    revalidate: 60, // 60秒内返回缓存,之后首次请求触发后台重新生成
  };
}

// pages/products/[id].js
// 商品详情页:只预渲染部分热门商品,其余按需生成
export async function getStaticPaths() {
  const hotProducts = await fetch('https://api.ipipp.com/products/hot')
    .then(res => res.json());

  return {
    paths: hotProducts.map(p => ({ params: { id: String(p.id) } })),
    fallback: 'blocking', // 未预渲染的路径在请求时生成,完成后缓存为静态页
  };
}

export async function getStaticProps({ params }) {
  const product = await fetch(`https://api.ipipp.com/products/${params.id}`)
    .then(res => res.json());

  return {
    props: { product },
    revalidate: 300, // 长尾商品5分钟再生一次即可
  };
}

// pages/orders.js
// 订单页:强个性化数据,必须走服务端渲染
export async function getServerSideProps({ req }) {
  const token = req.cookies.session;
  const orders = await fetch('https://api.ipipp.com/orders', {
    headers: { Authorization: `Bearer ${token}` },
  }).then(res => res.json());

  return { props: { orders } };
}

上面三段代码覆盖了混合渲染的三种典型形态。revalidate字段是ISR的关键,它声明了静态页面的有效期,过期后的第一个请求仍会拿到旧的缓存页面,同时服务器在后台重新生成新版本,这种策略保证了用户永远不会因为等待重建而卡住。fallback设为blocking时,未预渲染的路径会在请求时同步生成HTML再返回,用户看到的是完整内容而非骨架屏,SEO爬虫也能正常抓取。

需要注意SSR页面与静态页面的部署差异。getServerSideProps所在的页面要求运行环境是Node.js服务器或支持函数计算的边缘节点,不能直接扔到纯静态托管上。如果项目部署在Vercel,SSR会自动转为Serverless函数;自建服务器则需要用next start启动并做好进程守护和负载均衡。混合策略下建议把静态页面和动态页面的路由做好规划,静态的尽量收敛到独立目录,便于CDN缓存规则的配置。

混合方案的常见坑与优化建议

第一个常见的坑是ISR的缓存失效问题。当数据源发生变更时,除了等待revalidate到期,也可以主动调用revalidate接口触发指定路径的重新生成,这在商品价格修改、文章发布等场景下能实现准实时的内容更新,同时保留静态化的性能优势。

第二个坑是构建时间失控。如果商品规模持续增长,即使fallback策略也要维护热门商品的预渲染列表,建议根据访问日志动态生成getStaticPaths的返回值,只预渲染近期有流量的页面,让长尾完全依赖按需生成。同时为构建任务设置合理的并行度和超时,避免一次数据接口变慢拖垮整个构建流程。

第三个坑是水合(hydration)不一致。无论SSG还是SSR,服务端产出的HTML会在客户端被React重新接管,如果渲染逻辑依赖windowDate.now这类环境相关的值,就会出现水合警告甚至页面错乱。解决办法是把环境相关的计算放到useEffect中执行,或者利用suppressHydrationWarning处理确实无法避免的差异。把这些细节处理好,混合渲染方案才能在性能、实时性和维护成本之间拿到最好的平衡。

React预渲染SSR服务器端渲染SSG静态站点生成修改时间:2026-08-31 18:29:11

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。