對無線電商動態化方案的思考(二)

勾股發表於2016-05-25

上一篇談到了我對無線電商動態化的理解,並簡單提到了我們自己提出的技術方案:Weex,今天就來詳細介紹一下 Weex

一句話介紹

Weex 是一款輕量級的移動端跨平臺動態性技術解決方案!

幾個特點

輕量

體積小巧,語法簡單,方便上手

可擴充套件

業務方可自行橫向定製 native 元件和 API

高效能

快速載入,快速渲染,體驗流暢

其它

  • 擁抱標準:基於 Web 標準設計語法
  • 響應式介面: 通過簡單的模板資料繫結輕鬆解決資料和檢視的同步關聯問題
  • 多端統一:iOS、Android、HTML5 多端效果一致,撰寫一次就可以輕鬆達到跨平臺的一致性,無需針對多套平臺單獨開發,省時省力
  • 複雜邏輯描述:動態性不只體現在展示效果的動態性上,更體現在可以實時調整複雜的資料處理方式和邏輯控制方式
  • 元件化:元件之間通過 webcomponents 的設計完美的隔離,並可以通過特定的方式進行資料和事件的傳遞
  • 生態&鏈路:我們為 Weex 的開發者和使用者在不同維度上提供了各式各樣的工具和平臺,包括程式碼打包工具、開發者除錯工具、部署平臺、Playground、經典案例、入門指南和詳盡的文件等。你不是從零開始,你也不是一個人在戰鬥!

如何工作

1. 本地元件開發

首先,我們像開發 webcomponents 一樣,把一個元件分成 <template><style><script> 三部分,剛好對應一個元件的介面結構、介面樣式、資料&邏輯。

細節1:順便說一句,這也是我們認為描述介面的最佳實踐。

程式碼示例:

<template>
  <container style="flex-direction: column;">
    <container repeat="{{itemList}}" onclick="gotoDetail">
      <image class="thumb" src="{{pictureUrl}}"></image>
      <text class="title">{{title}}</text>
    </container>
  </container>
</template>

