最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
從Wepy到Uniapp變形記

一、 背景

隨著小程序的出現(xiàn),借助微信的生態(tài)體系和海量用戶,使服務(wù)以更加便捷方式的觸達(dá)用戶需求?;诖吮尘?,團(tuán)隊(duì)很早布局智能導(dǎo)購(gòu)小程序(為 vivo 各個(gè)線下門店導(dǎo)購(gòu)提供服務(wù)的用戶運(yùn)營(yíng)工具)的開(kāi)發(fā)。

早期的小程序開(kāi)發(fā)工程體系還不夠健全,和現(xiàn)在的前端的工程體系相差較大,表現(xiàn)在對(duì)模塊化,組件化以及高級(jí)JavaScript 語(yǔ)法特性的支撐上。所以團(tuán)隊(duì)在做技術(shù)選型時(shí),希望克服原生小程序工程體系上的不足,經(jīng)過(guò)對(duì)比最后選擇了騰訊出品的 wepy 作為整體的開(kāi)發(fā)框架。

在項(xiàng)目的從0到1階段,wepy 確實(shí)幫助我們實(shí)現(xiàn)了快速的業(yè)務(wù)迭代,滿足線下門店導(dǎo)購(gòu)的需求。但隨著時(shí)間的推移,在技術(shù)上,社區(qū)逐步沉淀出以 uniapp 為代表的 Vue  棧體系和以 Taro 為代表的 React ??缍说捏w系,wepy 目前的社區(qū)活躍度比較低。另外隨著業(yè)務(wù)進(jìn)入穩(wěn)定階段,除少量的 wepy 小程序,H5 項(xiàng)目和新的小程序都是基于 Vue 和 uniapp 來(lái)構(gòu)建,團(tuán)隊(duì)也是希望統(tǒng)一技術(shù)棧,實(shí)現(xiàn)更好的跨端開(kāi)發(fā)能力,降低開(kāi)發(fā)和維護(hù)成本,提升研發(fā)效率。

二、思考

隨著團(tuán)隊(duì)決定將智能導(dǎo)購(gòu)小程序從 wepy 遷移到 uniapp 的架構(gòu)體系,我們就需要思考,如何進(jìn)行項(xiàng)目的平穩(wěn)的遷移,同時(shí)兼顧效率和質(zhì)量?通過(guò)對(duì)當(dāng)前的項(xiàng)目狀態(tài)和技術(shù)背景進(jìn)行分析,團(tuán)隊(duì)梳理出2個(gè)原則3種遷移思路。

2.1 漸進(jìn)式遷移

核心出發(fā)點(diǎn),保證項(xiàng)目的平穩(wěn)過(guò)渡,給團(tuán)隊(duì)更多的時(shí)間,在迭代中逐步的進(jìn)行架構(gòu)遷移。希望以此來(lái)降低遷移中的風(fēng)險(xiǎn)和不可控的點(diǎn)?;诖耍覀兯伎純蓚€(gè)方案:

方案一 融合兩套架構(gòu)體系

在目前的項(xiàng)目中引入和 uniapp 的項(xiàng)目體系,一個(gè)項(xiàng)目融合了 wepy 和 uniapp 的代碼工程化管理,逐步的將 wepy 的代碼改成 uniapp 的代碼,待遷移完成刪除 wepy 的目錄。這種方案實(shí)現(xiàn)起來(lái)不是很復(fù)雜,但是缺點(diǎn)是管理起來(lái)比較復(fù)雜,兩套工程化管理機(jī)制,底層的編譯機(jī)制,各種入口的配置文件等,管理起來(lái)比較麻煩。另外團(tuán)隊(duì)每個(gè)人都需要消化 wepy 到 uniapp 的領(lǐng)域知識(shí)遷移,不僅僅是項(xiàng)目的遷移也是知識(shí)體系的遷移。

方案二 設(shè)計(jì) wepy-webpack-loader

以 uniapp 為工程體系基礎(chǔ),核心思路是將現(xiàn)有 wepy 代碼融入到 uniapp 的體系中來(lái)。我們都知道 uniapp 的底層依賴于 Vue 的 cli 的技術(shù)體系,最底層通過(guò) webpack 實(shí)現(xiàn)對(duì) Vue 單組件文件和其他資源文件的 bundle。

基于此,我們可以開(kāi)發(fā)一個(gè) wepy 的 webpack 的 loader,wepy-loader 類似于 vue-loader 的能力,通過(guò)該 loader 對(duì) wepy 文件進(jìn)行編譯打包,然后最終輸出小程序代碼。想法很簡(jiǎn)單,但我們想要實(shí)現(xiàn) wepy-loader工作量還是比較大的,需要對(duì) wepy 的底層編譯器進(jìn)一步進(jìn)行分析拆解,分析 wepy 的依賴關(guān)系,區(qū)分是組件編譯還是 page 編譯等,且 wepy 底層編譯器的代碼比較復(fù)雜,實(shí)現(xiàn)成本較高。

