DEBUG.WIKI
OnlineSIM:在线接收短信,虚拟号码租用
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →

Svelte 服务端错误页点重试没反应:检查 failed 边界水合

服务端已输出 failed snippet,客户端接管后 reset 却不重建内容。限定序列化失败边界,区分默认 SSR 整页错误与已销毁回调。

服务端已经输出 <svelte:boundary> 的 failed 内容,客户端接管后,重试按钮却没有反应,onerror 也没有拿到恢复回调。如果错误只发生在服务端、客户端本来可以正常渲染,应检查“以失败状态水合”的那条路径。

这条具体缺口出现在 Svelte 5.56.4、5.56.6。普通客户端刚发生的渲染错误不一定受影响;本题要求服务端 render 已提供 transformError,或框架已代为配置,使错误能序列化为 failed 标记;没有这项配置时,整次 SSR 失败并不是这里的失败边界水合路径。

失败水合给出的回调可能只是空函数

下面是应用已有失败边界中的恢复按钮形状,FlakyComponent 代表原业务组件:

<svelte:boundary>
  <FlakyComponent />
  {#snippet failed(error, reset)}
    <button onclick={reset}>重试</button>
  {/snippet}
</svelte:boundary>

旧的失败水合实现只恢复 failed snippet 的 HTML,并交给它一个空函数。它没有经过普通渲染错误的完整处理,因此 reset 看起来可以调用,却不会创建新的正常内容,也不会把有效 reset 交给 onerror。

先确认页面确实来自服务端 failed 标记,以及客户端加载的是对应产物。如果按钮事件本来没有绑定、水合整体已失败,或子组件在客户端仍持续抛同一个真实错误,应先沿那些可见错误处理;不能只因按钮没效果就认定命中空 reset。

正式恢复实现会重新渲染存活边界

已核对的正式 Svelte 5.57.3 在失败水合时创建真实 reset,并在微任务里调用 onerror,避免在水合期间同步修改状态。reset 清理失败内容,再走该边界正常渲染;旧版本中的空回调并不是需要应用自己补写的接口。

按框架兼容范围更新实际 Svelte 依赖,重新生成客户端与服务端资源,避免两边混用不同构建。没有必要全局禁用 SSR,或在按钮中硬刷新整页来掩盖客户端边界无法恢复的状态。

自己保存 reset 时,仍须让回调归属于产生它的边界。已销毁边界的旧回调不能继续用于新页面;每次失败提供的 reset 也不应被无条件重复调用。不要在 onerror 的同步执行过程中马上 reset,持续失败会变成错误恢复循环。

验收应让服务端在受控条件下失败并输出 failed snippet,而同一组件在客户端已满足成功条件。确认首次水合后收到 onerror 的错误与回调,用户触发一次 reset 后正常内容出现;再检查客户端真实错误仍能被边界处理。只测客户端自行抛错再恢复,没有覆盖服务端失败标记的水合分支。