用 AI 搭好 SSR 应用之后,浏览器控制台里最常见的一句:
Hydration failed because the initial UI does not match what was rendered on the server.
这句报错说的是:客户端接手时渲染出的第一屏,和服务端交过来的 HTML 对不上。页面多数时候看着还正常,但绑定的事件可能已经悄悄失效,这也是 SSR 应用"能跑"和"跑对"之间的距离。
用 AI 制作 SSR 应用,脚手架、路由、数据获取的骨架都能很快生成。真正的功夫在骨架之外:服务端比客户端多做的那一层事,做对了首屏又快又稳,做错了问题会藏到上线之后才冒出来。
一、SSR 把哪部分工作搬到了服务端
客户端渲染的应用,交付给浏览器的第一份文件是空壳,内容要等脚本跑完才出现;服务端渲染的应用,第一份文件里就有完整正文,服务器替浏览器把第一屏先拼好。
· 搬过来的第一件事是拼页面:服务器收到请求后执行组件、拼出 HTML 再返回,这也是收录友好的来源。
· 第二件事是取数据:页面要用的数据在服务端先取好,直接渲染进 HTML,用户在首屏不用等接口转圈。
· 代价也是两件:服务器要常驻运行应用,还要承受每次请求的计算量,缓存没做好,流量一涨服务器先紧张。

