博客 / 詳情

返回

跨端開發的最佳實踐——Chameleon(變色龍 )

前言

近期,在公司落地了一個社區內比較 新(踩)的(坑) 跨端框架 Chameleon,當時的需求是先實現快應用端,之後需要支持 H5、微信小程序、字節小程序等。由於公司用的技術棧是以 Vue.js 為主,在做了一番技術選型後,最終選擇了 Chameleon(開始瘋狂踩坑 😳)

這個時候,可能會有人問:為什麼不選 uniapp?這麼説吧,uniapp -> 快應用就不是一個坑了,是個炸彈 💣。後面,我會講解為什麼不選 uniapp 😲

不過,理性評價,Chameleon 確實是一個優秀的跨端框架。至於優秀在哪?(請繼續閲讀 😶)

本次文章將會分為以下三個部分,通過介紹、對比現有前端跨端框架,來逐點講述 Chameleon 優秀之處 😍:

  • 為什麼我們需要跨端?
  • 爆炸發展的前端跨端框架
  • Chameleon 未來的跨端方案

1. 😷 為什麼我們需要跨端?

當然,瞭解這個緣由的同學,可以跳過這個小節哈~

這個問題,我們可以分為兩個維度去解釋:

需求的多變性

現今,小程序實在是太多了...而且,對於日異變更的需求,今天可能和你説的是微信小程序,過了一段時間,可能會和你説同樣的產品,你寫個快應用版的 😲。對於需求方來説,他們並不關注你是怎麼實現的不同端,並且,可能還會覺得,你做個一樣的東西只是平台不一樣那不是很快嗎

技術的維護性

從技術維護維度思考,這是為了我們更好地維護代碼,儘量通過維護一套代碼來實現不同端的產品,例如微信小程序、字節小程序、快應用、H5 等等。所以,選擇跨端框架開發的方式,給我們帶來的好處:

  • 保證上新功能時的穩定
  • 出現問題時的,快速 touble shot
  • 減少寫重複性的代碼
  • and so on...

2. 💥 爆炸發展的前端跨端框架

現在,前端可選擇的跨端框架有很多,Taro、uniapp、kbone、mpvue、Chameleon 等等。當然,其中部分還是有技術限制的,例如騰訊的 Kbone 只能支持 web 端和微信小程序同構,京東的 Taro 支持的 DSL 是 React,Uniapp 支持的 DSL 是 Vue。所以,框架雖多,但是還是那句大白話,適合自己所處技術團隊的才是最好的 🤓️。

接下來,我們來簡單認識一下支持 Vue 的 DSL 的四個跨端框架 mp-vue、uniapp、kbone、Chameleon:

2.1 mpvue

mpvue 是 fork 自 Vue@2.4.1 版本,其保留了 Vue2.x 的一部分東西,例如使用 flow 來做靜態類型檢測、默認的一些語法等。mpvue 設計思路大體上是修改 Vue2.x 運行時和模版編譯的部分,針對不同的平台對編譯生成的 AST(抽象語法樹)做語法轉化到指定端的語法,從而完成對不同端的代碼生成。

友情提示:mpvue 的 GitHub commit 最近一次 commit 是 17 個月前

2.2 uniapp

uniapp 我想很多同學都耳熟能詳,估計有些接觸的前端同學,就是因為這個,畢竟 DCloud 也算是“大名鼎鼎”。前面,也提及 mpvue 最近的一次的 commit 已經是 17 個月前,而 uniapp 可以支持把 mpvue 的項目轉為 uniapp 的項目(估計能多不少使用者 😏)。

uniapp 在跨端方面確實是很優秀,引入了條件編譯的機制來支持不同端的表現,例如我們要在 H5 和微信小程序兩個不同端顯示用户頭像,前者可以通過微信提供的數據顯示用户頭像,後者可以直接使用 open-data 組件獲取。那麼,通過條件編譯我們可以這樣寫:

<!-- #ifdef MP-WEIXIN -->
   <open-data class="img-avatar" type="userAvatarUrl"></open-data>
<!-- #endif -->
<!-- #ifdef H5 -->
   <img :src="avatar" class="avatar" />
<!-- #endif -->
條件編譯,只會將符合這個條件的平台下的代碼寫入該平台的項目代碼中

