手把手教你写几个实用的的AST插件

Javascript AST

背景

AST 是非常有用的

今天下午听了小组一个老哥做的AST分享,深以为然。

为了加深印象,就写了篇总结,顺便分享给大家,希望能给朋友们一些启发。

AST有用,口说无凭, 且看几个具体的案例

且不说:

  1. Vue => React
  2. React => Vue

的代码转换方法,

我们就看一个可以无痛升级旧版React的工具:

react-codemod

代码地址:https://github.com/reactjs/re...

这个工具,功能十分强大,使用起来也很方便,只需要运行一行命令:

npx react-codemod <transform> <path> [...options]

这些无不借助了AST。

下面我们就进入今天的内容。

正文

本文的主要内容包括:

  • 1 理论: AST 概念
  • 2 实践: 使用 AST 实现一个代码转换工具, 把 var转换成let
  • 3 实践: 使用 AST 实现一个Eslint 插件, 禁用 console
  • 4 实践: 使用 AST 实现一个Babel插件, 过滤 Debugger

1. AST 基本概念

AST 是什么

AST is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.

在计算机科学中,抽象语法抽象语法树其实是源代码的抽象语法结构的树状表现形式

常用的浏览器就是通过将js代码转化为抽象语法树来进行下一步的分析等其他操作。

所以将js转化为抽象语法树更利于程序的分析。

AST 能做什么

  • 代码语法的检查
  • 代码风格的检查
  • 代码的格式化
  • 代码的高亮
  • 代码错误提示
  • 代码自动补全
  • 等等。

AST 三板斧

  • 生成AST
  • 遍历和更新AST
  • 将AST重新生成源码

为了便于理解, 我们看一个具体的例子。

这里顺便给大家介绍一个十分有用的网站: https://astexplorer.net/

你譬如:

image.png

声明, 变量, 类型等各种信息一应俱全。

而且这里也提供了各种插件模版供你选择:

image.png

十分的方便。

我们就根据这个例子, 我们做个小的实践。

2. 实践: 使用AST实现一个代码转换工具, 把var转换成let

比如, 现在要重构一个老项目, 你要把项目里的var 全部替换成let, 你会怎么做?

手动替换? 或者借助工具一键替换?

现在就教你一招:一键替换大法

首先还是要介绍一把大杀器: jscodeshift

jscodeshift 是一个 Javscript Codemod 工具,官方对 Codemod 的解释是:

Codemod is a tool/library to assist you with large-scale codebase refactors that can be partially automated but still require human oversight and occasional intervention.

jscodeshift 也是基于 esprima 的,其通过 path 可以很容易的在 AST 上遍历 node

现在我们就开始替换项目中的var.

首先,到 https://astexplorer.net 里面编写代码.

模板我们选: jscodeshift

image.png

官方自带的例子, 把变量名字反转:

image.png

我们现在要改变量, 这个工具很贴心的一点是可以高亮实时对照,

image.png

现在, 找到kind === var 的对象, 替换成let:

得到如下代码:

export default function transformer(file, api) {
  const j = api.jscodeshift;

  return j(file.source)
    .find(j.VariableDeclaration, { kind: 'var'})
    .forEach(path => {
      const letStatement = j.variableDeclaration('let', path.node.declarations)
      j(path).replaceWith(letStatement)
    })
    .toSource();
}

这样也可以:

path.node.kind = 'let'; // 传入的实际是一个引用

实际效果:

image.png

大功告成!

假如我项目里有几个文件也需要相同的操作:

简单安装:

sudo npm install -g jscodeshift

执行:

jscodeshift -t transform.js ./src/demo.js --dry --print

image.png

这里用了--dry 和 --print

--dry 加上之后,不会立刻把新生成的代码覆盖源文件

--print 是打印出来看看

在实际项目里, 你需要在独立的分支里操作,新生成代码之后, 需要你再检查检查review没有问题之后才能合并。

3. 使用AST实现一个Eslint 插件, 禁用console

和上面的类似, 我们也可以做一个eslint 插件, 功能也很简单: 检查到使用console的时候就报错

期望达到的效果:

// Do not use console methods (at 1:9)
   console.log('haha')
// --------^

我们这次选择 babel-eslint 模版。

代码实现:

const disallowMethods = ["log", "info", "warn", "error", "dir"];
export default function(context) {
  return {
    Identifier(node) {
      const isConsoleMethod =
        disallowMethods.includes(node.name) &&
        node.parent.type === "MemberExpression" &&
        node.parent.object.name === "console";

      if (!isConsoleMethod) return;

      context.report({
        node,
        message: "Do not use console methods"
      });
    }
  };
}

