基於weex的有贊無線開發框架

有贊技術發表於2018-10-30

出於對開發效率和動態化的要求,無線端的開發框架也一直在更新,從 Hybrid、結構化 Native View、React Native、Weex,再到現在正在大受關注的 Flutter。什麼樣的框架才是適合自己的團隊?不僅要有技術追求,而且要考慮實際業務需要。最近,有贊移動選擇了 weex 作為無線開發框架,搭建了從開發、Debug、構建、釋出、資料一個閉環的流程。本文將對此進行分享。

開發閉環

一、什麼是 weex

Weex 是阿里巴巴開源的一套構建高效能、可擴充套件的原生應用跨平臺開發方案。首先總結一下 weex 的特點:

  1. 頁面的開發目前支援RaxVue

    Weex 也不是隻支援 Vue 和 Rax,你也可以把自己喜歡的前端框架整合到 Weex 中,有一個文件擴充套件前端框架描述瞭如何實現,但是這個過程仍然非常複雜和棘手,你需要了解關於 js-native 之間通訊和原生渲染引擎的許多底層細節。

  2. 一次編寫,三端(Android、iOS、前端)執行

    前提是都整合了 weex sdk,另外視覺表現做不到完全一樣,有的會有一些差異,需要做一下適配。所以寫 weex 頁面的時候,如果支援三端,便需要在三端都進行自測。

  3. UI 的繪製通過 native 的元件,JavaScript 邏輯在 JS 引擎裡執行,兩者通過 JavaScriptCore 通訊

    weex 裡使用元件都需要在 native 端註冊,這樣 weex 裡才可以使用,執行的時候通過註冊時記錄的 map 進行查詢。weex sdk 內建註冊了一些基礎的元件,包括 list、text、input 等。WXJSCoreBridge 封裝了 JavaScriptCore 實現 native 和 js 之間的通訊。

  4. 支援 Native 擴充套件

    可以將 native 的 UI 元件封裝成 component,將 native 的邏輯程式碼封裝成 module。從而在 weex 裡可以進行使用。這裡的 natiev UI 元件包括 modal、webview、image 等,這裡的 native 邏輯程式碼包括 storage、network 等。

  5. 每個 weex 頁面會被打包成一個 js 檔案,weex sdk 將 js 檔案渲染成一個 view weex 的打包通過 webpack,將每個頁面打包成獨立的一個 js 檔案,weex sdk 會將 js 進行解析,將 UI 部分繪製成一個 view, 再繫結 view 的事件與 js 程式碼繫結。

二、為什麼要使用weex進行無線開發

1. 效率問題

1)開發的人力成本

如果不算 web 端,一個頁面本來需要 Android 和 iOS 2 個人開發;使用 weex 後只需要 1 個開發頁面。

2)開發的編譯速度

隨著專案漸漸變得龐大,Android 專案一次編譯需要 2-3 分鐘,機器不好的還需要 10 分鐘,iOS 可能會快一點,也需要 1-2 分鐘。使用 weex 後,介面修改,只需要十幾秒

3)測試效率

提測之後,發現 bug,修復完成,測試總需要重新下載一個包進行安裝;使用 weex 後,跟原生無關的 bug,只要測試重啟 App 就可以進行驗證。

2. 動態化

weex 頁面最後打包完是一個 js 檔案,只要能做到動態下發 JavaScript,那便可以實現動態化,可以熱修復,甚至可以熱部署,完全替換或者新增頁面。

3. 成熟度

在 2016 年阿里雙十一中,Weex 在阿里雙十一會場中的覆蓋率接近 99%,頁面數量接近 2000,覆蓋了包括主會場、分會場、分分會場、人群會場在內幾乎所有的阿里雙十一會場業務。阿里雙十一主會場秒開率97%,全部會場頁面達到 93%。 2016 年 12 月 15 日,阿里巴巴宣佈將移動開源專案 Weex 捐贈給 Apache 基金會開始孵化。 2017 年,weex 在阿里業務裡增長如下圖,來自 WeexConf 2018。

阿里業務增長

4. 接入成本

經過實踐,一個移動端開發,一週時間就可以開始進行使用 weex 進行業務開發。

三、如何使用 weex 進行無線開發

weex 其實是一套方案,各個流程很多東西需要自己建設,把它建設得讓小夥伴可以以較小成本開始使用 weex,把它建設得融入已有的系統。這方面,我們目前做了下面這幾個方面,還任重道遠。

zanweex 建設

1. 開發工具 zweex-toolkit

這是一個腳手架工具,基於 weex 官方的 weex-toolkit,用於新建 weex 工程,目前只支援 vue。

