前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于AST技术的Taro框架升级方案

基于AST技术的Taro框架升级方案

作者头像
QQ音乐技术团队
发布2024-01-04 08:39:02
1970
发布2024-01-04 08:39:02
举报

1、项目背景

音乐人小程序初版于2019年8月上线,当时做开发框架选型时,Taro 由于支持小程序、H5两端同构及类 React 语法等特性,比较契合团队当时的诉求,最终选择 Taro(版本1.3.4)作为主框架开发音乐人小程序。

随着 Taro 的主版本升级至3.x,Taro 1/2官方不再进行维护,目前使用的1.3.4版本在开发体验上跟3.x版本存在较大的不足,主要体现在以下几点:

  • Taro 1.x 版本遵循 React 语法规范实现的 Nerv 框架跟 React 在 jsx 语法差异,新特性不支持
  • 部分小程序官方提供的API不支持
  • Taro 全家桶,依赖升级困难
  • Taro 自研构建工具,编译慢,黑盒

2、预期收益

  • 改善开发体验:完全支持 React 18新版本语法特性,减少开发心智负担,编译时间提升明显,热更新速度达到秒级。
  • 提升页面性能:页面运行流畅度及加载速度方面都有一定的提升。
  • 提高可维护性:Taro 新版本issue处理活跃,生态丰富,文档完善,对项目质量更有保障。

3、升级方式对比

3.1 人工方式

先是梳理 Taro 新旧版本差异,然后对每个文件进行分别处理,这种方式费时费力不说,人工很容易遗漏文件及处理事宜,如果页面众多,风险很大。其次这种大工程一般多人协作参与,很容易出现代码冲突及重复建设问题。

3.2 程序升级方式

先梳理 Taro 新旧版本差异,然后针对这些差异制定不同的处理策略,对于语法特性及配置层面的差异我们通过抽象语法树(AST)来进行转换,这种方式能够面面俱到处理每一个文件,即使发现遗漏的事项,只要优化下升级程序就好。当然有些差异点旁路逻辑太多,程序处理本身编码就很复杂,这块考虑 ROI 也可程序升级完成后人工再介入处理下。

4、Taro 1.x与Taro 3.x差异及处理策略

4.1 npm 依赖

  • Taro3 核心依赖,需要升级到目标版本 3.5.12
  • Taro3 新引入的依赖(react/构建相关)
  • Taro3 需要删除过期依赖
  • Taro-ui 升级

处理:通过脚本读取package.json,并对当前依赖逐行与差异依赖进行版本比对,执行相应的新增、修改、删除等操作,最终写入文件覆盖package.json。

4.2 相关类库、模块

  • 相关模块从 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 进行匹配。

如果文件本身有引入 react ,则添加对应引用就行,如无则继续导入。直接通过 Taro 对象访问的变量则通过 MemberExpression 访问器直接将父对象改成 react 即可,代码具体实现如下:

4.3 项目文件结构

  • Taro3 (除小程序自定义组件外)不再支持Component config的写法,需要单独作为配置文件存在
  • Taro3 (除小程序自定义组件外)不再支持Component options的写法,需要删除

处理:通过把对应文件解析成 AST,遇到MemberExpression、ClassMethod、ClassProperty标记时。将对应的节点内容转化为代码,新建为配置文件,再删除旧标记节点。

4.4 样式

  • Taro3 不再支持小程序的原生样式隔离方式,所有样式文件统一被抽离到 app.wxss 中,原来的样式隔离会失效

处理:通过把对应文件解析成 AST,遇到 JSXAttribute 且属性名为 className 时,替换成css module引用方式,由于 className 的赋值语法多样(如下图)。

我们需要考虑多种场景,还有部分css是外部引入样式,本身找不到,需要向上查找,样式处理部分也是复杂度最高环节之一。

4.5 相关内置api

  • Taro3 不再支持 this.router、this.scope、useScope 等写法去获取路由、小程序实例等信息
  • Taro3 不再支持 组件级别的componentDidShow、componentDidHide事件,需要手动进行处理

处理:通过把对应文件解析成 AST,遇到MemberExpression、ClassProperty标记时,将对应的节点内容转化为代码。

4.6 构建配置及其他

  • Taro3整体的配置文件的字段也有所调整。主要范围在webpack、babel、scss、react等相关
  • Taro3 会模拟 全局window 对象,因此原来依靠 typeof window === 'undefined' 来判断是否是web环境会失效

处理:由于配置的修改相对于是一次性的行为,人工直接进行修改即可。

5、基于AST实现自动升级方案原理解析

如下是一个源文件转换成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者都有等等,这块需要人工确认处理。

6、项目总结及规划

基于 AST 的升级方案相较于纯人工方案优势明显,沉淀的命令行工具将来可贡献给 Taro 社区提供类似场景通用解决方案。

当然 AST 升级方案挑战也很多,工作量不小,开发过程中需要不断查阅文档反复调试,对个人而言也是深入研究该领域、扩展技术视野的好机会。

AST技术在业界使用广泛,小程序升级项目更多是进行代码变更等操作,我们团队对AST技术的运用也在持续探索,最近在尝试使用AST对代码改动进行分析,获取函数、变量之间的引用关系,最终得到一个代码改动对业务影响范围的报告,大家可期待后续相关分享。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、项目背景
  • 2、预期收益
  • 3、升级方式对比
  • 4、Taro 1.x与Taro 3.x差异及处理策略
  • 5、基于AST实现自动升级方案原理解析
  • 6、项目总结及规划
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档