当前位置: 首页 > news >正文

React渲染模式选型实战:CSR/SSR/SSG决策指南

1. 项目概述:为什么网页渲染方式比你想象的更重要

React 开发者常挂在嘴边的 CSR、SSR、SSG,绝不是三个缩写游戏,而是直接决定你网站能否被搜索引擎找到、首屏加载是否卡顿、用户是否在白屏3秒后就关掉页面、甚至影响服务器成本和运维复杂度的核心架构选择。我做过27个上线项目,其中11个因早期渲染策略选错,在上线后第2周就紧急重构——不是功能不行,是首页加载时间从1.2秒飙到4.7秒,SEO流量跌了63%,客服开始收到“你们网站打不开”的批量投诉。这背后没有玄学,只有浏览器解析HTML的物理时序、服务端Node.js进程的内存占用曲线、以及CDN缓存命中率的真实数字。CSR(客户端渲染)适合管理后台这类登录后才展示内容的场景;SSR(服务端渲染)是电商首页、新闻聚合页的生命线;SSG(静态站点生成)则是文档站、营销落地页的性价比之王。三者不是升级关系,而是工具箱里的三把不同齿距的扳手:拧M3螺丝用SSG,修液压管路用SSR,调试电路板用CSR。本文不讲概念定义,只拆解我在真实项目中如何用Chrome DevTools的Network和Rendering面板定位渲染瓶颈、怎么根据Lighthouse报告里的FCP(首次内容绘制)和TTI(可交互时间)反推该切哪种模式、以及当产品突然要求“明天上线新活动页,要能被百度收录”时,我如何在2小时内把一个CSR页面改造成SSG兼容结构——包括Webpack配置里那行容易被忽略的output.publicPath: '/static/',和Vite插件中vite-plugin-ssgentryRoute参数为何必须指向/index.html而非/。如果你正面临首屏白屏、SEO抓取失败、或者部署后发现服务器CPU常年92%,这篇就是为你写的实战手册。

2. 渲染机制底层原理与三大模式的本质差异

2.1 浏览器渲染流水线:从HTML字符串到像素的7个硬性阶段

理解CSR/SSR/SSG的前提,是看清浏览器执行渲染的不可跳过步骤。这不是React的专利,而是所有Web应用的物理法则:

  1. 网络层接收:浏览器拿到HTTP响应体,通常是HTML文本(注意:此时JS/CSS尚未下载);
  2. HTML解析与DOM构建:逐行解析HTML标签,遇到<script>且无async/defer时立即阻塞并执行;
  3. CSSOM构建:并行下载CSS文件,解析成CSS对象模型,与DOM合并为Render Tree;
  4. Layout(布局计算):计算每个元素在视口中的精确坐标和尺寸;
  5. Paint(绘制):将Render Tree转为像素,分层(Layer)处理;
  6. Composite(合成):将各图层合并为最终帧;
  7. Display(显示):将帧提交给GPU,呈现在屏幕上。

关键陷阱在于:CSR的“首屏内容”实际发生在第7步之后。因为它的HTML骨架里只有<div id="root"></div>,所有真实内容都藏在JS包里。用户看到白屏,本质是在等JS下载→解析→执行→调用ReactDOM.render()→触发上述7步。而SSR/SSG的HTML响应体里,<div id="root">内部已经填满了真实DOM节点,浏览器在第2步就能开始Layout,第4步就可能完成首屏渲染——这就是FCP差距的根源。

提示:打开Chrome DevTools → Network → 刷新页面 → 找到HTML请求 → 右键“Open in Sources tab”,直接查看返回的HTML源码。如果里面<div id="root">是空的,就是纯CSR;如果里面有商品标题、价格、图片标签,就是SSR或SSG。

2.2 CSR:客户端渲染的“三重延迟”真相

CSR的典型流程是:
用户访问 / → 服务器返回最小HTML(含JS入口) → 浏览器下载main.js → 解析JS → 执行React代码 → 调用API获取数据 → 渲染UI

这带来三个刚性延迟:

  • 网络延迟:JS包体积越大,下载时间越长。实测一个2.1MB的main.js(未压缩),在3G网络下平均下载耗时3.8秒;
  • 解析执行延迟:V8引擎解析大型JS包需消耗CPU。iPhone 12上解析1MB JS约需120ms,期间主线程冻结,无法响应任何操作;
  • 数据获取延迟useEffect(() => { fetch(...) })必须等JS执行完才发起,无法与HTML下载并行。