隨著頁面的增多,業務的複雜,工程會慢慢變得龐大,每次執行的時候如果全部頁面都執行起來比較慢。為了解決這個問題,使用 zweex-toolkit 建立建的工程模板支援執行的時候,支援只執行指定目錄下的頁面,只要在 npm start 後加上引數即可,如:

npm run start hi,helloworld
複製程式碼

這樣就表示只執行 hi 目錄下和 helloworld 下的頁面。 另外,我們支援:

  • 新增頁面zweex page
  • 開啟除錯zweex debug

2. ZanWeex SDK 的實現

官方 weex sdk 做的事情,就是輸入一個 js 檔案,然後返回一個view。考慮到每個應用的路由和個性化的需要,這一點,ZanWeex SDK 沒有做其他工作,也還是返回了一個view,業務方可以根據自己的需要將view新增到自己想要展示的地方。ZanWeex SDK 做的事情主要有如下幾方面:

1)支援下發配置,支援動態化,可以完成整個頁面的替換

weex 頁面打包後的結果是一個 js 檔案,所以可以進行下發進行動態更新,那麼就需要有一份配置,來關聯頁面路由和 js 檔案的關係,於是我們設計了這樣的資料結構:

h5:頁面路由地址,可以直接使用釋出平臺生成的 h5 地址

js:打包後的 js 檔案地址

version:支援的最低 App 版本,因為新頁面如果需要 native 擴充套件,那就需要釋出新版本進行支援

md5:為了校驗完整性,我們在配置裡新增每個 js 檔案的 md5。

2)支援多模組獨立配置,互不影響 一個App裡會有多個模組,每個模組可能由獨立的團隊進行負責,所以為了減少耦合,我們將配置獨立,每個模組可以獨立管理自己的配置,獨立接入weex,不依賴於宿主App。

3)預載入頁面模板,支援頁面模板快取和配置快取

  • 如果沒有快取,每次都從服務端拉取頁面模板,那麼是不可能達到秒開的,跟沒有做快取的H5頁面就區別不大了。我們SDK會預載入頁面模板到本地,開啟過的頁面會快取到記憶體。這樣渲染的時間就更接近原生的渲染時間了。

4)支援開發時的hot reloading,前端開發般的體驗

  • 如果沒有hot reloading,那麼每次修改完頁面,都得退出頁面重新進入。為了省去這個操作,hot reloading是必須的。
  • weex 工程裡本地開發時候,通過webpack-dev-server來啟動一個websocket,zan weex sdk 開啟一個weex頁面後,去與它建立連線。webpack-dev-server將工程的編譯狀態傳送給ZanWeex SDK,當接收到渲染完成的指令時,就重新渲染頁面,從而達到 hot reloading的目的。

5)支援頁面的適配,提供環境變數 ZanWeex SDK 會提供以下四個變數共 weex 頁面使用,方便完成頁面配置。

  • 容器的高度:weex.config.yzenv.viewHeight
  • 容器的寬度:weex.config.yzenv.viewWidth
  • 狀態列高度:weex.config.yzenv.statusBarHeight
  • 底部欄高度(針對iPhone X,其他為0):weex.config.yzenv.bottomHeight

6)開發階段日誌的檢視 在開發階段,weex sdk 原始碼裡輸出的日誌以及 js 裡通過 console.log 輸出的日誌,還有 js 執行的報錯,都只能通過 XCode 和 Android Studio 進行檢視。這對於一個只瞭解一端的開發人員是非常不方便的。於是我們做了一個入口,在開啟 weex 頁面的時候,會顯示該入口,點選即可檢視所輸出的日誌。

7)引數傳遞 正向傳參:從 A 頁面跳轉到 B 頁面,引數傳遞是開發過程肯定會遇見的一個場景。SDK 對外提供的渲染介面 renderByH5 的引數包括 url,params,data。業務方進行渲染的時候,可以將引數直接跟在 url 後面,或者通過 params、data 傳入,不同方式,取的方式也不一樣:

  • url 後面的引數,會傳入 data,weex 頁面裡直接在 data 裡定義引數就會自動賦值;

  • params的引數,在 weex 頁面裡可以通過 weex.config.name 來獲取;

  • data 傳入的引數,獲取方式同第一種。

  • 反向傳參:從 B 頁面返回到 A 頁面的時候,攜帶引數返回也是很常見的一個場景。SDK 提供了統一的儲存類 ZParamStorage 來臨時儲存引數。頁面 B 要返回的時候先把資料存入儲存區,A 頁面顯示的時候再從儲存區獲取,然後清空儲存區。

  • 非跳轉的引數傳遞:weex 頁面之間,可以採用 BroadcastChannel 進行傳參,weex 與 native 之間的傳遞可以通過自己封裝 Module 進行實現。

3. 頁面的開發

前面有提到,weex 的頁面目前可以採用 vue 或者 Rax 編寫。對於 Vue 和 Rax 的語法這裡不做陳述。這裡主要總結了容易在實際開發中卡住小夥伴的幾個問題。

