年初接到一个任务将 semi-ui 替换到 antd,但是能人力预算不太够,所以基于工作量和效率选择了基于 AST 的替换方案。项目技术栈是 React + tsx为什么要使用 AST?AST(Abstract Syntax Tree,抽象语法树)是一种在计算机科学中表示源代码语法结构的树状数据结构。通过 AST,可以理解代码的结构和含义,实现代码分析、转换和操作。基于 AST 的替换方案可以快速而准确的对大量代码进行修改,提高开发效率和代码质量。还有什么方案?固定字符串替换。对于 import 和 tsx 都有严重的误伤。正则替换,编写复杂,嵌套难以识别。手动替换,重复性工作容易失误,耗费工时太多,适合小工作量的情况。方案比对方案工作量误伤import组件替换组件属性替换固定字符串替换✅😭😭😒😒正则😒😭😒😒😒手动😭✅✅✅✅AST✅✅✅✅✅Babel 简介Babel 是前端领域的必备工具,是一种源码到源码的转译器。在项目中可以让我们使用一些新的语法(展开运算符) 和 api(@babel/core),会在编译的过程中将 code 转为目标环境所支持的语法并引入 polyfillBabel 实际应用场景将 ()=>{} 转为 function(){}为 Array.isArray 添加 polyfill除了上面提到的编译转译代码之外,babel 也可以用来做静态分析,分析代码提取信息,然后生成文档如:自动国际化处理Linter压缩混淆,删除死代码,变量名混淆。模块遍历器,分析 import 移除未被使用的资源模块Babel 编译原理babel 是 source to source 的转换,整体编译流程分为三步:• parse:通过 parser 把源码转成抽象语法树(AST)• transform:遍历 AST,调⽤各种 transform 插件对 AST 进⾏增删改• generate:把转换后的 AST 打印成⽬标代码,并⽣成 sourcemapBabel 中常⻅节点Literal 是字⾯量的意思,比如说 'are you sure?'Statement 是语句Identifer 是标识符的意思Declaration 声明语句是⼀种特殊的语句,它执⾏的逻辑是在作⽤域内声明⼀个变量、函数、class、import、export 等。Expression 是表达式,特点是执⾏完以后有返回值,这是和语句 (statement) 的区别。Element 是 JSX,分为 JSXElement、JSXOpeningElement、JSXClosingElement 等等
图片
Babel 中常⽤ API@babel/parser :babel parser 叫 babylon,是基于 acorn 实现的,扩展了很多语法,可以⽀持 es next(现 在⽀持到 es2020)、jsx、flow、typescript 等语法的解析。babel parser 默认只能 parse js 代码,jsx、flow、typescript 这些⾮标准的语法的解析需要指定语法插件。@babel/traverse :parse 出的 AST 由 @babel/traverse 来遍历和修改,⽀持指定要遍历的 AST 节点,指定 visitor 函数。babel 会在遍历 parent 对应的 AST 时调⽤相应的 visitor 函数。@babel/types :遍历 AST 的过程中需要创建⼀些 AST 和判断 AST 的类型,这时候就需要@babel/types 包。t.isIfStatement 创建,t.assertIfStatement ⽤于判断。@babel/template :⽀持通过代码来⽣成 ast 进⾏替换。相⽐ parser ,template ⽀持不同粒度@babel/generator :AST 转换完之后就要打印成⽬标代码字符串,通过@babel/generator 包@babel/helper-module-imports替换实战存在的问题项⽬技术栈 React + tsx839 个⽂件中,使⽤ 63 个组件,共计 2485 次使⽤,最多⼀个组件被使⽤了 299 次。项⽬周⼀、周三四,上线时间不定。更新频率较⾼没有测试同学,研发⾃测。测试环境⾃测,⽆等待时间,即可上线实战脚本替换属性值&替换属性名Space 不⽀持 vertical 需要改为 direction="vertical"替换 onChange 事件调⽤提取 children 构建为 options替换 Size 改为新的映射关系将 Link 解构赋值整体⽅案统计待升级组件,确认替换范围和影响(839 个⽂件中,使⽤ 63 个组件,共计 2485 次使⽤)项⽬格式化 npx eslint --fix ./src , prettier --write '*/.{tsx,ts}' , 暂不开启编辑器⾃动格式化分批替换(⻚⾯维度、组件维度)每周替换4个组件,以低频⾼优作为参考项。与业务⽅沟通确定上线节奏及变更影响范围,周⼆推 test,周四推 online,提前⼀周在业务群公布。替换计划固定变更影响范围。测试验收(⾃测&test环境)功能、样式⽀持快速回滚。依赖 turbo 实现快速回滚,采⽤临时 release 分⽀,实现需求迭代和组件替换不冲突,遇到问题也可以快速回滚。加⼊业务 feedback 群,遇到问题优先回滚⽌损。所有替换⼯作完成后,开启⾃动格式化,移除⽆效代码。优缺点&改进优点:• ⽀持增量替换,不阻塞业务开发• ⽀持快速回滚• 适合⼤批量重复性⼯作• 适合 jsx 这种嵌套关系的内容修改,可以减少误伤缺点:• 有⼀定的学习成本(当然可以使⽤ GitHub Copilot 、ChatGpt 减少⼀些⼯作量),• 需要收集组件差异(这⾥可以考虑提取属性和⽅法,然后抓取⽂档中的定义做⽐对)• 编码成本(如果替换数量不多,可以考虑⼿动替换)总结最后我们再来回顾⼀下 @babel/parser 、 @babel/traverse 、 @babel/types 、@babel/template 、 @babel/generator 这些库的作⽤。也可以想想有什么应⽤场景是可以落地的?⽐如说• ⾃动国际化,通过脚本提取所有⽂案。• 增加⼀些个性化的格式化规则,⾃闭合标签,优化 imoprt 导⼊顺序。


慷慨的麦片
1 声望0 粉丝