從 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模塊 。