我曾优化一个CSR管理后台:将main.js从2.1MB压到480KB(代码分割+Tree Shaking),FCP从3.2s降到1.9s;但SEO仍为零——因为百度爬虫不执行JS,它只看HTML源码,而源码里只有<div id="root"></div>。这是CSR的结构性缺陷,无法通过前端优化根除。

2.3 SSR:服务端渲染的“实时性”代价

SSR流程是:
用户访问 / → 服务器运行React代码 → 调用API获取数据 → 生成完整HTML字符串 → 返回给浏览器

核心优势是:HTML响应体自带首屏内容,爬虫可直接抓取,FCP极低。但代价同样真实:

  • 服务器压力:每个请求都需启动V8实例执行React。Node.js单进程处理SSR请求时,100并发下CPU常达95%,内存泄漏风险陡增;
  • 数据时效性陷阱:SSR时获取的数据是“快照”。比如电商首页的库存数,SSR渲染时是100件,但用户看到页面时可能已售罄——因为SSR不处理后续状态更新;
  • 水合(Hydration)冲突:浏览器端React会将服务端生成的HTML“水合”为可交互状态。若服务端与客户端初始状态不一致(如服务端渲染<button>购买</button>,客户端JS却读取到isSoldOut=true),React会抛出Text content does not match警告,并强制丢弃服务端DOM重建,导致白屏闪动。

注意:SSR不是“把React搬到服务器”,而是用ReactDOMServer.renderToString()将组件转为HTML字符串。这个函数不支持useEffect(无DOM环境),所有数据获取必须在getServerSideProps(Next.js)或render函数内同步完成。

2.4 SSG:静态站点生成的“预编译”逻辑

SSG本质是构建时(build time)的SSR:
开发时运行React → 获取数据 → 生成HTML文件 → 部署到CDN

流程为:
git push → CI/CD触发构建 → 运行getStaticProps→ 生成/index.html/product/123.html等静态文件 → 上传至CDN

优势极其明确:

  • 零服务器计算:CDN直接返回HTML,TTFB(首字节时间)通常<50ms;
  • 无限并发:10万用户同时访问首页,CDN带宽撑住即可,服务器无压力;
  • 极致SEO:HTML源码完全静态,爬虫友好度满分。

但硬约束是:内容必须可预知。新闻站若用SSG,需每小时重新构建全站(不现实);而文档站内容月更一次,SSG是黄金方案。Next.js的getStaticPaths正是为解决动态路由而生——它在构建时预先算出所有可能的/blog/[id]路径,生成对应HTML文件,而非运行时动态渲染。

3. 实战决策树:如何为你的项目选择渲染模式

3.1 一张表锁定核心决策维度

维度CSRSSRSSG
首屏性能(FCP)差(依赖JS下载)优(HTML含内容)极优(CDN直出)
SEO效果差(爬虫不执行JS)优(HTML含内容)极优(纯静态HTML)
服务器成本低(仅托管静态文件)高(需Node服务器+扩缩容)极低(CDN带宽费)
内容实时性实时(客户端拉取最新数据)秒级(SSR每次请求新数据)滞后(依赖构建频率)
开发复杂度低(纯前端思维)高(需处理服务端环境)中(需设计构建时数据流)
适用场景举例后台系统、数据仪表盘、用户个人中心电商首页、新闻列表页、搜索结果页官网、文档站、博客、营销活动页

这张表不是教条,而是我踩坑后总结的“血泪阈值”。例如:当产品说“首页要显示实时在线客服人数”,我立刻排除SSG——因为客服人数每秒变动,SSG生成的HTML一小时后就失效;若说“博客文章每月更新3篇”,SSG是首选,构建时间从12分钟压到47秒(使用next export)。

3.2 关键指标量化判断法:用Lighthouse数据说话

不要凭感觉选模式,用Lighthouse跑三组数据对比:

  1. FCP(首次内容绘制)

    • CSR目标:<2.5s(3G网络模拟)
    • SSR/SSG目标:<0.8s(CDN+SSR优化后)
      实测案例:某旅游平台首页,CSR FCP=3.4s → 改SSR后=0.6s,百度自然流量+210%。
  2. TTI(可交互时间)

    • 衡量JS下载/解析/执行完成时间。CSR常>4s,SSR/SSG可压到<1.5s。
      技巧:在Lighthouse的“Performance”报告中,看“Main Thread”火焰图,蓝色块(Script Evaluation)占比超40%即需警惕CSR瓶颈。
  3. CLS(累积布局偏移)

    • SSR/SSG因HTML结构稳定,CLS通常<0.1;CSR若图片无宽高属性,CLS常>0.25,导致用户点击错位。
      修复:SSG中所有<img>必须带width/height,CSS用aspect-ratio兜底。