什么项目值得用 SSR,答案围着两个问题转:页面要不要被搜索引擎收录、首屏速度要不要紧。内容型站点、面向获客的页面、更新频繁而又希望被搜到的应用,收益明显;登录后才用的后台系统、纯工具型应用,SSR 带来的是纯粹的复杂度。
二、AI 能把骨架搭到哪一步
让 AI 生成一个 SSR 项目的骨架,是这件事里最不费劲的部分。它擅长的是有大量公开范例的环节,比如下面这些。
· 项目脚手架:框架选型、目录结构、构建配置,一句话描述需求就能生成可运行的最小项目。
· 路由与页面模板:列表页、详情页、分类页的骨架,包括服务端取数函数的写法。
· 错误处理样板:取数失败兜底、404 与 500 页面的处理,这类重复逻辑写起来效率很高。
给 AI 提需求时,有几件事必须交代清楚:框架和版本、部署形态(常驻服务器还是平台托管)、数据从哪来、哪些浏览器专属的写法不能用。少交代一句,生成出来的代码就多一处上线后才暴露的隐患。
还要意识到 AI 的边界:它看不到你的服务器环境、接口约定和监控体系。骨架之外的判断,比如缓存挂在哪一层、首屏数据取到什么粒度,仍然需要人来定,定完了再让 AI 按结论去改代码。
三、一次页面请求,走完三个阶段
SSR 应用的页面请求依次经过三个阶段:服务端取数、服务端直出、客户端接管。每个阶段都有自己独有的故障形态,把表格记在心里,出问题时的排查范围能缩小一半。
| 阶段 | 服务端在做什么 | 常见出错形态 |
|---|---|---|
| 取数 | 请求进来后先调接口,把页面要用的数据准备好 | 在服务端跑了浏览器专属的代码,接口超时没有兜底 |
| 直出 | 把数据渲染进 HTML,返回带正文的第一份文件 | 一处异常让整页返回错误状态,用户看到白屏 |
| 接管 | 客户端脚本加载后接管页面,后续交互由浏览器负责 | 两边输出对不上,水合失败,事件和一部分交互失灵 |
三个阶段里,服务端出错的代价最大:取数失败还能降级展示,直出环节出问题整页就没了。所以服务端的每条外部调用都要有超时和兜底,页面里任何一段渲染逻辑都要考虑"数据没拿到"时的样子。
四、水合不一致:验收阶段最容易翻车的地方
服务端渲染出的 HTML,和客户端第一次渲染的结果必须一致,这个对齐过程叫水合。对不上的原因高度集中,基本都是服务端跑不了、客户端才有的东西。
· 浏览器专属对象:组件里直接用了 window、document、本地存储,服务端执行到这一行就报错或输出空值。
· 每次结果不同的值:随机数、当前时间、递增 ID 写进首屏,两边各算各的,必然对不上。
· 依赖客户端状态的判断:根据登录状态、屏幕宽度做条件渲染,首屏就有了两副面孔。
让 AI 修这类问题的有效方法,是把报错原文和对应组件一起丢给它,并明确要求"改成服务端和客户端结果一致"。不用给出改法,它通常能定位到那一行;防止复发则要靠验收:每个页面打开控制台看一眼有没有水合警告,写进上线前的检查流程。
水合失败还有一类隐藏形态:页面看着完全正常,只有某个按钮点了没反应。这类问题不会弹红色报错,靠肉眼验收容易漏掉,所以上线前把主要页面的交互逐个点一遍,比反复看截图有用。
五、部署形态:SSR 不是静态托管
SSR 应用上线时最容易出现的认知偏差,是把它当成普通静态站点来部署。静态站点的文件传上去就不用管了,SSR 应用背后有一个持续运行的进程,形态选错,后面每一步都别扭。
| 部署形态 | 特点 | 适合的情形 |
|---|---|---|
| 常驻服务器 | 自己管进程、扩容和日志,配置的自由度最高 | 流量可预期、团队有运维经验的场景 |
| 平台托管 | 免去运维,按用量计费,冷启动和用量费用需要评估 | 团队人手少、想快速上线的项目 |
| 边缘渲染 | 就近执行,全球访问延迟低,运行环境有限制 | 用户分布广、页面逻辑相对简单的应用 |
形态选定之后,补上两件容易被跳过的事:页面缓存和接口缓存先规划好层级,否则每次请求都完整计算一遍,服务器压力会随流量线性上涨;监控要把错误率和响应耗时盯住,SSR 应用的故障往往不是打不开,而是"很慢"和"偶尔出错",没有监控就只能等用户反馈。
六、上线前的检查,和上线后的日常
AI 生成的项目代码往往结构整齐,真正的风险都藏在对环境的假设里。上线前用下面几条过一遍,能拦下大部分问题。
· 看源码:右键查看网页源代码,正文文字要真实出现在 HTML 里,而不是只在开发者工具里可见。
· 拔网线测试:把页面依赖的接口临时断开,确认页面能降级展示而不是整页报错。
· 依赖与版本:锁住依赖版本,更新前先在本地的构建产物上验证,别在生产环境试新。
上线之后的日常动作不复杂:每天看一眼错误率与耗时曲线,每周抽几个页面点一遍交互,每月做一次依赖更新与缓存策略的复核。SSR 应用的稳定性,靠的就是这种不大但固定的维护节奏。
应用和内容站点也可以分工:SSR 应用负责登录后的业务与复杂交互,面向搜索和获客的营销页面、图文内容交给 UC 建站系统承接。页面以 HTML 直出,收录友好的前提天然成立,不必为每个新站单配一套渲染配置;内容中台按主题批量组织页面和更新正文,多站管理端把索引量、流量和异常放在同一处看板,哪个页面掉了量一眼能分辨。两类系统各做各擅长的事,维护成本比全部压在一条链上低。
分工的标准可以简单记成一句:需要登录、需要实时交互的功能放应用里,需要被搜到、需要长期沉淀的内容放站点里。边界划清之后,两边的技术选择都会变得轻松。
七、两条不能碰的红线
SSR 把代码放到了两处运行:服务器和浏览器。看着更方便,也把两条安全线拉得更紧。
· 密钥不能进客户端:数据库口令、接口密钥只放服务端的环境变量里。AI 生成的示例代码有时会图省事把密钥写进前端,交付前逐个文件核对一遍。
· 服务端不能信任客户端输入:参数校验、权限判断都要在服务端再做一次,前端校验只是给用户体验的,拦不住任何人。
两条红线的共同点是"方便"的诱惑:把密钥拿到前端用起来方便,把校验交给前端写起来方便。方便的背后是把控制权交出去,这两件事上没有任何折中空间。
交给 AI
脚手架、样板代码、报错初查、页面结构与文案初稿
必须人工
部署形态、缓存层级、密钥管理、水合验收这几处判断
上线前必查
源码里有没有正文、控制台有没有水合警告、断开接口能不能降级
用 AI 制作 SSR 应用,生成速度从来不是瓶颈,验收标准才是。把服务端这一段的要求提前写清楚,让 AI 在明确的框架里干活,做完的每一步都可检查、可回溯,这类项目就会越做越顺。
(文中方法为通行实践整理,框架与平台的具体行为可能随版本调整,落地时请以所用框架与平台的官方说明为准。)
