必须用 parse5 解析 html 并操作 ast 插入 script,禁用字符串替换;状态需用 type="application/json" 的 script 标签内嵌,id 唯一、textcontent 写入、json 双重转义;hydration 要求服务端与客户端 dom 完全一致,数据获取须独立于模板。

服务端注入状态必须用 parse5 解析 HTML,不能字符串替换
直接 htmlStr.replace('', '<script>...</script>') 会出错——遇到 、<!-- comment --> 或含 <img src="<script>"> 的属性时,正则或字符串操作会截断、错位甚至引入 XSS。浏览器解析 HTML 是基于 token 流的,不是纯文本。
正确做法是用标准 HTML5 解析器转 AST:
-
parse5.parse()得到 document 对象,遍历找到节点 - 用
parse5.treeAdapters.default.appendChild()插入新<script></script>节点(不是 innerHTML) - 确保插入位置在
子节点最前,避免干扰 hydration 顺序
<script type="application/json"></script> 是唯一推荐格式
把状态挂到 window.__INITIAL_STATE__ 看似简单,但极易被后续脚本覆盖、误删,或因 JS 加载失败导致 hydration 中断。Next.js、Remix 等框架统一采用 DOM 内嵌 JSON 的方式,核心就是这个标签:
- 必须设
type="application/json",不执行、不污染全局作用域 - 必须加
id="__NEXT_DATA__"(或类似约定 ID),方便客户端精准定位 - 内容只能用
textContent写入,禁止用innerHTML—— 否则含的数据会提前终止解析
示例写法:
<script type="application/json" id="__NEXT_DATA__">{"props":{"pageProps":{}}}</script>
JSON 序列化必须双重转义,不能只靠 JSON.stringify()
JSON.stringify(state) 输出的字符串若含未编码的 '、"、,插入 script 标签后会被浏览器解析器当作标签闭合,导致截断。比如用户昵称是 Jack & Jill,不处理就会在 & 处中断。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
安全做法是:
- 先
JSON.stringify(),再对结果做 HTML 实体转义:.replace(/, '\u003c').replace(/>/g, '\u003e').replace(/'/g, '\u0027') - 更稳妥:用
serialize-javascript这类专为服务端设计的库,它自动处理 Unicode 控制字符、嵌套引号、终止标签等边界情况 - 绝对不要手动拼接字符串或信任模板引擎的“自动转义”——很多引擎只转 HTML 实体,不防
hydration 对齐要求 DOM 结构零差异
服务端渲染的 HTML 和客户端 hydration 时的 DOM 必须完全一致,差一个空格、少一个布尔属性(如 disabled 没写值)、多一个注释,React/Vue 都可能放弃复用而整棵重挂载。
关键控制点:
- 禁用模板引擎的自动空格压缩(如 EJS 的
不要换成) - 所有动态属性(
class、data-id)必须由模板原生支持条件拼接,而非 JS 字符串拼完传入 - 时间字段必须冻结为字符串(如
new Date().toISOString()),避免客户端 hydration 时时间戳不同引发 diff 误判 - 服务端和客户端必须使用同一套组件树生成逻辑,不能服务端用
renderToString,客户端用hydrateRoot却传入不同 props
最容易被忽略的是:服务端模板里混入 await 或 fetch,会导致数据获取与模板渲染耦合,既无法缓存,也无法 mock 测试——数据获取必须独立成函数,如 getServerSideData({ req, params })。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










