Chrome 44 拼写检查的浏览器性能 bug

Chrome 在更新到 44.0.2403.125 m 后,存在一个由拼写检查导致的性能低下 bug,该 bug 只在 win 版 Chrome 下呈现,同时影响 32 位和 64 位版本。

chrome-44-about就是这货

具体表现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
p {margin: 20px;font-weight: bold;text-align: center;width: 33%}
.input {display: block;width: 33%;margin: 20px;border: 2px solid #999;}
.editor {display: block;width: 33%;border-radius: 4px;margin:20px;overflow: scroll;padding: 8px;min-height: 100px;max-height: 400px;}
.area {border: 2px solid #fa0;}
.div {border: 2px solid #0af;}
</style>
</head>
<body>
<input type="text" class="input">
<p>Textarea</p>
<textarea class="editor area"></textarea>
<p>Contenteditable DIV</p>
<div class="editor div" contenteditable='true' role='textbox'></div>
</body>
</html>

将上面这段代码另存为 html 网页,在 Chrome 44 (win) 版本下打开。

用文本编辑器制造 10000 行会被触发单词拼写识别的文本,比如使用 Excel 连续生成 10000 行『AKB0048』。复制粘贴到橙色 Textarea 框中,然后用鼠标点击灰色 Input 框……

你会发现,非常的卡,光标在三个输入框中切换,每次切换都需要花费很长时间,对于性能不佳的电脑,和彻底进入死循环没区别了。

刷新页面重置数据后,再将这 10000 行粘贴到 Contenteditable DIV 的蓝色框里,第一次粘贴也略有卡顿,毕竟数据量比较大。但等卡顿过后,鼠标再在三个框中反复切换,就非常顺畅毫无迟滞感了。

10000linta

这就是这个 bug 的真身了:

在 Textarea 有大量会触发拼写检查的内容时,Chrome 44 的 Spellcheck 功能会极大消耗计算机资源,使得整台电脑近乎死机。

解决办法

由于这是浏览器 bug,前端程序员对此几乎无能为力,只能绕过这个 bug。

通常来说,HTML5 已经提出了 Textarea 的一些标准属性,比如 spellcheck=”false” 可以强制浏览器不检查内容,webkit 内核支持这一属性。正常来说,这似乎是很容易解决的一个兼容性问题。

但偏偏 Chrome 却强制忽略了这一设置,就像它强制忽略 font-size < 10 时那样。禁用拼写检查只在用户手动输入时有效,而对于 Ctrl+V 进来的内容,拼写检查依然正常运行,搞死你机。

即使你把相关属性全部列全:

1
<textarea class="editor area" spellcheck="false" autocapitalize="off" autocomplete="off" autocorrect="off"></textarea>

也是然并卵,在别的浏览器一切正常,而 Chrome 下依然故我。并没有解决问题。

解决方法一:

你可以通过 JS 检查当前浏览器是否是 Chrome,在需要粘贴大量内容的 textarea 上提示用户去关闭 SpellCheck 功能,具体位置为:

Chrome 菜单 → 设置 → (最下方)显示高级设置 → 语言和输入设置 → 启用拼写检查。

但这并不是一个好方法,尤其是需要用户主动去对 Chrome 进行设置。

解决方法二:

使用 JS,将一次的粘贴行为,模拟为连续字符添加的行为。比如当用户 Paste 后得到 Text 值,立刻删除该 Textarea 元素再重建一个。然后根据 text.length 使用 JQuery 插件 Jquery.Caret 不断循环插入字符。

这一方法缺点更多,首先是作为 walkaround 的方案,引入了太多并非用户参与的互动。其次,这一 bug 本来就是在大文本量 paste 下才会出现,如果再使用额外的一重循环,并不会使得体验有太多改善。最后,假如 Chrome 的再次升级把 JS 插入字符也纳入拼写检查的话,就会导致页面更 n 倍重的卡顿,到时候大概是再高性能的电脑都扛不住了。

解决方法三:

使用带 contenteditable=’true’ 属性的 DIV 元素代替 Textarea,并使用 innerText 或者 $.text() 来获取用户填写的文本内容。

10000lintv

这也是这篇博客所写的内容,这样的方法是最合法且绕过 Chrome 44 拼写检查 Bug 的方法。完全相当于是『有两种实现方法选择了另一种』。contenteditable = ‘true’ 属性的 DIV 往往也是很多 JS 版所见即所得编辑器的常用办法。比如 WordPress。这一方法不需要用户操作,也只需要少量 JS 代码。最后,即使这个 BUG 的影响范围继续蔓延,也不过是和现有的情况一样,不会更坏。

关于 MAC 版 Chrome:

Mac 下无此 bug,是因为暂时还没有拼写检查功能。

==== edit ====

现在 Mac 下也有了。

==== edit ====

现在修正了。