Note-31132-16

Token ID: 1

ERC-721 1 Transfers

Metadata

{
  "title": "xLog 修补小记 —— 纯文本节点引发的应用崩溃",
  "tags": [
    "post"
  ],
  "sources": [
    "xlog"
  ],
  "external_urls": [
    "https://zsakvo.xlog.app/textNode-cause-app-crash"
  ],
  "date_published": "2023-04-11T15:12:47.442Z",
  "content": "## 背景\n\n在之前就发现过本平台一个颇为微妙的 bug:\n当使用 Chrome 内建的翻译工具进行全局翻译时,页面会出现错误,具体提示为 \n\n> 应用程序错误:发生了客户端异常(有关详细信息,请参阅浏览器控制台)。\n\n不过因为平台本身具有良好的 i18n,加上也并无过于复杂的内容,极少会在相关页面使用全局翻译,也就没有多做关注。直到近日看到其他的小伙伴提起这个问题 https://github.com/Crossbell-Box/xLog/issues/229 ,勾起了好奇心,遂简单看看具体缘故。\n\n\n\n## 探究\n\n既然说了参阅控制台,那么就看看到底说了什么:\n\n```javascript\nreact-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.\n    at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89708)\n    at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89781)\n    at e (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89781)\n    at uK (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:89833)\n    at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86503)\n    at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)\n    at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86495)\n    at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)\n    at uq (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86692)\n    at uQ (https://xlog.xlog.app/_next/static/chunks/framework-9e494f4410668bc3.js:9:86382)\n```\n粗略扫一眼,嗯,看不出来。再看看,猜测应该是 React 内部爆出的错误。那么直接操起 Google,很轻易地就搜到了原因以及解决方案:https://github.com/facebook/react/issues/11538#issuecomment-390386520\n\n> 问题在于 Google Translate 用包含翻译的 `<font>` 标签替换文本节点,而 React 保留了不在 DOM 树中的文本节点的引用。\n\n而解决方案也堪称简单粗暴:\n\n> 最简单的解决方法是使用 `<span>` 将那些文本节点包装起来,这样被 React 引用的节点即使其内容被替换为 `<font>` 标签,也会保留在 DOM 树中。\n\n\n## 解决\n\n有了原因和解决方案,那么只需要找到出错的地方修复即可。\n\nxLog 的代码也不算少,直接去找也算是个大工程,所以为了定位,干脆用了个很粗暴的方案,使用二分法逐步在控制台删除元素。\n\n运气颇好地,没用几下就找到了引起问题的地方:`src/components/site/SiteFooter.tsx`\n\n```javascript\n<div className=\"max-w-screen-md mx-auto px-5 py-10 text-xs flex justify-between\">\n  <div className=\"font-medium text-base\">\n    &copy;{\" \"}\n    <UniLink href=\"/\" className=\"hover:text-accent\">\n      {site?.name}\n    </UniLink>{\" \"}\n    ·{\" \"}\n    <Trans\n      i18nKey=\"powered by\"\n      defaults={\"Powered by <name/>\"}\n      components={{\n        name: <LogoWithLink />,\n      }}\n      ns=\"site\"\n    />\n</div>\n```\n\n大致两步搞定:\n1. 直接用 `<span>` 标签包裹住纯文本\n2. 修正 `Trans` 组件输出的结构:按照 https://react.i18next.com/latest/trans-component 所言修改对应语言文件中的字符串模板,然后在 `components` 字段中添加对应的 `span` 声明即可。\n\n粗略看了下,没什么问题了,当然不排除没改干净的情况,遇到了再说吧。\n\n## 总结\n\n没啥可说的,多用 Google 就行  :_)\n",
  "attributes": [
    {
      "value": "textNode-cause-app-crash",
      "trait_type": "xlog_slug"
    }
  ]
}