並且,uniapp 能跨端的類型也是很完善的,也支持快應用。但是,不同於其他小程序,快應用是自繪渲染引擎,而不是 webview 渲染。所以,目前 uniapp 對於快應用只支持了 vivo、oppo、華為這三種廠商。

因此,這也是我起初做技術選型的時候,放棄 uniapp 的原因。不過 uniapp 還支持轉 webview 版的快應用,但是 webview 版的快應用又不是所有廠商都支持的...

2.3 kbone

kbone 是騰訊團隊推出的一套支持 Web 端和微信小程序端進行同構的跨端框架。但是,顯然相比較前面兩者,kbone 的使用場景就略少一些,因為其受限於只支持 Web 端和微信小程序端。不過,如果需求只是 H5 和微信小程序,顯然 kbone 是一個不錯的選擇,畢竟原裝正版(騰訊)的技術支持。

那麼,接下來就輪到 Chameleon 了,主角即將登場 😎~

3. 🐲 Chameleon 未來的跨端方案

Chameleon 作為跨端框架中的新興勢力,它同樣有一套自己的 DSL(特色領域語言),即也可以稱它為 CML。但是,不同於上述我們介紹的跨端框架,Chameleon 擴展多端的方式是採用的多態協議的方式,這裏我們引用一下官方的介紹

Chamleon 通過定義統一的語言框架 + 統一多態協議,從多端(對應多個獨立服務)業務中抽離出自成體系、連續性強、可維護強的“前端中台服務”。

3.1 多態協議

官方的介紹中出現了一個大家可能沒有接觸過的一個名詞多態協議。那麼,Chameleon 的多態協議是什麼?

首先,我們從理論層面瞭解一下什麼是多態協議,Chameleon 的多態協議設計的想法 💡 源於 Apache Thrift - 可伸縮的跨語言服務開發框架。那麼,什麼是 Apache Thrift ?

Apache Thrift 是一個採用接口描述語言定義並創建服務,支持可擴展的跨語言服務開發的框架。用大白話講,就是 Apache Thrift 使得不同語言(Java、C、PHP)創建的服務可以被互相調用。

而 Chameleon 框架的核心機制之一 —— 多態協議則是借鑑了這種設計,提供了多態接口多態組件的方式來擴展第三方端(微信小程序、快應用、字節小程序等)。例如,我們可以通過定義多態接口來實現不同端的特定 API,然後在業務代碼層面直接使用定義好的多態接口就可以實現一個方法調用在不同端下的特定 API,這看起來會是這樣:

並且,對於目前 Chameleon 默認支持的跨端平台來説,其編譯生成的代碼只是支持了 Chameleon 官方提供的基礎組件和 API,例如在微信和快應用中常用到的組件 listtext,API setStoragegetStorage 等等。

那麼,這些不同端是如何基於 Chameleon 規定的基礎組件和 API 來擴展實現的呢?接下來,我會以 Chameleon 擴展快應用端的實現為例,帶大家深入淺出一番其中的所以然 😲 ~

3.2 如何擴展一個新端

首先,不得不説的一點就是 Chameleon 可以完美支持跨快應用的開發,但是這個過程有一點點坑,不過踩掉就行~

那麼,這裏我們來了解一下基於 Chameleon 擴展快應用需要做什麼?這個過程主要是由 6 個 packages 完成:

|—— cml-quickapp-api              ## 實現 CML 提供的 api
|—— cml-quickapp-plugin            ## 實現編譯相關處理,例如生成 .ux 文件、manifest.json 文件
|—— cml-quickapp-runtime            ## 實現 App、Page、Component 組件實例
|—— cml-quickapp-store            ## 實現 CML 的狀態管理
|—— cml-quickapp-ui            ## 實現 CML 的普通組件
|—— cml-quickapp-ui-builtin        ## 實現 CML 的 Native 組件
實際上快應用是 7 個 package,還有一個 cml-quickapp-mixins,它會對一些指令和事件(例如 c-model、touchstart)做兼容處理。

可以看到擴展一個端,我們至少需要 6 個 packages,而這 6 個 packages 完成了這 4 點:

而其中每一點需要實現的細節,官方文檔已經講解很詳細了,這裏就不重複論述。本小節只是簡單介紹一下每個 packages 的職責,讓同學們可以具備 debugger 源碼的一點思路,有興趣的同學可以自行了解其中的代碼細節。

接下來,我們講講在業務開發中要如何擴展某個端的特定 API,即多態接口。