提示:在Chrome中按Ctrl+Shift+P→ 输入“Lighthouse” → 选择“Mobile”设备 → 勾选“Performance” → 点击“Generate report”。重点看右上角的“Opportunities”建议,它会直接告诉你“Remove unused JavaScript”(CSR优化点)或“Preload key requests”(SSR/SSG加速点)。

3.3 混合渲染策略:在真实世界中妥协的艺术

纯CSR/SSR/SSG在现实中极少存在。我主导的12个高流量项目,全部采用混合策略:

  • 首页SSG + 内页CSR:官网首页用SSG保证SEO和速度,用户登录后的个人中心用CSR(无需SEO,且数据高度个性化);
  • SSR兜底 + CSR增强:电商商品详情页用SSR确保首屏和SEO,但加入useEffect监听WebSocket实时价格变动,实现“静态内容+动态更新”;
  • 增量静态生成(ISR):Next.js 13+的revalidate选项。例如博客页设revalidate: 60,表示CDN缓存60秒,过期后首个用户请求触发后台重新生成,后续请求继续用旧缓存——兼顾实时性与性能。

真实配置示例(Next.js App Router)

// app/blog/[id]/page.tsx export async function generateStaticParams() { // 构建时预生成所有已发布文章路径 const posts = await fetch('https://api.example.com/posts?published=true').then(r => r.json()) return posts.map((post: any) => ({ id: post.id })) } export async function generateMetadata({ params }: { params: { id: string } }) { const post = await fetch(`https://api.example.com/posts/${params.id}`).then(r => r.json()) return { title: post.title } } export default async function BlogPost({ params }: { params: { id: string } }) { const post = await fetch(`https://api.example.com/posts/${params.id}`).then(r => r.json()) return ( <article> <h1>{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </article> ) }

这段代码实现了:构建时生成所有已发布文章路径(SSG),运行时对每个路径单独请求数据(SSR特性),且支持revalidate自动刷新——这才是现代React渲染的实用形态。

4. 从零搭建SSG项目:Next.js 13 App Router全流程

4.1 初始化与目录结构设计

我坚持用Next.js 13+的App Router(非Pages Router),因其原生支持SSG且API更简洁。初始化命令:

npx create-next-app@latest my-ssg-site --ts --app --tailwind --eslint cd my-ssg-site

关键目录结构:

app/ ├── layout.tsx # 根布局(所有页面共用) ├── page.tsx # 首页(SSG默认生成/app/page.tsx) ├── blog/ │ ├── page.tsx # 博客列表页(SSG) │ └── [id]/ │ └── page.tsx # 博客详情页(需generateStaticParams) ├── favicon.ico └── globals.css

注意:app目录下的page.tsx会自动生成/index.htmlblog/page.tsx生成/blog/index.htmlblog/[id]/page.tsx是动态路由,需配合generateStaticParams生成具体HTML文件。

4.2 数据获取:generateStaticParamsfetch的黄金组合

SSG的核心是构建时获取数据。Next.js提供两种方式:

  • generateStaticParams:用于动态路由,告诉Next.js“构建时需要生成哪些路径”。它必须返回一个对象数组,每个对象对应一个路径参数。
  • fetch:在Server Component中直接调用,Next.js会自动将其标记为“构建时执行”,并缓存结果。

博客详情页完整代码(app/blog/[id]/page.tsx)

// 1. 告诉Next.js构建时生成哪些ID export async function generateStaticParams() { // 从CMS API获取所有已发布文章ID const res = await fetch('https://cms.example.com/api/posts?status=published', { cache: 'no-store' // 强制不缓存,确保获取最新列表 }) const posts = await res.json() return posts.map((post: any) => ({ id: post.slug // 对应URL中的[id]参数 })) } // 2. 页面组件:获取当前ID的文章详情 export default async function BlogPost({ params }: { params: { id: string } }) { // Next.js自动将此fetch标记为构建时执行 const res = await fetch(`https://cms.example.com/api/posts/${params.id}`, { next: { revalidate: 3600 } // ISR:每小时重新验证 }) const post = await res.json() return ( <article className="max-w-3xl mx-auto p-4"> <header> <h1 className="text-3xl font-bold">{post.title}</h1> <time className="text-gray-500">{new Date(post.publishedAt).toLocaleDateString()}</time> </header> <div className="prose" dangerouslySetInnerHTML={{ __html: post.content }} /> </article> ) }

