最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从零开始写一个babel插件

    正文概述 掘金(flyingbird)   2021-07-28   718

    背景

    需要分析JS执行的效率,所以需要记录JS的执行时间,通过执行时间分析JS执行效率。但是由于aync/await使用的盛行,造成在记录函数执行时间的过程中,会记录异步执行的时长,造成时间记录不准确,无法分析JS函数真正执行的时间。

    看一段代码

    const asyncFn = ms => new Promise((resolve, reject) => {
      setTimeout(resolve, ms);
    });
    
    const record = {
      start: 0,
      time: 0,
    };
    
    const fn = async () => {
      record.start = performance.now();
      await asyncFn(100);
      record.time = performance.now() - record.start;
      console.log(record.time);
    }
    
    fn();
    

    通过浏览器控制台可以看到输出结果103.84499999781838,每次执行时间可能会不同,但应该都在这个值附近。可以看出由于aync/await函数的存在导致fn函数的计时不准确,把异步函数的执行时间也计算在内了

    在Web端异步函数执行时一般是在请求外部相关接口,此时并不会阻碍Web端执行其他JS函数,不会造成JS阻塞导致页面卡顿,所以这种异步函数的执行时间并不在我们的统计范围内,我们只统计web中代码的执行时间。

    修正方式

    一般我们可以通过在async/await函数上下分开计时的方式来解决这个问题,具体可以看下段代码:

    const asyncFn = ms => new Promise((resolve, reject) => {
      setTimeout(resolve, ms);
    });
    
    const record = {
      start: 0,
      time: 0,
    };
    
    const fn = async () => {
      record.start = performance.now();
      record.time = performance.now() - record.start;
      await asyncFn(100);
      record.start = performance.now();
      record.time = performance.now() - record.start;
      console.log(record.time);
    }
    
    fn();
    

    通过在浏览中运行,可以在控制台中看到结果,大概是0.010000003385357559,可以看出确实可以解决异步函数带来的影响,但是需要在每个涉及async/await的地方都要这样手动处理,你不觉得这样很麻烦吗?

    目标

    使用babel AST的能力,通过分析代码的AST,自动处理async/await的计时问题,避免人工输入大量重复代码,减少出错的机会。

    工具

    一个优秀的工具是通往目标的阶梯,而babel当之无愧是这个阶梯。

    可视化AST平台

    点击跳转,可以很方便查看代码AST结构,有助于理解代码和AST结构之间的关系,事半功倍。

    将上面两段代码复制进AST,我们可以看到上述代码的AST结构:

    从零开始写一个babel插件

    对我们来说,需要重点关注的就是type为Program的部分,这里面描述了代码片段的AST结构。

    babel生成AST流程介绍

    写babel插件之前,需要对babel的运作周期有个清晰的认识,这样我们才能知道自己写的插件什么时候起作用、达到的效果是什么,写插件的过程中才能游刃有余。

    Github上对babel的介绍点击跳转,可以查看对babel插件内容的基本介绍,包括AST中各种节点的定义类型、遍历方式、插件入口等,建议详细查看一遍。由于相关内容,该文档已经比较详细,编写插件过程中,方便进行各种API使用方法的查询手册,因此本文中就不再赘述这部分内容了。

    找到处理目标节点

    由于本次只是涉及async/await函数相关操作,我们将关注type为AwaitExpression类型的AST节点 从零开始写一个babel插件

    babel插件编写格式

    按照babel插件的格式,我们需要默认导出一个函数,该函数接收一个babel对象作为参数,返回一个具有visitor属性的对象,具体为:

    export default function (babel) {
        return {
            visitor: {
                AwaitExpression(path) {},
            },
        };
    }
    

    在visitor对象中,定义我们需要处理的节点类型进行处理即可,具体逻辑可以参考github上代码

    babel插件处理流程

    具体流程可以参考github上代码,单元测试部分,主要分为三个部分:

    • 解析代码字符串生成AST,主要利用babylon
    • 遍历AST,进行节点处理,主要利用babel-traverse,这里为了简便生成需要插入代码的AST,使用了babel-template这个工具,使用起来超级方便,再也不用自己手动使用babel-types去手动构建所需要的AST了
    • 根据处理后的AST生成代码,主要利用babel-generator

    总结

    这样一个简单的babel插件就完成了,当然要是真实环境进行使用的话,还需要考虑很多其他边界条件,这里从整体上介绍babel的插件编写模式,便于后续有相似需求时,可以快速上手。

    插件代码示例

    可以在github上找到本文中的代码示例,方便进行效果测试和新插件开发。


    起源地下载网 » 从零开始写一个babel插件

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元