1)如何判斷一個頁面是否用 weex 來實現?

可以認為所有的新頁面都可以採取 weex 來開發,區別在於這個頁面使用的 native 能力有多少。可以通過自定義 Module 來呼叫 native 的能力,通過自定義 component 來使用 native 的元件;

2)什麼時候需要自定義 Module?

  • 需要原生的能力的時候,比如:
    • 要呼叫系統選擇圖片的介面
    • 呼叫打電話、發簡訊的功能
    • 開啟其他應用
  • 呼叫已有的業務邏輯,比如:
    • 加密、解密邏輯
    • 登入邏輯

3)什麼時候需要自定義 component?

  • 如果一個元件已經使用 native 實現,為了保持統一一致,那麼可以將原有的元件封裝成 component
  • 如果一個元件不能使用 weex 實現,比如地圖元件、超長圖顯示等

4)多個彈層的佈局如何實現?

weex 頁面渲染的層級,是從上而下的,越在下面的佈局,顯示越上層。所以要作為彈層的佈局,就把它放到最下面。

5)頁面的動畫如何實現?

官方 weex sdk 已經封裝了 animation 的 module 可以直接使用,複雜的動畫可以使用 BindingX 實現。

6)weex 的程式碼如何複用?

程式碼都可以抽離出元件。

  • 作為一個 UI 元件,抽離成一個元件,向外暴露屬性引數和事件介面;
  • 作為獨立的 js 函式,抽離成一個 js 供其他頁面引入;
  • css 樣式也可以抽離成一個 css 檔案,供其他頁面引入;
  • 如果包含多個元件形式,可以通過 mixins 來引入。

4. 構建和打包平臺

我們開發了以專案為單位的構建平臺:

  • 每個專案可以新增多個分支,可以是不同倉庫的分支。因為一個專案有可能是跨團隊跨模組的,但是需要一起釋出。
  • 構建通過 webpack 構建,構建之後,支援釋出線下儲存和線上 cdn

我們還開發了以應用為單位的 weex 釋出平臺:

  • 這裡的應用是一個抽象概念,不是傳統的“應用”,可以理解成模組
  • 業務方可以在構建平臺構建完成後,一鍵跳轉到釋出平臺進行釋出,除了需要第一次填寫最低支援的版本號,其他均無需操作。
  • 釋出平臺支援灰度釋出、全量釋出和回滾。
  • 釋出平臺會展示 weex 在端上的使用情況,渲染時間、渲染錯誤、下載時間等

四、遇到的問題以及解決方案

在開發過程中,很多問題,可以通過閱讀原始碼來解決,比如:

  • 使用 iconfont 的時候,是否已支援快取?

    答:已支援,包括記憶體快取和檔案快取,記憶體快取使用 familyname 來做 key,檔案快取使用 md5(url) 來做本地檔名

  • module實現的函式能不能返回引數?

    答:module 的函式氛圍 UIThread 和 JSThread,JSThread 對於 js 執行緒來說是同步的,支援直接返回引數;UIThread 對於 JS 執行緒來說是非同步的,不支援直接返回引數,只能使用 callback

另外,很多常見的問題,我們已經在 ZanWeexSDK 進行了解決,包括實現動態化、多模組的支援、快取管理、Hot Reloading、日誌檢視、頁面適配、引數傳遞等。

此外,還會有一些常見的問題,在此羅列一下:

  1. 配置的更新機制是怎樣的?更新失敗,如何開啟 weex 頁面?

    答: 配置的更新介面開放給業務方呼叫,由業務方決定什麼時候呼叫更新介面;SDK 裡做了三種處理,來儘量保證配置可以更新成功:

    1)配置介面拉取失敗後,會有三次重試;

    2)網路從無網變成有網時,sdk 會檢查配置是否已拉取,如果未拉取就主動拉取

    3)允許業務方內建配置和 js 檔案,當拉取失敗後,SDK裡會從內建配置裡讀取

  2. 配置的版本管理是怎樣的?

    答:配置每次釋出的時候,都會指定該釋出支援的 App 最低版本號。每次請求,會攜帶 App 版本號,服務端只會返回符合該版本號的最新配置。

  3. 支援不支援螢幕旋轉?

    答:答案是支援的。旋轉之後,螢幕變成了橫屏,weex 就按照橫屏的尺寸來渲染,問題是隻要你寫的頁面符合這種變化就可以了,跟 native 來實現頁面沒有什麼區別。

五、未來還要繼續做的事情

  1. 元件庫的建設
  2. 效能統計,比如幀率、記憶體、CPU
  3. 配置和js檔案的增量更新、推送更新
  4. 降級處理

基於weex的有贊無線開發框架

相關文章