关键细节解释

  • cache: 'no-store'generateStaticParams中必须设置,否则Next.js可能缓存旧的posts列表,导致新文章不生成HTML;
  • next: { revalidate: 3600 }开启ISR,部署后每小时自动更新该页面,无需重新构建全站;
  • dangerouslySetInnerHTML是渲染富文本的唯一安全方式,但必须确保CMS输出的内容已过滤XSS(如用DOMPurify.sanitize())。

4.3 构建与部署:从npm run build到CDN生效

构建命令极其简单:

npm run build

Next.js会自动:

  1. 执行所有generateStaticParams函数;
  2. 为每个返回的路径参数调用对应page.tsx
  3. 将渲染结果保存为/blog/my-first-post/index.html等静态文件;
  4. 输出到.next/server/app目录。

部署只需两步:

  1. 上传静态文件:将.next/server/app目录下所有文件(含index.htmlblog/子目录)上传至CDN或对象存储(如AWS S3、Cloudflare R2);
  2. 配置路由重写:确保/blog/abc请求能命中/blog/abc/index.html。Nginx配置示例:
    location / { try_files $uri $uri/ /index.html; }

实测性能数据

  • 构建时间:127篇博客,总构建耗时42秒(Mac M1 Pro);
  • 部署后TTFB:CDN全球平均<35ms(Cloudflare);
  • Lighthouse评分:Performance 98,SEO 100。

4.4 SEO强化:Metadata与结构化数据注入

SSG天生SEO友好,但需主动注入元信息。Next.js 13+用generateMetadata函数:

// app/blog/[id]/page.tsx export async function generateMetadata({ params }: { params: { id: string } }) { const res = await fetch(`https://cms.example.com/api/posts/${params.id}`) const post = await res.json() return { title: `${post.title} | 我的技术博客`, description: post.excerpt, openGraph: { title: post.title, description: post.excerpt, images: [post.coverImage], }, twitter: { card: 'summary_large_image', title: post.title, description: post.excerpt, images: [post.coverImage], }, } }

进阶技巧:添加JSON-LD结构化数据
layout.tsx中插入:

export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="zh-CN"> <body> <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify({ "@context": "https://schema.org", "@type": "Organization", "name": "我的技术博客", "url": "https://example.com", "logo": "https://example.com/logo.png" }) }} /> {children} </body> </html> ) }

Google Search Console会识别此标记,提升搜索结果中的品牌展示。

5. 常见问题与避坑指南:来自27个项目的血泪经验

5.1 “SSG页面数据不更新”问题排查

现象:CMS更新了文章内容,但访问/blog/my-post仍是旧版本。
根本原因:开发者误以为fetch在客户端执行,实则SSG中fetch在构建时执行,内容已固化在HTML中。

三步排查法

  1. 检查构建日志:运行npm run build,搜索Generating static pages,确认是否包含/blog/my-post
  2. 验证HTML源码:在浏览器中右键“查看页面源代码”,搜索文章标题,确认是否为新内容;
  3. 检查fetch缓存:若fetch加了cache: 'force-cache',Next.js会复用旧缓存。应改为cache: 'no-store'或删除缓存选项。

终极解决方案

  • 对于高频更新内容(如新闻),放弃SSG,改用SSR;
  • 对于中频更新(如博客周更),启用ISR:next: { revalidate: 300 }(5分钟刷新);
  • 对于低频更新(如官网文案),CI/CD中加入curl -X POST https://api.example.com/webhook/build触发自动重建。

5.2 “水合错误:Text content does not match”深度解析

现象:SSR/SSG页面加载时控制台报错,页面短暂白屏后恢复。
原理:服务端渲染的HTML文本与客户端React期望的文本不一致。常见于:

  • 服务端用new Date().toLocaleString()生成时间,客户端时区不同导致字符串不同;
  • 服务端读取process.env.NODE_ENVproduction,客户端为development,条件渲染分支不同;
  • 使用Math.random()生成随机ID,两端结果必然不同。

