JS生态系统加速探索Draft-js emoji插件功能及使用探索

 更新时间:2024年01月21日 11:24:39   作者:大家的林语冰 人猫神话  
这篇文章主要介绍了JS生态系统加速探索Draft-js emoji插件功能使用探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

长话短说:从 42kB 的重字符串中,从零开始构建了 7138 次正则表达式。缓存该计算大大加快了 Draft-js 表情符号插件的初始化阶段。

本期《前端翻译计划》共享的是“加速 JS 生态系统系列博客”,包括但不限于:

  • PostCSS,SVGO 等等
  • 模块解析
  • 使用 eslint
  • npm 脚本
  • draft-js emoji 插件
  • polyfill 暴走
  • 桶装文件崩溃
  • Tailwind CSS

本期共享的是第 5 篇博客 —— Draft-js emoji 插件。

Draft-js emoji 插件

我通过 Josh Goldberg 的电邮收到了一个非常有趣的问题,涉及一个网站卡死了大约 2-3 秒。该网站使用 Draft-js 富文本编辑器进行一些输入,它能够将范围缩小到 Draft-js 表情符号插件中出现的问题。

通过 Chrome 的分析器捕获的快速记录证实了最初的怀疑。表情符号插件出 bug 了。我们可以看到,底部有一大坨频繁的函数调用,占用了大部分时间。不幸的是,Chrome 的分析器没有像 speedscope 那样的某种“left-heavy”可视化功能。这使得确定哪个函数值得研究变得有点困难。“left-heavy”对此更好,因为它将类似的调用堆栈合并为一个。

每个单独的调用看起来都棒棒哒,并且总是以调用正则表达式引擎结束。但一大坨调用已经足以引发忧虑。Chrome 分析器一个很酷的事情是,它可以使用采样的跟踪来注释源码行。这将为您提供每行执行所需的大概时间。由于前端项目涉及大量转译,它并不是 100% 准确,但它足以得出一些早期结论。

