相关模块从 Taro 切换到 React,含 ts 类型(useEffect、useState、useMemo、useCallback、useRef、Component、FunctionComponent、FC、PropsWithChildren、SFC、PureComponent、ComponentClass)
@tarojs/redux 转成 react-redux,dispatch的写法也有所差异,需要同时处理
处理:通过把对应文件解析成 AST,遇到MemberExpression、ImportDeclaration、TSQualifiedName 等节点访问器时,进行相应的模块名称替换,若有新添加的模块或者不再需要的模块引用,需要对该模块添加导入或者删除导入操作,这部分也是复杂度最高环节之一。
下图是一个普通函数组件处理前后语法的变化:
要完成上面的转换,主要需要导入 react,然后相关 api 引用由 Taro 改成 react。可以通过 ImportSpecifier 节点访问器获取 Taro 对象引用的变量名称,通过 node.imported.name 进行匹配。
Taro3 (除小程序自定义组件外)不再支持Component config的写法,需要单独作为配置文件存在
Taro3 (除小程序自定义组件外)不再支持Component options的写法,需要删除
4.4 样式
Taro3 不再支持小程序的原生样式隔离方式,所有样式文件统一被抽离到 app.wxss 中,原来的样式隔离会失效
Taro3 不再支持 this.$router、this.$scope、useScope 等写法去获取路由、小程序实例等信息
Taro3 不再支持 组件级别的componentDidShow、componentDidHide事件,需要手动进行处理
Taro3整体的配置文件的字段也有所调整。主要范围在webpack、babel、scss、react等相关
Taro3 会模拟 全局window 对象,因此原来依靠 typeof window === 'undefined' 来判断是否是web环境会失效
如下是一个源文件转换成AST,进行二次处理,最终又变成源代码文件的过程。
Taro 项目代码命令行工具执行入口主要是 app.tsx 及 app.config.js,具体执行流程见下图。
我们以 app.tsx 举例,首先通过@babel/parser将源代码转成AST,然后通过@babel/parser遍历 AST 的节点访问器。
针对上面2中的区别我们封装了多个独立处理单元,每个处理单元功能都是原子化的,负责具体某个功能的转换,它由多个 AST 节点访问器组成。
对于整个命令行工具执行过程中,我们还开发了一个日志模块收集相关处理信息,并能生成html预览页,便于代码转换成功后人工进行check。
相关信息如下,其中未被引用到的文件清单给开发删除项目冗余文件提供了指引,人工确认代码文件主要是对className的处理,例如有些在全局及相关css中都没找到,有些2者都有等等,这块需要人工确认处理。
基于 AST 的升级方案相较于纯人工方案优势明显,沉淀的命令行工具将来可贡献给 Taro 社区提供类似场景通用解决方案。
当然 AST 升级方案挑战也很多,工作量不小,开发过程中需要不断查阅文档反复调试,对个人而言也是深入研究该领域、扩展技术视野的好机会。
AST技术在业界使用广泛,小程序升级项目更多是进行代码变更等操作,我们团队对AST技术的运用也在持续探索,最近在尝试使用AST对代码改动进行分析,获取函数、变量之间的引用关系,最终得到一个代码改动对业务影响范围的报告,大家可期待后续相关分享。