Svelte 嵌套边界水合报 startsWith:检查起始注释被替代
多出的元素占据边界起始注释位置时,Svelte 5.57.1 可能抛 startsWith 异常并显示父级错误内容。5.57.2 修正了这条不匹配恢复路径。
SSR 页面在客户端接管时突然显示错误边界,报 Cannot read properties of undefined (reading 'startsWith');移除水合前插入的一个元素,页面又正常。如果额外节点恰好占据嵌套 <svelte:boundary> 的起始注释位置,应检查旧水合代码是否把元素当成了注释。
Svelte 5.57.1 有这条具体表现。正式 5.57.2 已列出嵌套边界注释被意外节点替代时的恢复修正;5.57.3 的发布包也包含节点类型检查。这里针对水合结构不匹配被错误转成普通 TypeError,并不表示服务端 HTML 中所有差异都可以忽略。
意外节点改变了错误进入的路径
边界需要读取起始注释里的水合标记。旧路径直接读取 comment.data.startsWith(...),但当前位置若实际是 span 等元素,data 就是 undefined,于是抛出普通 TypeError。
上层边界有 failed 或 onerror 时,可能把这个异常当成应用渲染失败,显示自己的错误内容。它没有进入本应处理结构不匹配的水合信号路径。页面因此看似“业务组件报错”,实际诱因却是接管前 DOM 多了一个节点。
先比较服务器响应中的 HTML 与执行水合前的实际 DOM,确定节点何时出现。浏览器扩展、页面集成脚本都可能改动内容,但不能仅凭安装了扩展就认定它是根因;要确认多出的节点正好落在边界标记位置。业务组件自己抛出的 startsWith 错误仍需沿真实调用栈排查。
使用包含节点校验的正式版本
按框架兼容范围更新到包含修正的 Svelte 版本,并让客户端、服务端产物来自同一组依赖。5.57.3 的边界通过水合标记读取函数先检查节点是否为注释;遇到错误类型会发出不匹配警告并抛出专用水合信号,避免直接对 undefined 调用 startsWith。
该信号可以继续交给顶层 hydrate 处理。允许恢复时,恢复可能清空目标并重新挂载内容,不保证保留每一个原有 DOM 节点;显式设置 recover: false 的入口也不能同时期待自动恢复。自行封装水合入口时,应核对这项既有选择,而不是为了消除错误随意改变恢复策略。
能控制插入脚本时,让它避开 Svelte 管理的根节点,或按照集成约定在水合完成后操作自己的区域。不要手工伪造边界注释、删掉所有注释或在框架接管中途移动节点,这些做法会进一步破坏标记与内容的对应关系。
验收要覆盖无干扰的正常 SSR 页面,以及受控插入节点的原位置。前者应正常接管;后者在允许恢复时应走不匹配警告与恢复,不再因读取 startsWith 进入父级失败内容。再确认真正的业务错误仍由原有边界处理,不能用吞掉全部错误换取页面继续显示。