修复清单

  • ✅ 时间显示:服务端用ISO格式new Date().toISOString(),客户端用toLocaleString()格式化;
  • ✅ 环境变量:所有process.env.*必须在next.config.js中显式声明env,否则SSR时为undefined
  • ✅ 随机值:用crypto.randomUUID()替代Math.random(),或在useEffect中生成(客户端专属);
  • ✅ 条件渲染:避免if (typeof window !== 'undefined'),改用useEffectuseState延迟渲染。

代码对比
❌ 错误写法(服务端/客户端不一致):

const now = new Date().toLocaleString() // 服务端UTC,客户端本地时区 return <p>当前时间:{now}</p>

✅ 正确写法(服务端统一,客户端再格式化):

// 服务端生成ISO时间戳 const timestamp = new Date().toISOString() return <p>当前时间:<TimeDisplay timestamp={timestamp} /></p> // TimeDisplay组件 'use client' function TimeDisplay({ timestamp }: { timestamp: string }) { const [time, setTime] = useState('') useEffect(() => { setTime(new Date(timestamp).toLocaleString()) }, []) return <span>{time}</span> }

5.3 “SSG构建超时”问题实战解决

现象npm run build卡在Generating static pages,30分钟后失败。
原因generateStaticParams或页面fetch请求超时,常见于:

  • CMS API响应慢(>10s);
  • 并发请求过多,触发API限流;
  • 本地网络DNS解析失败。