实际效果:

image.png

简单有效。

不过你要是非要玩什么骚操作,比如自定义一个log, 那就没得搞了。

最后, 你可以把这段代码封装成一个完整的插件:

教你如何编写 Eslint 插件

你可以自行实践。

4. 使用AST实现一个Babel插件, 过滤debugger

最后一个是过滤源代码中的debugger, Transform 我们选择babelv7

这个插件,我们期望达到的效果是:

var a = 1
debugger
function test() {
  debugger
   a++
}
debugger

到:

var a = 1;

function test() {
  a++;
}

这也是一个十分有用的功能。

代码实现:

export default function (babel) {
    const {
        types: t
    } = babel;

    return {
        name: "ast-transform", // not required
        visitor: {
            DebuggerStatement(path) {
                path.remove()
            }
        }
    };
}

实际效果:

image.png

总结

内容大概就是这么多,没什么难度,重在讲述理论和入门

对AST还不熟练的同学, 希望这篇可以帮助到你。

后面还有会AST在我们实际项目中的应用, 我也会写一个实战篇, 敬请期待!

以上。

延伸阅读

https://www.toptal.com/javasc...

最后

如果觉得内容有帮助,可以关注下我的公众号 「 前端e进阶 」,一起学习。

clipboard.png

Image placeholder
licongmin123
未设置
  53人点赞

没有讨论,发表一下自己的看法吧

推荐文章
直男福利!手把手教你做一只口红色号识别器,秒变李佳琦

大数据文摘编辑组出品技术实现:宁静 七夕将至,送礼时节。直男送礼,首选口红。毕竟李佳琦一句”OMG买它”,女朋友披头散发抢购,钱包就空了一半。但是,口红色号千千万,选对了牌子才成功了一半。快乐橙、伤心

Python爬虫:手把手教你采集登陆后才能看到数据

课程推荐:Python开发工程师--学习猿地--送9个上线商业项目 爬虫在采集网站的过程中,部分数据价值较高的网站,会限制访客的访问行为。这种时候建议通过登录的方式,获取目标网站的cookie,然后再

python自动化测试学习 - Pytest插件之selenium

推荐课程《Python开发工程师--学习猿地精品在线课》今天主要演示Pytest框架的selenium插件。webdriver是主流的UI自动化测试框架,在Pytest的测试框架中也提供了对webdr

核心业务“瘦身”进行时!手把手带你搭建海量数据实时处理架构

01背景 在线交易服务平台目的是减轻核心系统计算压力和核心性能负荷压力,通过该平台可以将核心系统的交易数据实时捕获、实时计算加工、计算结果保存于SequoiaDB中。并能实时的为用户提供在线交易查询服

手把手带你入门前端工程化——超详细教程

课程推荐:前端开发工程师--学习猿地精品课程 本文将分成以下7个小节: 1技术选型2统一规范3测试4部署5监控6性能优化7重构 部分小节提供了非常详细的实战教程,让大家动手实践。另外我还写了一个前端工

手摸手教你搭建简单的 Git 的代码自动发布

