从 Wepy 到 UniApp 变形记( 二 )


如下图所示 , 

从 Wepy 到 UniApp 变形记

文章插图
所以我们将文件拆解为 script,template,style 样式三个部分,通过 transpiler 分别转换 。同时这个过程主要是对 script 和 template 进行转换,样式和 Vue 可以保持一致性最终借助 Vue 进行转换即可 。
同时 wepy 还有自己的 runtime运行时的依赖,为了确保项目对 wepy 做到最小化的依赖,方便后续完全和 wepy 的依赖进行完全解耦,我们抽取了一个 wepy-adapter 模块,将原先对于 wepy 的依赖转换为对wepy-adapter 的依赖 。
整体转换设计,如下图所示:
从 Wepy 到 UniApp 变形记

文章插图
3.2 编译器流水线构建
从 Wepy 到 UniApp 变形记

文章插图
如上图所示,整个编译过程就是一条流水线的架构设计,在每个阶段完成不同的任务 。主要流程如下:
3.2.1 项目资源分析不同的项目依赖资源不同的处理流程,扫描项目中的源码和资源文件进行分类,等待后续的不同的流水线处理 。
静态资源文件(图片,样式文件等)不需要经过当中流水线的处理,直达目标 uniapp 项目的对应的目录 。
3.2.2 AST抽象语法树转换针对 wepy 的源文件(app,page,component等)对 script,template 等部分,通过 parse 转换成相对应的AST抽象语法树,后续的代码转换都是基于对抽象语法树的结构改进 。
3.2.3 代码转换实现 - Transform code根据 wepy 和 uniapp 的 Vue 的代码实现上的差异,通过对ast进行转换实现代码的转换 。
3.2.4 代码生成 - code emitter根据步骤三转换之后最终的ast,进行对应的代码生成 。
四、项目搭建整体项目结构如下图所示:
从 Wepy 到 UniApp 变形记

文章插图
4.1 单仓库的管理模式使用 lerna 进行单仓库的模块化管理 , 方便进行模块的拆分和本地模块之间依赖引用 。另外单仓库的好处在于 , 和项目相关的信息都可以在一个仓库中沉淀下来 , 如文档,demo,issue 等 。不过随着 lerna 社区不再进行维护,后续会将 lerna 迁移到 pnpm 的 workspace 的方案进行管理 。
4.2 核心模块
  • wepy-adapter - wepy运行期以来的最小化的polyfill
  • wepy-chameleon-cli - 命令行工具模块
  • wepy-chameleon-transpiler - 核心的编译器模块,按照one feature,one module方式组织
4.3 自动化任务构建等Makefile - *nix世界的标准方式
4.4 scripts 自动化管理shipit.ts 模块的自动发布等自动化能力
4.5 单元测试
  • 采用Jest作为基础的测试框架,使用typescript来作为测试用例的编写 。
  • 使用@swc/jest作为ts的转换器,提升ts的编译速度 。
  • 现在社区的vitest直接提供了对ts的集成 , 借助vite带来更快的速度 , 计划迁移中 。
五、核心设计实现5.1 wepy template 模版转换5.1.1 差异性梳理下面我们可以先来大致看一下wepy的模板语法和uniapp的模板语法的区别 。
从 Wepy 到 UniApp 变形记

文章插图
图:wepy模板和uni-app模板
从上图可以看出,wepy模板使用了原生微信小程序的wxml语法 , 并且在采用类似Vue的组件引入机制的同时,保留了wxml< import/ >、< include/ >标签的能力 。同时为了和wxml中循环渲染dom节点的语法做区别,引入了新的< Repeat/ >标签来渲染引入的子组件,而uni-app则是完全使用Vue风格的语法来进行开发 。
所以总结wepy和uni-app模板语法的主要区别有两点:
  1. wepy使用了一些特定的标签用来导入或者复用其他wxml文件例如< import >和< include > 。
  2. wxml使用了xml命名空间的方式来定义模板指令 , 并且对指令值的处理更像是使用模板引擎对特定格式的变量进行替换 。
下表列举一些两者模板指令的对应转换关系 。
从 Wepy 到 UniApp 变形记

文章插图
此外 , 还有一些指令的细节需要处理 , 例如在wepy中wx:key="id"指令会自动解析为wx:key="{{item.id}}",这里便不再赘述 。
5.1.2 核心转换设计编译器对template转换主要就需要完成以下三个步骤:
  1. 处理wepy引入的特殊的标签例如 。
  2. 将wxml中使用的指令、特殊标签等转换为Vue模板的语法 。
  3. 收集引入的组件信息传递给下游的wepy-page-transform模块 。