音乐人小程序初版于2019年8月上线,当时做开发框架选型时,Taro 由于支持小程序、H5两端同构及类 React 语法等特性,比较契合团队当时的诉求,最终选择 Taro(版本1.3.4)作为主框架开发音乐人小程序。
随着 Taro 的主版本升级至3.x,Taro 1/2官方不再进行维护,目前使用的1.3.4版本在开发体验上跟3.x版本存在较大的不足,主要体现在以下几点:
3.1 人工方式
先是梳理 Taro 新旧版本差异,然后对每个文件进行分别处理,这种方式费时费力不说,人工很容易遗漏文件及处理事宜,如果页面众多,风险很大。其次这种大工程一般多人协作参与,很容易出现代码冲突及重复建设问题。
3.2 程序升级方式
先梳理 Taro 新旧版本差异,然后针对这些差异制定不同的处理策略,对于语法特性及配置层面的差异我们通过抽象语法树(AST)来进行转换,这种方式能够面面俱到处理每一个文件,即使发现遗漏的事项,只要优化下升级程序就好。当然有些差异点旁路逻辑太多,程序处理本身编码就很复杂,这块考虑 ROI 也可程序升级完成后人工再介入处理下。
4.1 npm 依赖
处理:通过脚本读取package.json,并对当前依赖逐行与差异依赖进行版本比对,执行相应的新增、修改、删除等操作,最终写入文件覆盖package.json。
4.2 相关类库、模块
处理:通过把对应文件解析成 AST,遇到MemberExpression、ImportDeclaration、TSQualifiedName 等节点访问器时,进行相应的模块名称替换,若有新添加的模块或者不再需要的模块引用,需要对该模块添加导入或者删除导入操作,这部分也是复杂度最高环节之一。
下图是一个普通函数组件处理前后语法的变化:
要完成上面的转换,主要需要导入 react,然后相关 api 引用由 Taro 改成 react。可以通过 ImportSpecifier 节点访问器获取 Taro 对象引用的变量名称,通过 node.imported.name 进行匹配。
如果文件本身有引入 react ,则添加对应引用就行,如无则继续导入。直接通过 Taro 对象访问的变量则通过 MemberExpression 访问器直接将父对象改成 react 即可,代码具体实现如下:
4.3 项目文件结构
处理:通过把对应文件解析成 AST,遇到MemberExpression、ClassMethod、ClassProperty标记时。将对应的节点内容转化为代码,新建为配置文件,再删除旧标记节点。
4.4 样式
处理:通过把对应文件解析成 AST,遇到 JSXAttribute 且属性名为 className 时,替换成css module引用方式,由于 className 的赋值语法多样(如下图)。
我们需要考虑多种场景,还有部分css是外部引入样式,本身找不到,需要向上查找,样式处理部分也是复杂度最高环节之一。
4.5 相关内置api
处理:通过把对应文件解析成 AST,遇到MemberExpression、ClassProperty标记时,将对应的节点内容转化为代码。
4.6 构建配置及其他
处理:由于配置的修改相对于是一次性的行为,人工直接进行修改即可。
如下是一个源文件转换成AST,进行二次处理,最终又变成源代码文件的过程。
主要依赖babel库:
整体转换工具处理流程:
Taro 项目代码命令行工具执行入口主要是 app.tsx 及 app.config.js,具体执行流程见下图。
我们以 app.tsx 举例,首先通过@babel/parser将源代码转成AST,然后通过@babel/parser遍历 AST 的节点访问器。
针对上面2中的区别我们封装了多个独立处理单元,每个处理单元功能都是原子化的,负责具体某个功能的转换,它由多个 AST 节点访问器组成。
例如对于 Taro 1.x版本中使用的 taro-ui 组件,在新版本中需要使用 CustomWrapper 组件进行包裹下,不然会导致组件不可见,具体实现如下:
对于整个命令行工具执行过程中,我们还开发了一个日志模块收集相关处理信息,并能生成html预览页,便于代码转换成功后人工进行check。
相关信息如下,其中未被引用到的文件清单给开发删除项目冗余文件提供了指引,人工确认代码文件主要是对className的处理,例如有些在全局及相关css中都没找到,有些2者都有等等,这块需要人工确认处理。
基于 AST 的升级方案相较于纯人工方案优势明显,沉淀的命令行工具将来可贡献给 Taro 社区提供类似场景通用解决方案。
当然 AST 升级方案挑战也很多,工作量不小,开发过程中需要不断查阅文档反复调试,对个人而言也是深入研究该领域、扩展技术视野的好机会。
AST技术在业界使用广泛,小程序升级项目更多是进行代码变更等操作,我们团队对AST技术的运用也在持续探索,最近在尝试使用AST对代码改动进行分析,获取函数、变量之间的引用关系,最终得到一个代码改动对业务影响范围的报告,大家可期待后续相关分享。