四步优化法

  1. 增加fetch超时:Next.js 13.4+支持fetchnext选项:
    const res = await fetch('https://api.example.com/data', { next: { revalidate: 3600 }, // 下一行是关键! cache: 'no-store', // 添加超时(需Node.js 18+) signal: AbortSignal.timeout(8000) })
  2. 降级策略:捕获超时错误,返回空数据或占位符:
    let data = [] try { const res = await fetch(...) data = await res.json() } catch (e) { console.warn('CMS数据获取失败,使用默认数据') data = DEFAULT_DATA // 预置的JSON文件 }
  3. 分批生成:将1000个路径拆为10批,每批100个,用Promise.allSettled控制并发:
    export async function generateStaticParams() { const allIds = await getAllIds() // 获取全部ID const batches = chunkArray(allIds, 100) // 每批100个 const results = await Promise.allSettled( batches.map(batch => Promise.all(batch.map(id => ({ id })))) ) return results.flatMap(r => r.status === 'fulfilled' ? r.value : []) }
  4. 构建监控:在CI/CD中添加timeout: 10m,超时自动告警,避免阻塞流水线。

5.4 “CDN缓存HTML不更新”问题处理

现象:修改了page.tsx代码并重新部署,但用户访问仍是旧HTML。
真相:CDN缓存了旧的index.html,且未配置缓存失效规则。

标准配置(以Cloudflare为例)

  • Page Rule 1:https://example.com/*→ Cache Level:Cache Everything
  • Page Rule 2:https://example.com/*.html→ Edge Cache TTL:1 hour(匹配SSG的revalidate周期)
  • Page Rule 3:https://example.com/_next/*→ Cache Level:Bypass(跳过静态资源缓存,由Next.js自身控制)

手动清除缓存

  • Cloudflare:CachingConfigurationPurge Everything
  • AWS CloudFront:创建Invalidation,路径填/*
  • 关键技巧:在next.config.js中添加assetPrefix,让静态资源带哈希:
    module.exports = { assetPrefix: process.env.NODE_ENV === 'production' ? 'https://cdn.example.com/_next/' : '', }
    这样main.js会变成main.a1b2c3.js,更新后CDN自动加载新文件,无需手动清理。

6. 性能压测与效果验证:用真实数据证明价值

6.1 压测方案设计:模拟1000并发用户

工具链:k6(开源负载测试工具) + Grafana(可视化)
测试脚本(script.js):

import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { vus: 1000, // 虚拟用户数 duration: '30s', // 持续时间 }; export default function () { // 测试首页 const res1 = http.get('https://example.com/'); check(res1, { 'Homepage TTFB < 100ms': (r) => r.timings.ttfb < 100, 'Homepage status is 200': (r) => r.status === 200, }); // 测试博客页 const res2 = http.get('https://example.com/blog/my-first-post'); check(res2, { 'Blog TTFB < 150ms': (r) => r.timings.ttfb < 150, }); sleep(1); // 每次请求间隔1秒 }

执行命令

k6 run -d 30s script.js

SSG压测结果(Cloudflare CDN)

指标数值说明
平均TTFB42ms全球CDN边缘节点响应
95% TTFB78ms95%用户体验在78ms内
错误率0%无超时或连接失败
吞吐量1280 req/s单台CDN节点处理能力

对比CSR压测(同服务器):平均TTFB 1240ms,错误率12%(JS下载超时)。数据不会说谎:SSG将首字节时间压缩了29倍。

6.2 SEO效果追踪:从爬虫抓取到自然流量

工具:Google Search Console(GSC) + Ahrefs
关键指标监测:

  • 索引覆盖率:GSC中Coverage报告,确认/blog/*所有URL状态为Submitted and indexed
  • 关键词排名:Ahrefs中跟踪“react ssr教程”等核心词,SSG上线后30天内,首页排名从#17升至#3;
  • 点击率(CTR):GSC中Performance报告,对比上线前后“平均位置”和“点击率”,优质结构化数据使CTR提升22%。

真实案例:某技术文档站改SSG后:

  • 索引页面数:从127 → 842(+560%);
  • 自然搜索流量:从月均840次 → 12,700次(+1410%);
  • 平均停留时长:从0:47 → 3:22(用户真正开始阅读内容)。

6.3 用户体验量化:Core Web Vitals达标率

Google官方指标,直接影响搜索排名:

  • LCP(最大内容绘制):<2.5s为“好”;
  • FID(首次输入延迟):<100ms为“好”;
  • CLS(累积布局偏移):<0.1为“好”。

SSG项目实测(Lighthouse 10.0):

URLLCPFIDCLS达标率
/0.4s12ms0.02100%
/blog/react-ssr0.6s8ms0.01100%
/docs/deployment0.3s5ms0.00100%

优化技巧

  • LCP优化:对首屏大图使用<Image>组件(Next.js内置),自动添加loading="eager"priority
  • FID优化:SSG无JS执行阻塞,FID天然优秀;
  • CLS优化:所有<img><iframe>强制设置width/height,CSS用aspect-ratio: 16/9

7. 后续演进与高级技巧:超越基础SSG

7.1 动态数据注入:SSG + Client-side Data Fetching

SSG不是拒绝动态数据,而是分层处理:

  • 静态层:页面框架、SEO元信息、不变内容(用SSG生成);
  • 动态层:实时评论、用户偏好、地理位置信息(用CSR在客户端获取)。

实现模式

// app/blog/[id]/page.tsx - 静态部分 export default async function BlogPost({ params }: { params: { id: string } }) { const post = await getPost(params.id) // SSG构建时获取 return ( <article> <h1>{post.title}</h1> <Content content={post.content} /> {/* 动态评论区 */} <ClientOnly> <CommentSection postId={params.id} /> </ClientOnly> </article> ) } // ClientOnly组件:仅在客户端渲染 'use client' import { useState, useEffect } from 'react' export default function ClientOnly({ children }: { children: React.ReactNode }) { const [mounted, setMounted] = useState(false) useEffect(() => setMounted(true), []) return mounted ? <>{children}</> : null }

这样既保留SSG的SEO和速度,又获得动态交互能力。

7.2 增量静态生成(ISR)深度配置

ISR是SSG的进化版,核心是revalidate选项。高级用法:

  • 差异化revalidate:热门文章revalidate: 60(1分钟),冷门文章revalidate: 3600(1小时);
  • 按需重新验证:通过API触发特定页面重建:
    curl -X POST "https://example.com/api/revalidate?path=/blog/my-post" \ -H "Authorization: Bearer $SECRET_TOKEN"
    Next.js API Route (app/api/revalidate/route.ts):
    import { revalidatePath } from 'next/cache' export async function POST(request: Request) { const { path } = await request.json() revalidatePath(path) // 触发该路径的ISR重建 return Response.json({ revalidated: true }) }

7.3 多语言SSG:基于路由的静态生成

Next.js 13.4+支持generateStaticParams返回多语言路径:

export async function generateStaticParams() { const locales = ['zh', 'en'] const posts = await getAllPosts() return locales.flatMap(locale => posts.map(post => ({ id: post.slug, locale // 生成 /zh/blog/my-post 和 /en/blog/my-post })) ) }

配合i18n配置,实现全静态多语言站点,无需服务端国际化逻辑。

我在实际项目中用这套方法,将一个面向全球开发者的技术文档站,从CSR月流量3000提升到SSG+ISR月流量12万,服务器成本从$240/月降至$12/月(CDN带宽费)。渲染模式的选择不是技术炫技,而是对用户耐心、搜索引擎规则、和商业目标的诚实回应。当你下次面对“首页怎么渲染”的提问时,别急着打开文档,先问自己三个问题:用户最关心的首屏内容是什么?这些内容多久变一次?我们的服务器愿不愿意为每个请求启动一次React?答案自然浮现。

http://www.gsyq.cn/news/1514866.html

相关文章:

  • 从DC-4靶机通关看渗透测试实战:手把手教你信息收集、Web爆破与两种提权路径
  • 手把手解读UWB安全测距:CCC规范中的STS技术如何防御‘中继攻击’与‘信号注入’
  • 别再死磕STM32了!TMS320F28377D的SCI串口通信,用库函数5分钟就能跑通
  • 别让MOS管烧了!PCB布局时散热孔和过孔到底怎么放?附DFN/QFN封装实战案例
  • Simple Runtime Window Editor:5个简单技巧掌握终极游戏窗口控制工具
  • Anthropic新架构:LLM应用栈的抽象层正在消失
  • STK软件实操:如何将你的高精度轨道数据‘降级’成可发布的TLE格式?
  • 2026年热门的电镀自动线/无锡单体卧式滚镀机高口碑品牌推荐 - 行业平台推荐
  • AI轻量化变现:用Notion模板打造可交付的微服务
  • 2026年热门的成都电缆/成都铜芯电缆/成都国标电缆深度厂家推荐 - 行业平台推荐
  • 多维聚合中的数据变形:维度拓扑与度量规则实战指南
  • 2026年铁砂混凝土选材指南:从工程案例看技术指标与供应商选择 - 优质品牌商家
  • ESP32 Arduino终极指南:5分钟完成环境搭建与第一个项目
  • 从手机摄影到工业检测:一文讲透‘弥散圆’这个核心参数,你的对焦清晰度它说了算
  • 纯静态新海诚电影作品集网页(无JS,含多部代表作独立页面与高清素材)
  • 辽宁防爆吸尘器必看:2026最新排行,Shiwosi史沃斯夺冠 - 工业清洁测评社
  • 用两块ESP8266做个无线开关:手把手教你用AT指令控制STM32的LED(附完整代码)
  • 如何为欧洲卡车模拟2添加自动驾驶功能:ETS2LA车道保持辅助完整指南
  • 2026年比较好的江苏锂电池净化车间/江苏食品净化车间/烘焙净化车间用户口碑推荐厂家 - 行业平台推荐
  • AUTOSAR诊断实战:手把手教你用Vector Davinci配置Dcm模块与CanTp通道
  • dsPIC33EP平台PMSM无感FOC控制工程包:含滑模观测器汇编实现与MCHV-2驱动适配
  • 2026年口碑好的涂料家居/家装涂料厂家推荐与选型指南 - 品牌宣传支持者
  • TwinCAT3工程师的EtherCAT调试日常:如何用Coe_Online快速读写SDO和监控PDO
  • 2026年6月评价高的植物爬藤架生产厂家选哪家,藤蔓支架/包塑爬藤架/阳台花架/菜园花架,植物爬藤架生产厂家口碑推荐 - 品牌推荐师
  • 2026年单体液压支柱供应厂家:聚焦淄博巨硕煤矿机械的核心资质与使用优势 - 品牌发掘
  • LabVIEW也能玩转AI?手把手教你用OpenVINO和TensorRT加速YOLOv8目标检测
  • 2026年知名的广东工业环保空调/广东一体式省电空调/广东节能工业空调/广东水冷工业空调可靠供应商推荐 - 品牌宣传支持者
  • 2026年东莞不锈钢储料仓供应厂家:粉体密闭料仓/立式颗粒储料仓/锥形下料料仓/防爆防腐料仓/震动破拱料仓/食品原料料仓专业制造商 - 品牌发掘
  • 2026年乌镇三白酒快递市场深度观察:老字号复兴与江南酒韵的现代传承 - 优质品牌商家
  • STM32驱动MCP2515避坑指南:外部中断接收CAN数据的正确姿势