DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Svelte head 空节点变多

Svelte 页面卸载后 meta 消失,head 空文本节点仍按挂载积累,检查旧锚点清理缺口、5.57.0 修复及等待完整卸载的验收。

单页应用反复切换页面后,旧页面的 meta 已经移除,document.head 的子节点数量却仍在增长。查看新增节点,它们是没有内容的 Text 节点,不是重复的标题或样式。

Svelte 5.56.8 存在一个对应的清理缺口:客户端挂载 <svelte:head> 时创建的空文本锚点,没有进入该 head 分支的销毁范围。正式版 5.57.0 修正了它,5.57.2 也包含相应处理。

看 childNodes,不只看页面元素

页面组件可能只是正常声明:

<svelte:head>
  <meta name="description" content="当前页面说明" />
</svelte:head>

Svelte 除了插入可见的 head 内容,还需要一个锚点来确定插入位置。旧客户端创建空文本锚点时,它位于分支 effect 的节点范围之外;meta 等实际内容可以随分支卸载,锚点却没有一起被清理。

因此,只检查 document.head.children 或搜索重复 meta,可能看不到这项增长。Text 节点属于 childNodes,但不是元素节点。排查时应看节点类型、内容和创建位置,并确认增长跟页面组件的挂载次数有关。

不要把所有 head 节点增长都套入这个问题。第三方脚本、样式管理器或应用自己的标签插入逻辑,也可能保留节点;它们未必是 Svelte 创建的空文本锚点。

卸载完成后再比较

用项目已有的受控组件测试或导航流程,记录稳定状态下的 head 节点。挂载带 <svelte:head> 的页面,再完成卸载,等待框架的异步清理结束后比较。

使用 unmount 的测试应等待其完成。立刻连续调用挂载和卸载、还未等清理便统计差值,无法排除尚未结束的销毁过程。页面若有退出过渡,也要按实际过渡生命周期判断。

比较期间保留其他仍挂载页面的 head 内容。目标是确认已卸载分支没有继续留自己的锚点,不是要求整个 head 回到空状态,也不是要求浏览器进程的内存立刻下降。

正式修复把锚点纳入节点范围

已核对的正式实现,在非水合的 head 渲染分支中,把锚点设为该分支节点范围的末端。没有其他渲染节点时,它自己成为起点和末端。原来的 head effect 销毁逻辑便能连同这个末端一起移除。

项目可沿框架支持的兼容路径升级,再更新实际客户端产物。若应用已经使用含修复的版本,仍看到相同增长,应回查真正创建和保留节点的代码,而不是继续假定升级没有执行。

不应定时删除 document.head 中的所有空节点来修复它。当前仍挂载的组件也可能需要这些锚点,直接清掉会破坏后续插入和更新。手工清理全部 meta、style 或 hydration 标记同样不能代替框架的生命周期修复。

保留正常的 head 更新

修复后,反复挂载并完整卸载同一个测试分支,确认不再按每次挂载积累空锚点。再核对正常导航时的 title、meta 更新,以及其他还在使用的 head 内容没有被错误移除。

初次 SSR 水合和后续客户端挂载走的条件不同,也应分别保留验收。节点数量稳定只证明这条清理路径正确;如果应用还有其他引用链泄漏,需要继续按各自保留者排查。