1.为什么我要弄这个? emmmm,因为有个自己的项目每次发布到线上,都要登录一下服务器,然后pull一下代码,执行一些项目初始化的命令(诸如:gitsubmoudleupdate,phpartisa

徒手教你使用zookeeper编写服务发现

zookeeper是一个强一致【不严格】的分布式数据库,由多个节点共同组成一个分布式集群,挂掉任意一个节点,数据库仍然可以正常工作,客户端无感知故障切换。客户端向任意一个节点写入数据,其它节点可以立即

jQuery选择器的的优点是什么

jQuery选择器的的优点1、简洁的写法,说道简洁的写法,给大家列举一下例子,看看jQ和原生哪个更方便。。2、提供了完善的处理机制(完善的兼容处理)3、jQuery选择器判断dom节点存在的方法:4、

腾讯汤道生:产业互联网时代,安全成为CEO的一把手工程

产业互联网日益成为众多行业实现转型,获得发展新动能的趋势性选择,政务、金融、医疗、出行、教育、零售、工业等垂直领域,正在全面拥抱产业互联网。网络安全作为互联网的基础保障,在产业互联网发展和企业数字化升

一步步教你如何在 Django REST API 中构建使用 JWT 验证

基于令牌的身份验证,允许后端服务与前端(无论是web端,原生移动端或其他端)分离,并驻留在不同域中。JSONWebTokens(JWT)是一种流行的令牌认证实现,在本文中,我们使用它来验证,通过Dj

还在用useState来定义数据吗?教你个更好的方案:useImmer!

以前编写state的方式Hooks上市之前我们是这么定义state的:state={ people:[ { name:'马云', englishName:'JackMa' }, { name:'马化腾

学习IT的实用工具和网站推荐

对于一些学习IT的初学者来说,掌握一些实用的软件工具和学习网站是十分有必要的。本文要为大家推荐一些学习IT的相关的资源,像是鸠摩搜书和脚本之家等电子书搜索网站,还有冰点文库和文件搜索工具等实用工具以及

爱奇艺的数据库选型大法,实用不纠结!

来源:rrd.me/fgGsG我们进行数据库选型的时候要考虑哪些问题?有哪些需求?待选用的数据库是否和需求对得上?是不是直接可以拿来用?需不需要一些额外的开发?这些都会在本文的分享中提及。一、数据库技

Linux常用命令 & 实用命令万字总结

课程推荐:Linux开发工程师--学习猿地精品课程 ls最高使用频率的命令之一。命令格式:ls[OPTION]...[FILE]...单纯的输入:[root@iz2ze76ybn73dvwmdij06

教你阅读 Python 开源项目代码

为什么要阅读开源代码 阅读Python开源项目代码主要有如下三个原因: 在工作过程中遇到一些问题Google和StackOverFlow等网站找不到解决办法,只能去翻源码。 对某些项目或者方向非常感

甜过初恋!浙大博士用200个西瓜130页论文,教你用机器学习科学挑瓜

大数据文摘出品作者:易琬玉刚刚送走了最热七月,转眼就迎来了最热八月。2019年是人类有气象纪录以来最热的几个年份之一,虽然这个夏天还没结束,但气象学家们已经有十足把握做出这个判断。为了应付热,人们想出

10后小学生都能教你学编程了!低龄编程的下限在哪?

大数据文摘出品作者:宁静最近,文摘菌经常收到读者留言,说b站上有一个10后小学生在教编程。小学生???教编程???话说文摘菌小学时候还只知道玩儿贪吃蛇……在感叹长江后浪推前浪的同时,文摘菌也赶紧去这位

「解放双手」老舅教你VS Code Disco

观感度:🌟🌟🌟🌟🌟口味:驴肉蒸饺烹饪时间:15min这是最好的时代,也是最坏的时代。今年听到过最浪漫的一句话:我们在键盘上留下的余温,也将随时代传递到更远的将来。感觉让理性的技术人多了份柔光滤镜。也许

忘记MySQL密码怎么办?一招教你搞定!

课程推荐:PHP开发工程师--学习猿地精品课程 在安装完MySQL或者是在使用MySQL时,最尴尬的就是忘记密码了,墨菲定律也告诉我们,如果一件事有可能出错,那么它一定会出错。那如果我们不小心忘记了M

支付中台的几个面向:支付业务、资金核算、面向风控等切面

手哥架构宝典之支付系统1.0发布后,很多架构师朋友表示受益匪浅,询问支付系统2.0版本什么时候放出来,今天刊发出《架构宝典》支付系统2.0版本,以飨读者。00 概述在1.0的支付系统中,我们遇到了诸多

广联达转型还要几个三年?

日前,广联达发布了2019年中报,根据财报,广联达实现营收13.48亿元,同比增长27.76%,实现归属于上市公司股东净利润0.90亿元,同比下降39.13%。“七三”战略收官之年行至一半,广联达净利

jquery怎么判断元素是第几个?

jquery怎么判断元素是第几个?假设有下面这样一段HTML代码: jQuery判断当前元素是第几个元素示例 jQuery获取第N个元素示例 jQuery选择器示例 如果我们点击任何一个li标签,想知

消失的这几个月我都干了什么

前言消失两个多月后我胡汉三又回来了,比较遗憾的是这并不是一篇技术文,有兴趣的朋友就当做故事看吧。所以这其实是一份年终总结其实这段期间一直有朋友在问我咋不接着更新公众号了?甚至一点消息都没了。真不是不更

jquery怎么获取第几个元素?

在jquery中,可以使用eq()方法找到第几个元素或第N个元素,jquery中eq()的使用如下:eq()选择器选取带有指定index值的元素。index值从0开始,所有第一个元素的index值是0

【值得收藏】前端优化详解以及需要关注的几个问题

课程推荐:web全栈开发就业班--拿到offer再缴学费--融职教育 前端优化是一个大的课题,需要花好多时间才能理解,之前对前端优化陆陆续续有一些了解。所以这次从渲染优化,打包优化,代码优化做了一个系