win11 Emoji 渲染无限闪动(Twemoji CDN 问题)

问题描述

聊天消息中包含 emoji 时,页面进入无限闪动循环:emoji 短暂出现约 1 秒后消失,随后图片占位符与空白持续交替闪烁,整个页面无法正常使用。

复现步骤

  1. 发送或接收任意包含 emoji 的消息

  2. emoji 首次正常渲染约 1 秒(React useEffect 之前,浏览器原生渲染)

  3. useTwemojiRendereruseEffect 触发,调用 twemoji.parse()

  4. 页面开始无限闪动

根因

useTwemojiRenderer hook 将 Unicode emoji 替换为 <img> 标签,图片源指向 https://twemoji.maxcdn.com/v/14.0.2/。MaxCDN 域名有问题(连接级超时,非 404)。

这触发了一个死循环:

① Unicode emoji → twemoji.parse() → <img src="...maxcdn...">

② maxcdn 不可达 → 图片加载失败 → onerror 触发

③ onerror: replaceChild 恢复 emoji 文字 → DOM 变化

④ MutationObserver 检测到 DOM 变化 → 再次 twemoji.parse()

⑤ emoji 文字又变成 <img> → 回到 ② → 无限循环

涉及文件

  • en-US-Br1mQzod.jsuseTwemojiRenderer hook,含 MutationObserver 监听 DOM 变化并反复调用 twemoji.parse()

  • label-COK6pl_R.js 第 553 行:twemoji 默认 base URL 指向已失效的 MaxCDN

建议修复

  1. 更换 CDN(主修复):将 twemoji 默认 base URL 从 maxcdn 换为 jsDelivr

// 改前
base: "https://twemoji.maxcdn.com/v/14.0.2/"
// 改后
base: "https://cdn.jsdelivr.net/gh/jdecked/twemoji@14.0.2/assets/"
  1. onerror 加防重入(防御性修复):防止任何 CDN 故障时再次陷入循环

    onerror: function onerror() {
      if (this.dataset.twemojiFailed) return;
      this.dataset.twemojiFailed = "1";
      if (this.parentNode) {
        this.parentNode.replaceChild(createText(this.alt, false), this);
      }
    }

  2. MutationObserver 防抖(可选优化):当前 observer 在流式渲染时每次 DOM 变化都重新 parse 全量 emoji,建议加 debounce 或已解析标记

用win的兄弟如果有遇到同样问题也可以临时修一下(ps:可以直接丢给alma,让它自己修复):

在 Alma 的 app.asar 中,Twemoji 的 onerror 处理函数位于一个已知的固定字符串:

this.parentNode.replaceChild(createText(this.alt, false), this);

用任意十六进制编辑器搜索这段字符串(64 字节),替换为:

this.style.display='none'; ← 后面用空格补齐到 64 字节

效果:broken image 被 display:none 隐藏,不再恢复 emoji 文字,MutationObserver 不会再次触发 twemoji.parse(),死循环被打断。emoji 位置显示为空白,但页面不再闪动。

回滚:替换前备份 app.asar,原样覆盖回来即可。

前提:修改前需关闭 Alma,修改后重新启动。

Please authenticate to join the conversation.

Upvoters
Status

In Review

Board
🐛

Bug Reports

Date

About 1 hour ago

Author

name my

Subscribe to post

Get notified by email when there are changes.