消耗大部分时间的两种方法都处理正则表达式。大家可能很容易得出结论,正则表达式本身是罪魁祸首,但我有一种感觉,这只是深层问题的表症。我们首先检查的是此函数被调用的频率。这可以通过增加一个简单的计数器,或直接使用 console.count()

  ns.escapeRegExp = function(string) {
+   console.count("escapeRegExp");
    return string.replace(/[-[\]{}()*+?.,;:&\\^$#\s]/g, "\\$&");
  };

  ns.replaceAll = function(string, find) {
+   console.count("replaceAll");
    var escapedFind = ns.escapeRegExp(find);
    var search = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+escapedFind+")", "gi");
    // ...
  };

事实证明,每当页面加载时,replaceAll 方法就会被调用 7318 次。接下来,我们检查了 escapeRegExp 被调用的参数类型。理论上,也许它会被相同的参数反复调用。

一分钟后,这个假设被实锤了,因为它反复转义同一个字符串。我们知道此方法是从 replaceAll 调用的,所以让我们检查一下是否总是在那里传递相同的参数。果然,第一个 string 参数收到两个不同的值,但第二个 find 参数始终相同。这就是后来传递给 escapeRegExp 的那个。

图穷匕见的问题是:“谁在调用 replaceAll,为什么它们总是传递相同的参数?”

再次放大配置文件,我们观察到对 replaceAll 的所有调用都将 toShort 作为共同祖先。

这里发生了一些非常有趣的事情,传递给 replaceAll 的第二个参数,根本不依赖传递给 toShort 的参数。沿着 unicodeCharRegex 的线索,我们可以更清楚地了解此处代码的用途。与 Slack 等流行聊天 App 一样,draft-js 插件允许您输入文本 :smile:,然后该文本会自动转换为正确的表情符号“😀”。但反过来也是必要的,这就是我们在这里看到的。

寻找解决方案

进一步了解此代码的用途后,我们注意到,正则表达式是通过迭代 unicode 字符及其元数据的大数据结构构建的。然后将此正则表达式应用于传入的文本,匹配表情符号并将其替换为短代码。每次调用 toShort 时,都会从零开始构建正则表达式。这成为了一个性能问题,因为 unicode 标准有无数的表情符号,并且随着肤色和其他东西变化。是的没错,难怪生成的正则表达式很大。

Chrome 的控制台显示,构建正则表达式的生成字符串比单独的 42kB 更大。

与大多数昂贵计算的情况一样,我们可以通过缓存先前的结果来避免大量工作。这样我们就不需要反复重新计算同样的事情。这是侵入性最小的修复,不需要对插件的架构大更改。我们做了一个 PR,它总共将阻塞时间从 2-3s 减少到 <200ms。

完结撒花

如果我们退后一步,每当该模块首先加载时,总是构建该正则表达式似乎是浪费。结果总是相同的,因此优化是存储转换后的结果,并在插件中使用它。每当发布新版本的插件时都可以构建它。

另一个潜在的想法是,使用手工函数来匹配表情符号。它可以让您非常快速地缩小潜在匹配项的搜索空间,但仍然需要验证此方案在该情况下是否比正则表达式更快。我认为值得一试。

一个更好的想法是,我们可以利用最近的 unicode 增强功能,而不是构建 >40kB 的正则表达式。这包括特殊的 unicode 属性转义,比如 Emoji_Presentation,它允许您直接匹配所有表情符号(比如:/\p{Emoji_Presentation}/gu)。这样我们就可以完全摆脱所有正则表达式生成代码。

总的来说,这个特定问题很好地提醒我们时不时地分析我们的代码。这提醒我们,即使是看似无害的函数,也会对性能产生巨大影响。

免责声明

本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考,英文原味版请传送 Speeding up the JavaScript ecosystem - draft-js emoji plugin

以上就是JS生态系统加速探索Draft-js emoji插件功能及使用探索的详细内容,更多关于JS Draft-js emoji插件的资料请关注脚本之家其它相关文章!

相关文章

  • 阻止事件(取消浏览器对事件的默认行为并阻止其传播)

    阻止事件(取消浏览器对事件的默认行为并阻止其传播)

    取消浏览器对事件的默认行为(响应)(比如a标签的跳转等)并停止事件的继续传播,下面有一个不错的示例大家可以感受下
    2013-11-11
  • JavaScript避免代码的重复执行经验技巧分享

    JavaScript避免代码的重复执行经验技巧分享

    经常会发现一个问题,那就是重复的代码执行,下面就是一些在查看它们的源代码时发现一些问题,把这些分享给大家,希望能让你们更加简洁高效的写出JavaScript代码
    2014-04-04
  • Javascript中的作用域和上下文深入理解

    Javascript中的作用域和上下文深入理解

    这篇文章主要介绍了Javascript中的作用域和上下文深入理解,本文讲解了作用域 VS 上下文、变量作用域、“this”上下文、执行上下文(Execution Context)、作用域链等内容,需要的朋友可以参考下
    2015-07-07
  • JavaScript中的变量提升和函数提升

    JavaScript中的变量提升和函数提升

    这篇文章主要介绍了JavaScript中的变量提升和函数提升,在js中对变量进行操作后打印值经常会出现undefined的现象。其实原因是因为js中有一个叫做变量提升的功能
    2022-07-07
  • XMLHttpRequest对象_Ajax异步请求重点(推荐)

    XMLHttpRequest对象_Ajax异步请求重点(推荐)

    下面小编就为大家带来一篇XMLHttpRequest对象_Ajax异步请求重点(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • JavaScript中while循环的基础使用教程

    JavaScript中while循环的基础使用教程

    这篇文章主要给大家介绍了关于JavaScript中while循环的基础使用教程,文中通过示例代码介绍的非常详细,对大家学习或者使用JavaScript具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • 原生ajax处理json格式数据的实例代码

    原生ajax处理json格式数据的实例代码

    这篇文章主要介绍了原生ajax处理json格式数据的实例代码,需要的朋友可以参考下
    2016-12-12
  • 详解JavaScript原型与原型链

    详解JavaScript原型与原型链

    这篇文章主要介绍了JavaScript原型与原型链的相关资料,帮助大家更好的理解和学习JavaScript,感兴趣的朋友可以了解下
    2020-11-11
  • layui多图上传实现删除功能的例子

    layui多图上传实现删除功能的例子

    今天小编就为大家分享一篇layui多图上传实现删除功能的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • 浅析javascript闭包 实例分析

    浅析javascript闭包 实例分析

    闭包是一个拥有许多变量和绑定了这些变量的环境表达式(通常是一个函数),因而这些变量也是环境表达式的一部分。
    2010-12-12

最新评论