3.3 如何擴展某個端的 API(多態接口)

假設,此時我們處於快應用開發的場景,需要為應用添加桌面。而快應用添加桌面的 API 不在 Chameleon 官方文檔規定的 API 中,所以這個時候就需要實現多態接口,即我們要需要自定義快應用添加桌面的 API。

首先,創建 shortcut.interface 文件,在該文件中定義 API 的類型:

<script cml-type="interface">
  type successCallBack = (res: boolean) => void
  type failCallBack = (res: boolean) => void
  type obj = {
    success: successCallBack,
    fail: failCallBack
  }

  interface UtilsInterface {
    installShortCut(obj): void;
    hasInstalled(obj): void;
  }
</script>
相信大家可以看出來,其實接口的類型定義和 TypeScript 中的類型定義大同小異。

然後,在 shortcut.interface 文件中,定義添加桌面的類,其中包含兩個方法 installShortCut()hasInstalled(),在方法內部可以直接使用快應用的原生 API:

<script cml-type="quickapp">
class Method implements UtilsInterface {
  installShortCut(obj) {
    quickapp.shortcut.install(obj)
  }
  hasInstalled(obj) {
    quickapp.shortcut.hasInstalled(obj)
  }
}

export default new Method()
</script>
<script cml-type="web">
class Method implements UtilsInterface {
  installShortCut(obj) {
  }
  hasInstalled(obj) {
  }
}
export default new Method();
</script>
...

並且,這裏需要注意 ⚠️ 2 點:

  • 為了保證其他端的正常運行,shortcut.interface 文件中同樣需要聲明其他端對應的方法,這裏我們可以是一個空函數
  • 不能直接在方法的內部使用 shortcut API。因為,在快應用中 shortcut 是綁定在 system 上的,而 system 在編譯時會被注入代碼中以 quickapp 存在,所以我們必須通過 quickapp.shortcut 的方式調用

最後,我們就可以在業務代碼中使用添加桌面的 API,並且它只會在快應用下有所表現:

<template>
  <page title="index">
    <text @click="addShortCut"></text>
  </page>
</template>
<script>
import shortCut from "../../components/utils/shortcut.interface";
  
class Index {
    methods = {
      addShortCut() {
        shortCut.installShortCut({
          success: (res) => {
            console.log(res)
          },
          fail: (err) => {
            console.log(err)
          }
        })
      }
    }
}
</script>
而擴展某個端的組件(多態組件)和擴展 API 大同小異。chameleon-tool 也提供了命令 cml init component 來初始化一個多態組件模版,這一塊官方文檔也詳細介紹了,這裏就不做論述哈。

3.4 小結

多態組件和多態接口都是多態協議的一部分,多態協議還支持多態模版,這會類似於 uniapp 的條件編譯,可以指定 template 中展示的組件所屬的端(僅作用於 root element)。並且,我想懂得了如何使用多態組件、多態接口、多態模版,那麼使用 Chameleon 開發可以説是隨心所欲。

最方便的是萬不得已時我們可以改一點源碼哈哈 😄

結語

Chameleon 這個框架給我的感受,確實是又愛又狠 😷。因為,當時在項目開發過程中,快應用團隊寫的擴展有幾個問題,我為了保證項目的正常上線,所以只能硬着頭皮魔改源碼抗着項目往前走 😳,最終項目也成功上線。然後,在週末的時間,我也整理了一些對 Chameleon 框架的理解,以及修復了幾個快應用擴展存在的問題(順手提了個 PR)。

最後,歡迎 👏 打算在業務中嘗試 Chameleon 的同學一起交流心得(加我微信或公眾號),如果在快應用實現中遇到了坑,我想我應該可以幫助一二,並且,如果文中存在表達不當或錯誤的地方,歡迎各位同學提 Issue~

參考

深入淺出主流的幾款小程序跨端框架原理

Chameleon 統一的語言框架 + 多態協議

Apache Thrift - 可伸縮的跨語言服務開發框架

Chameleon 擴展新端標準

❤️ 愛心三連擊

寫作不易,可以的話麻煩點個贊,這會成為我堅持寫作的動力!!!

我是五柳,喜歡創新、搗鼓源碼,專注於 Vue3 源碼、Vite 源碼、前端工程化等技術分享,歡迎關注我的微信公眾號:Code center

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.