2.2 整體性遷移

構(gòu)建一個(gè)編譯器實(shí)現(xiàn) wepy 到 uniapp 的自動(dòng)代碼轉(zhuǎn)換

通過(guò)對(duì) wepy 和 uniapp 整體技術(shù)方案的梳理,加深了對(duì)兩套架構(gòu)差異性的認(rèn)知和理解,尤其 wepy 上層語(yǔ)法和 Vue 的組件開(kāi)發(fā)的代碼上的差異性。基于團(tuán)隊(duì)對(duì)編譯的認(rèn)知,我們認(rèn)為借助 babel 等成熟編譯技術(shù)是有能力實(shí)現(xiàn)這個(gè)轉(zhuǎn)換的過(guò)程,另外,通過(guò)編譯技術(shù)會(huì)極大的提升整體的遷移的效率。

2.3 方案對(duì)比

通過(guò)團(tuán)隊(duì)對(duì)方案的深入討論和技術(shù)預(yù)研,最終大家達(dá)成一致使用編譯轉(zhuǎn)換的方式(方案三)來(lái)進(jìn)行本次的技術(shù)升級(jí)。最終,通過(guò)實(shí)現(xiàn) wepy 到 uniapp 的編譯轉(zhuǎn)換器,使原本 25人/天的工作量,6s 完成。

如下動(dòng)圖所示:

三、架構(gòu)設(shè)計(jì)

3.1 wepy 和 uniapp 單文件組件轉(zhuǎn)換

通過(guò)對(duì) wepy 和 uniapp 的學(xué)習(xí),充分了解兩者之間的差異性和相識(shí)點(diǎn)。wepy 的文件設(shè)計(jì)和 Vue 的單文件非常的相似,包含 template 和 script 和 style 的三部分組成。

如下圖所示,

所以我們將文件拆解為 script,template,style 樣式三個(gè)部分,通過(guò) transpiler 分別轉(zhuǎn)換。同時(shí)這個(gè)過(guò)程主要是對(duì) script 和 template 進(jìn)行轉(zhuǎn)換,樣式和 Vue 可以保持一致性最終借助 Vue 進(jìn)行轉(zhuǎn)換即可。

同時(shí) wepy 還有自己的 runtime運(yùn)行時(shí)的依賴,為了確保項(xiàng)目對(duì) wepy 做到最小化的依賴,方便后續(xù)完全和 wepy 的依賴進(jìn)行完全解耦,我們抽取了一個(gè) wepy-adapter 模塊,將原先對(duì)于 wepy 的依賴轉(zhuǎn)換為對(duì)wepy-adapter 的依賴。

整體轉(zhuǎn)換設(shè)計(jì),如下圖所示:

3.2 編譯器流水線構(gòu)建

如上圖所示,整個(gè)編譯過(guò)程就是一條流水線的架構(gòu)設(shè)計(jì),在每個(gè)階段完成不同的任務(wù)。主要流程如下:

1. 項(xiàng)目資源分析

不同的項(xiàng)目依賴資源不同的處理流程,掃描項(xiàng)目中的源碼和資源文件進(jìn)行分類,等待后續(xù)的不同的流水線處理。

靜態(tài)資源文件(圖片,樣式文件等)不需要經(jīng)過(guò)當(dāng)中流水線的處理,直達(dá)目標(biāo) uniapp 項(xiàng)目的對(duì)應(yīng)的目錄。

3.2.2 AST抽象語(yǔ)法樹(shù)轉(zhuǎn)換

針對(duì) wepy 的源文件(app,page,component等)對(duì) script,template 等部分,通過(guò) parse 轉(zhuǎn)換成相對(duì)應(yīng)的AST抽象語(yǔ)法樹(shù),后續(xù)的代碼轉(zhuǎn)換都是基于對(duì)抽象語(yǔ)法樹(shù)的結(jié)構(gòu)改進(jìn)。

3. 代碼轉(zhuǎn)換實(shí)現(xiàn) - Transform code

根據(jù) wepy 和 uniapp 的 Vue 的代碼實(shí)現(xiàn)上的差異,通過(guò)對(duì)ast進(jìn)行轉(zhuǎn)換實(shí)現(xiàn)代碼的轉(zhuǎn)換。

4. 代碼生成 - code emitter

根據(jù)步驟三轉(zhuǎn)換之后最終的ast,進(jìn)行對(duì)應(yīng)的代碼生成。

四、項(xiàng)目搭建

整體項(xiàng)目結(jié)構(gòu)如下圖所示:

4.1 單倉(cāng)庫(kù)的管理模式

使用 lerna 進(jìn)行單倉(cāng)庫(kù)的模塊化管理,方便進(jìn)行模塊的拆分和本地模塊之間依賴引用。另外單倉(cāng)庫(kù)的好處在于,和項(xiàng)目相關(guān)的信息都可以在一個(gè)倉(cāng)庫(kù)中沉淀下來(lái),如文檔,demo,issue 等。不過(guò)隨著 lerna 社區(qū)不再進(jìn)行維護(hù),后續(xù)會(huì)將 lerna 遷移到 pnpm 的 workspace 的方案進(jìn)行管理。

