xLog 修补小记 —— 纯文本节点引发的应用崩溃

背景

在之前就发现过本平台一个颇为微妙的 bug：
当使用 Chrome 内建的翻译工具进行全局翻译时，页面会出现错误，具体提示为

应用程序错误：发生了客户端异常（有关详细信息，请参阅浏览器控制台）。

不过因为平台本身具有良好的 i18n，加上也并无过于复杂的内容，极少会在相关页面使用全局翻译，也就没有多做关注。直到近日看到其他的小伙伴提起这个问题 https://github.com/Crossbell-Box/xLog/issues/229 ，勾起了好奇心，遂简单看看具体缘故。

探究

既然说了参阅控制台，那么就看看到底说了什么：

Copy
react-dom.production.min.js:189 DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89708)
at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89781)
at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89781)
at uK (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89833)
at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86503)
at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)
at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86495)
at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)
at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86692)
at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)

粗略扫一眼，嗯，看不出来。再看看，猜测应该是 React 内部爆出的错误。那么直接操起 Google，很轻易地就搜到了原因以及解决方案：https://github.com/facebook/react/issues/11538#issuecomment-390386520

问题在于 Google Translate 用包含翻译的 标签替换文本节点，而 React 保留了不在 DOM 树中的文本节点的引用。

而解决方案也堪称简单粗暴：

最简单的解决方法是使用 将那些文本节点包装起来，这样被 React 引用的节点即使其内容被替换为 标签，也会保留在 DOM 树中。

解决

有了原因和解决方案，那么只需要找到出错的地方修复即可。

xLog 的代码也不算少，直接去找也算是个大工程，所以为了定位，干脆用了个很粗暴的方案，使用二分法逐步在控制台删除元素。

运气颇好地，没用几下就找到了引起问题的地方：src/components/site/SiteFooter.tsx

Copy


&copy;{" "}
<UniLink href="/" className="hover:text-accent">
{site?.name}
</UniLink>{" "}
·{" "}
<Trans
i18nKey="powered by"
defaults={"Powered by <name/>"}
components={{
name: <LogoWithLink />,
}}
ns="site"
/>


大致两步搞定：

直接用 标签包裹住纯文本

修正 Trans 组件输出的结构：按照 https://react.i18next.com/latest/trans-component 所言修改对应语言文件中的字符串模板，然后在 components 字段中添加对应的 span 声明即可。

粗略看了下，没什么问题了，当然不排除没改干净的情况，遇到了再说吧。

总结

没啥可说的，多用 Google 就行 :_)