<style>
  .thumb {width: 200; height: 200;}
  .title {flex: 1; color: #ff0000; font-size: 48; font-weight: bold; background-color: #eeeeee;}
</style>

<script>
  module.exports = {
    data: {
      itemList: [
        {itemId: `520421163634`, title: `寶貝標題1`, pictureUrl: `https://gd2.alicdn.com/bao/uploaded/i2/T14H1LFwBcXXXXXXXX_!!0-item_pic.jpg`},
        {itemId: `522076777462`, title: `寶貝標題2`, pictureUrl: `https://gd1.alicdn.com/bao/uploaded/i1/TB1PXJCJFXXXXciXFXXXXXXXXXX_!!0-item_pic.jpg`}
      ]
    },
    methods: {
      gotoDetail: function () {
        this.$openURL(`https://item.taobao.com/item.htm?id=` + this.itemId)
      }
    }
  }
</script>

顯然這些程式碼是不會被 native app 識別的,我們要想辦法讓這些程式碼可執行。所以我們同時做了三件事:

  1. 在本地用一個叫做 transformer 的工具把這套程式碼轉成純 JavaScript 程式碼
  2. 在客戶端執行一個 JavaScript 引擎,隨時接收 JavaScript 程式碼
  3. 在客戶端設計一套 JS Bridge,讓 native 程式碼可以和 JavaScript 引擎相互通訊

所以緊接著第二步,就是用 transformer 對程式碼進行轉換,變成客戶端可執行的 JavaScript 程式碼

其實本地開發還有一點很重要,就是把複雜的介面通過元件化的方式進行分解,併合理的建立元件之間的組合和呼叫關係。

最終,我們把簡單元件組合成複雜的介面,並通過 transformer 打包成一個完整的程式包 (主體是一段 JavaScript 程式碼)

細節2:由於 Weex 元件的開發和 Web 元件的開發非常接近,但是對標準的支援範圍和一些細節是有不同之處的,我們會貼心的在 transformer 里加入了一些友情提醒,幫助大家迴避常犯的書寫錯誤。

2. 客戶端渲染

上一節已經提到了,我們在客戶端會執行一個 JavaScript 引擎並且有 JS Bridge 通訊機制。這裡再介紹具體一些:

native 渲染和 JavaScript 引擎之間,主要進行三類通訊:

  1. 介面渲染,單向 (JS -> native):這毫無疑問,JavaScript 引擎需要把介面的結構和樣式告訴 native 端,這樣我們才能得到 native 級別的終極介面效果
  2. 事件繫結與觸發,雙向:在我們的客戶端技術方案中,native 端只負責介面渲染和非常薄的事件觸發層,事件的邏輯處理都會放在 JavaScript,這樣我們就具備了複雜資料處理和邏輯控制的動態性可能。JS 告訴 native 需要監聽的互動行為,而當使用者產生對應的互動行為時,native 端會把互動資訊回傳給 JS
  3. 對外的資料/資訊請求與響應,雙向:JS 引擎在處理特殊邏輯時,難免需要向伺服器請求資料、或請求本地的系統資訊和使用者資訊、或呼叫 native 的某個功能,這個時候也會通過 JS Bridge 進行請求,native 收到這些請求之後,也會在必要的情況下通過 JS Bridge 把資訊回傳給 JS 引擎

再加上外層對 Weex 例項的管理,整套機制就可以順暢的工作起來了

細節3:native 端渲染的時候,我們以圖片和文字的形態為主,並大量依賴了標準的 CSS 樣式進行細節的渲染

細節4:我們把框架層面的 JS 程式碼全部提前放在了客戶端本地,並提前執行做好準備。這樣本地生產的 JavaScript 是非常小的,網路傳輸的代價也非常低,而在客戶端執行的初始化成本也非常低。整條鏈路都和介面開啟速度息息相關

細節5:我們在 JS 處理介面邏輯的過程中採取了資料監聽+依賴收集的策略,既沒有通過髒檢查,也沒有通過全量 diff Virtual DOM 樹的方式,因為通常在移動端,資料變更都是非常小量的,經過我們的實踐,這套方案完全可以應付移動端日常的動態性介面需求

細節6:我們對業務上通用常用的元件進行了封裝,並且暴露規範化的型別 (標籤名)、特性、樣式、事件、上下級約束等維度的定義。這樣所有的業務介面都可以用這些基礎的元件搭建而成

細節7:我們對業務上通用常用的 API 進行了封裝,並且暴露規範化的 JS API

3. 服務端部署

我們在服務端提供了基礎的程式包釋出,給每個程式包一個特定的 page id,然後為客戶端提供通用的服務,通過 page id 獲取程式包,這樣本地開發、動態實時部署、客戶端動態化渲染和邏輯處理就完美的串聯在一起了

細節8:實際上,除了介面本身可以動態化之外,客戶端的 JS 引擎的程式碼、還有部分 native 的實現,我們也準備了相應的動態化機制,也就是說客戶端的動態能力本身也是具有動態性的

4. 瀏覽器端渲染

我們還會面對這樣的場景,就是一個客戶端的業務,會通過微博之類的渠道進行轉播和推廣,當使用者手機裡剛好安裝了手機淘寶客戶端,那麼會直接“拉起”客戶端進行相應的介面展示,如果沒有裝手機淘寶,則需要在瀏覽器裡展示一個相同或接近的介面。自然 Weex 技術方案支援的業務也有這樣的需求。所以我們同時提供了 HTML5 版本的技術方案,同一份 JavaScript 程式包,可以同時通過客戶端的 JS Bridge 渲染成為 native 介面,也可以通過瀏覽器渲染成為 web 介面。我們的做法也非常簡單,就是把 JS Bridge 背後的 native 處理邏輯同構成了 HTML5 版本。然後釋出這樣的一個頁面。

細節9:我們能夠同構 HTML5 版本和 native 版本,主要歸功於我們在 JS Bridge、元件定義、API 定義方面的高度抽象——當然 HTML5 的版本在效能和體驗上確實有一定的劣勢,並不是最理想化的效果,所以核心的主戰場還是客戶端,這也和目前的移動網際網路的形態相吻合

綜上所述,整個 Weex 的工作原理大致可以用一張圖來表述:

回看 Weex 的幾個特點

輕量

我們致力於把開發體驗、網路傳輸的大小、執行時的開銷控制做到極致,並且儘可能的降低多端適配和優雅降級的成本

橫向可擴充套件

我們對元件的定義和業務功能預留了很好的橫向可擴充套件能力,這也業務方可以自由定製屬於自己的 native 元件和 API,從而在後期可以通過實時釋出不同的程式包來進行動態化控制。同時也因為它的橫向可擴充套件性,Weex 的核心可以非常小,非常易於融入現有的無線技術體系

高效能

我們在網路傳輸、例項初始化、JS 運算、native 渲染能力等方面做了非常針對性且深入的優化,尤其是針對中低端安卓機,不論是載入時間還是執行時的流暢度,都比之前的方案有質的飛躍。我們對 CPU、記憶體、幀率、首屏渲染時間等核心效能指標也一直保持高度的關注,也建立了相應的線上監控和資料統計機制。而更多可優化的空間和方案我們還在不斷的進行優化嘗試。

下圖是今天凌晨舊金山 QCon 上 Weex 技術方案的首次公開分享中的一頁效能表現對比圖,大家可以感受一下:

總結

這就是 Weex,如上一篇文章所介紹的:

  • 致力於移動端
  • 能夠充分排程 native 的能力
  • 能夠充分解決和迴避效能瓶頸
  • 能夠靈活擴充套件
  • 能夠多端統一
  • 能夠優雅“降級”到 HTML5
  • 能夠保持較低的開發成本
  • 能夠快速迭代
  • 能夠輕量實時釋出
  • 能夠融入現有的 native 技術體系
  • 能夠工程化管理和監控

目前 Weex 還在努力達到更高的效能、更高的擴充套件性、更低的開發成本、更完整的生態和工具鏈,也同時嘗試接入更多的業務,體現出它的更大的價值。已經有很多業務方迫不及待的在和我們主動取得聯絡了,未來我們希望 Weex 能夠逐步在集團內開放試用,並最終走向開源。

另外整個技術方案還有很多值得分享的東西,比如 transformer 的實現、元件和 API 的設計思路等,我們會再做針對性的分享和介紹

下一篇:對無線電商動態化方案的思考(三)


相關文章