4.2 核心模塊

wepy-adapter - wepy運(yùn)行期以來(lái)的最小化的polyfill

wepy-chameleon-cli - 命令行工具模塊

wepy-chameleon-transpiler - 核心的編譯器模塊,按照one feature,one module方式組織

4.3 自動(dòng)化任務(wù)構(gòu)建等

Makefile - *nix世界的標(biāo)準(zhǔn)方式

4.4 scripts 自動(dòng)化管理

shipit.ts 模塊的自動(dòng)發(fā)布等自動(dòng)化能力

4.5 單元測(cè)試

采用Jest作為基礎(chǔ)的測(cè)試框架,使用typescript來(lái)作為測(cè)試用例的編寫。

使用@swc/jest作為ts的轉(zhuǎn)換器,提升ts的編譯速度。

現(xiàn)在社區(qū)的vitest直接提供了對(duì)ts的集成,借助vite帶來(lái)更快的速度,計(jì)劃遷移中。

五、核心設(shè)計(jì)實(shí)現(xiàn)

5.1 wepy template 模版轉(zhuǎn)換

5.1.1 差異性梳理

下面我們可以先來(lái)大致看一下wepy的模板語(yǔ)法和uniapp的模板語(yǔ)法的區(qū)別。

圖:wepy模板和uni-app模板

從上圖可以看出,wepy模板使用了原生微信小程序的wxml語(yǔ)法,并且在采用類似Vue的組件引入機(jī)制的同時(shí),保留了wxml< import/ >、< include/ >標(biāo)簽的能力。同時(shí)為了和wxml中循環(huán)渲染dom節(jié)點(diǎn)的語(yǔ)法做區(qū)別,引入了新的< Repeat/ >標(biāo)簽來(lái)渲染引入的子組件,而uni-app則是完全使用Vue風(fēng)格的語(yǔ)法來(lái)進(jìn)行開(kāi)發(fā)。

所以總結(jié)wepy和uni-app模板語(yǔ)法的主要區(qū)別有兩點(diǎn):

wepy使用了一些特定的標(biāo)簽用來(lái)導(dǎo)入或者復(fù)用其他wxml文件例如< import >和< include >。

wxml使用了xml命名空間的方式來(lái)定義模板指令,并且對(duì)指令值的處理更像是使用模板引擎對(duì)特定格式的變量進(jìn)行替換。

下表列舉一些兩者模板指令的對(duì)應(yīng)轉(zhuǎn)換關(guān)系。

此外,還有一些指令的細(xì)節(jié)需要處理,例如在wepy中wx:key="id"指令會(huì)自動(dòng)解析為wx:key="{{item.id}}",這里便不再贅述。

5.1.2 核心轉(zhuǎn)換設(shè)計(jì)

編譯器對(duì)template轉(zhuǎn)換主要就需要完成以下三個(gè)步驟:

  1. 處理wepy引入的特殊的標(biāo)簽例如。
  2. 將wxml中使用的指令、特殊標(biāo)簽等轉(zhuǎn)換為Vue模板的語(yǔ)法。
  3. 收集引入的組件信息傳遞給下游的wepy-page-transform模塊。
  • wepy特殊標(biāo)簽轉(zhuǎn)換

首先我們會(huì)處理wepy模板中的特殊標(biāo)簽< import/ >、< include/ >,主要是將wxml的文件引入模式轉(zhuǎn)換成Vue模板的組件引入模式,同時(shí)還需要收集引入的wxml的文件地址和展示的模板名稱。由于< include/ >可以引入wxml文件中除了< template/ >和< wxs/ >的所有代碼,為了保證轉(zhuǎn)換后組件的復(fù)用性,我們將引入的xx.wxml文件拆成了xx.vue和xx-incl.vue兩個(gè)文件,使用< import/ >標(biāo)簽的會(huì)導(dǎo)入xx.vue,而使用< include/ >標(biāo)簽的會(huì)導(dǎo)入xx-incl.vue,轉(zhuǎn)換import的核心代碼實(shí)現(xiàn)如下:

transformImport() {
// 獲取所有import標(biāo)簽
const imports = this.$('import')
for (let i = 0; i < imports.length; i++) {
const node = imports.eq(i)
if (!node.is('import')) return
const importPath = node.attr('src')
// 收集引入的路徑信息
this.importPath.push(importPath)
// 將文件名統(tǒng)一轉(zhuǎn)換成短橫線風(fēng)格
let compName = TransformTemplate.toLine(
path.basename(importPath, path.extname(importPath))
)
let template = node.next('template')
while (template.is('template')) {
const next = template.next('template')
if (template.attr('is')) {
const children = template.children()
// 生成新的組件標(biāo)簽例如
//
//