淺談混合應用的演進

還是怕麻煩發表於2018-06-08

前端想要寫 APP

開篇想以這樣的方式開頭,從 APP 開始火到現在,前端同學就一直想要寫 APP,各方技術也是為了讓前端同學寫上 APP 操碎了心。

淺談混合應用的演進

為什麼要前端同學來寫 APP,站在整個技術鏈上來看,都是在做頁面呈現,頁面互動,對於技術而言只是將產品在不同的端上進行呈現,所以很早之前就有提倡說大前端的概念。既然功能都差不多,就沒有分家的理由。

再者,開發客戶端現在的常規平臺有 iOS 和 android 兩個大的平臺,在前端領域越來越細分的大環境下,傳統意義上的客戶端開發至少需要兩撥開發者來做,成本就會有增加。並且伴隨著成本增加還帶來了需要兩套體系化的語言開發,開發效率也會大打折扣。相較於兩大客戶端平臺的開發人員,前端的開發人員是要更多的,並且隨著移動端的興起前端開發者會有資源剩餘的情況,前端來寫 APP 也可以平衡資源。

所以不僅僅是前端同學想要來寫 APP,更多的是未來發展需要這樣的技術來提高生產力,所以才會有各種各樣的方案出現,各種方案的誕生也發現了前端寫 APP 的不足,所以又有了不斷的演進來適應未來發展。送給每一個前端人,我們的征途是星辰大海

淺談混合應用的演進

web APP

淺談混合應用的演進

就是我們常說的 h5 應用,這個階段屬於滿足展示功能階段,首先是解決手機端能展示頁面的問題。

實現方式就是客戶端提供 webView 元件,就是一個基於 webkit 引擎、展現 web 頁面的控制元件。web APP 實際上就是客戶端提供了一個瀏覽器的宿主環境,能在手機上顯示對應的網頁內容,但是各大手機廠商對於核心都會有所謂的“優化”,這些所謂的優化或者核心版本升級所帶來的相容性問題,也是讓前端同學咬牙切齒。

客戶端提供了類似瀏覽器的宿主環境,前端將自己的 HTML/CSS/JS 執行起來,就可以看到頁面了。但是在 PC 端原來我們看到的頁面放在手機上,展示和互動都不太合適。之所以我們要叫 h5 應用,是說我們在移動端上需要用到 HTML5/CSS3 的新功能,通過這些功能能在客戶端的瀏覽器上做適配展示頁面。

響應式的佈局方式,新式的 meta 標籤,媒體查詢等功能讓前端以前顯示在 PC 端上的頁面能展示在手機端。隨著 PWA 的出現,現在手機端逐漸對 Service Worker 的支援(Safari 還在躊躇猶豫),web APP 又重新煥發了青春。

淺談混合應用的演進

優點:

  • 基於 webView 的跨平臺,除錯方便(控制檯除錯)
  • 開發速度快,只要有瀏覽器就能開啟,適合小版本的試錯
  • 無需安裝,不佔記憶體,隨時更新,維護成本低

缺點:

  • 開啟白屏時間長,使用者體驗較差,互動功能受限。
  • 產品也受限於瀏覽器,並且留存低,適合拉新
  • 不採用 PWA 的方案就無法離線,沒有網路就失去了活力,現在不用網路的 APP 情況已經很少了。重複開啟重複載入

代表產品:

  • 所有可以使用手機瀏覽器開啟的網頁(不做相容展示會有問題)
  • 微信公眾號裡純文章

hybrid 應用

淺談混合應用的演進

跨過了 web APP 的滿足展示功能階段,這個時候開始想有更多的功能滿足互動需求,比如調起原生的攝像頭(雖然 input 也可以實現),這個時候催生了 hybrid APP,也進入了豐富功能階段。

前端 webView 的互動實現無法直接與攝像頭的 API 進行互動,類似這樣的功能是客戶端的能力,webView 想要完成這樣的功能,如果不能直接完成是不是可以通過呼叫客戶端來完成這樣的功能,但是前端和客戶端是兩種不同的語言及實現方式,如何進行通訊?

想要通訊完成通訊,其實就是需要再前端與和客戶端搭建一個溝通橋樑,就是現在常說的 js bridge。介紹擊中常見的 js bridge 通訊方式。

js bridge

js 呼叫 native:

  • 請求攔截
  • 彈窗攔截
  • 注入 js 方法

native 呼叫 js:

  • 直接執行 js 程式碼

請求攔截

webView 傳送請求都會經過客戶端的請求傳送模組,客戶端可以在請求傳送出去之前做攔截,大家約定好一種 URI 的實現協議,如果符合實現協議的請求,就攔截下來進行約定協議解析,其他的就當做真正的請求傳送出去。

首先約定一個簡單的協議

eros://bmImage/camera?params={"imageNum":2,"allowCrop":true,"callbackId":"bmImage.camera1527235458519"}

eros            // 作為協議存在,用於做攔截的方式
bmImage/camera  // 用於約定是呼叫客戶端的方法名,可以是想要呼叫相機上傳兩種圖片的介面
params          // query 表示引數,其中有一個引數名叫 params 的引數是一個 json,是呼叫客戶端的方法所需要的三個引數
複製程式碼

不管 js 如何封裝,就是需要傳送一個請求出去,最好前端能做統一封裝通過 iframe 或者直接通過 ajax 傳送請求。

客戶端如何攔截

android 的攔截方式 shouldOverrideUrlLoading

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    // 根據協議判斷是否需要攔截
    if (true){
      // 解析協議路徑得知呼叫方法
      // 解析 query 得到引數
      // 通過反射的方式去呼叫對應的原生方法
      return true;
    }
    return super.shouldOverrideUrlLoading(view, url);
}
複製程式碼

iOS 的攔截方式(UIWebView) webView:shouldStartLoadWithRequest:navigationType:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    // 根據協議判斷是否需要攔截
    if (true){
        // 解析協議路徑得知呼叫方法
        // 解析 query 得到引數
        // 通過 AOP 的方式去呼叫去呼叫對應的原生方法
        return NO;
    }
    return YES;
}
複製程式碼

上述過程就完成了 js 向 native 的通訊的一種方式,客戶端完成了操作之後如何告知 js 後面會講到。這種方式不好的地方在於只能支援非同步的呼叫方式,網路 I/O 就決定了這種方式不支援同步。既然是 URI 的協議就會有長度限制,超長了請求就會被截斷

更為嚴重的是無序性和有丟訊息的可能,這也導致了這個方式非常不穩定,也是早期沒有其他選擇使用的方式。

彈窗攔截

js 呼叫彈窗時一般有 alert/confirm/prompt 三種彈窗,這三種彈窗對應客戶端都會有方法實現,可以直接做攔截。

var actionInfo = {
    type: 'eros',
    action: 'bmImage/camera',
    params:{
        "imageNum":2,
        "allowCrop":true,
        "callbackId":"bmImage.camera1527235458519"
    }
}

prompt(JSON.stringify([actionInfo]))
複製程式碼

android 攔截 prompt

@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    // 解析傳過來的字串判斷 type 型別是不是解析的方式
    if (true){
        // 解析協議路徑得知呼叫方法
        // 解析 query 得到引數
        // 通過 AOP 的方式去呼叫去呼叫對應的原生方法
        // 如果是非同步返回
        return true;
        // 如果是同步,待上面的程式執行完畢之後返回結果
        // return res
    }
    return super.onJsPrompt(view, url, message, defaultValue, result);
}
複製程式碼

iOS 攔截 prompt(使用 WKWebView)

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
    // 解析傳過來的字串判斷 type 型別是不是解析的方式
    if (true){
        // 解析協議路徑得知呼叫方法
        // 解析 query 得到引數
        // 通過 AOP 的方式去呼叫去呼叫對應的原生方法
        // 如果是非同步返回
        NSInvocation *invocation = [執行方法]
        [invocation invoke];
        return invocation;
        // 如果是同步,待上面的程式執行完畢之後返回結果
        return nil
    }else{
        執行對應的彈窗
    }
}
複製程式碼

這種方式比請求攔截好的地方是可以支援同步呼叫了。但是 iOS 中有兩種 UIWebView 和 WKWebView,前者在 webView 中遮蔽的彈窗的功能。後者雖然記憶體要比前者控制的好但是有很多相容性的問題。

js 注入上下文

上面的使用方式還是比較曲折,發展到現在有了 JavaScriptCore,也是現在大部分混合應用解決方案核心,JavaScriptCore 沒有 BOM 物件也沒有 DOM 物件,甚至還缺失一些瀏覽器的方法,但是這塊是 js 和 native 都能訪問到的公共區域。在開啟 webView 之後,往 js 的上下文中注入方法,供 js 進行呼叫。

iOS JavaScriptCore 注入(UIWebView)

// 獲取 WebView 中 JS上下文
JSContext *context = [webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//注入 callNative 函式方法
context[@"callNative"] = ^( JSValue * params )
{
    // 解析引數找到對應的方法進行處理
    // 同步回撥
    NSInvocation *invocation = [執行方法]
    [invocation invoke];
    return invocation;
    // 非同步回撥
    return nil
}
複製程式碼

js 呼叫方式

callNative({
    action: 'bmImage/camera',
    params:{
        "imageNum":2,
        "allowCrop":true,
        "callbackId":"bmImage.camera1527235458519"
    }
});
複製程式碼

android webView 注入

// 通過 addJavascriptInterface 將物件對映到 JS 物件
// android 物件
// js 的物件名
mWebView.addJavascriptInterface(new JavaScriptBridge(), "callNative");
複製程式碼

js 呼叫方式

callNative.bmImage.camera({
    "imageNum":2,
    "allowCrop":true,
    "callbackId":"bmImage.camera1527235458519"
})
複製程式碼

這種方式就更接近寫程式碼的方式了,不管是呼叫方式、傳遞引數的方式還是同步非同步回撥都更好了。但是這種方式也有需要注意的地方,首先需要注意客戶端注入的時機,在 loadUrl 之前注入是無效的,但是在 FinishLoad 之後注入可能 webView 已經呼叫了方法,此時會出現呼叫不到該方法,所以還需要其他的機制來保證這個問題。比如微信公眾號的 wx.config 介面。

native 呼叫 js

前面已經講了 js 呼叫 客戶端,js 在向客戶端發出呼叫指令之後,如果是同步方法,比如 獲取當前客戶端版本能立即得到結果,如果是非同步呼叫,之前每次呼叫客戶端的時候都傳遞了一個 callbackId,這個就是為客戶端回撥 js 做準備。

首先 js 會提供一個方法等待客戶端呼叫

window.nativeCallbackMap = {};
const callJs = (data) => {
    var data = JSON.parse(data);
    var callback = window.nativeCallbackMap[data['callbackId']
    if(callback){
        callback.call(null, data['resData'])
    }
    delete window.nativeCallbackMap[data['callbackId']
}
複製程式碼

iOS 呼叫 js

NSString *resDataString = [self _serializeMessageData:data];
NSString* javascriptCommand = [NSString stringWithFormat:@"callJs('%@');", resDataString];
if ([[NSThread currentThread] isMainThread]) {
    [self.webView evaluateJavaScript:javascriptCommand completionHandler:nil];
} else {
    __strong typeof(self)strongSelf = self;
    dispatch_sync(dispatch_get_main_queue(), ^{
        [strongSelf.webView evaluateJavaScript:javascriptCommand completionHandler:nil];
    });
}
複製程式碼

android 呼叫 js

final int version = Build.VERSION.SDK_INT;
// 因為該方法在 Android 4.4 版本才可使用,所以使用時需進行版本判斷
if (version < 18) {
    mWebView.loadUrl("javascript:callJs()");
} else {
    mWebView.evaluateJavascript("javascript:callJs()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            // js 的同步返回
        }
    });
}
複製程式碼

上述 js bridge 的實現大致就是現在大部分的客戶端與 js 的通訊方式,現在 webView 也豐富了自己的功能,有能力呼叫客戶端提供的方法,完成所有客戶端能做的功能,js bridge 設計完之後剩下的就是需求推動,根據所需的功能提供不同的方法供前端呼叫。

如果需要與原生頁面間互相通訊,應該約定一種 scheme,也可以理解成一種 URI 的實現,通過 js bridge 的介面呼叫客戶端(此時還可以傳一個回撥到客戶端,當客戶端完成某個操作之後返回該頁面執行回撥,比如日期選擇),客戶端解析協議,開啟對應的原生頁面,完成對應的操作。scheme 還是手機瀏覽器會識別的一種協議,如果有對應的 APP 可以直接呼起 APP,但是當你開啟客戶端頁面的引數太多時,你的 scheme 會變得超長,瀏覽器會將 URL 截斷,這個時候還需要簡單的短鏈服務轉化

淺談混合應用的演進

優點:

  • 首先具有所有 webView 所有的優點
  • 解決了單純 webView 的互動功能受限,能呼叫原生介面完成需求

缺點

  • 也無法避免 webView 所帶來的效能問題,開啟白屏時間長,使用者體驗較差,等問題,也存在受限與瀏覽器,及重複開啟需要重複載入等問題
  • 所有新需要客戶端提供的功能都需要客戶端發版
  • 隨著業務發展客戶端定義的介面必須向下相容,這會帶來很多冗餘程式碼

代表產品:

  • 公眾號使用到微信 sdk 的功能
  • AppCan、PhoneGap、cordova 等 hybrid 框架

小程式

淺談混合應用的演進

在 hybrid 混合應用穩定之後,大家發現功能上已經能滿足開發需求了,所以下個階段應該追求體驗和效能上的提升,就是 RN 的方案了,ReactNative 的方案已經逐漸被大家所熟知並逐步落到專案中,混合應用方案也是本文介紹的重點,後面會詳述。

這裡想先講一講小程式,因為在技術的演進上小程式才應該是下一小步的提升,並且小程式嚴格意義上來說並非 APP 的一種方案,更像是微信分發生態中的體驗進化,在使用公眾號這類 hybrid 的方案時,發現體驗和互動上的一些問題,比如載入白屏時間,頁面之間跳轉的互動,頁面內容的快取等等。

由於小程式現在實現方案面向開發者也是一個黑盒,我也是一邊瞭解一邊猜小程式如何實現的,小程式的框架包含兩部分:View 檢視層和 APP service。前者用來渲染頁面結構,後者用來做邏輯處理,介面呼叫。他們在兩個程式裡執行,有點類似在當前的頁面裡使用 web worker,關係如下圖:

淺談混合應用的演進

APP View

我們寫的檢視層和邏輯程式碼是分離的,WXML 和 WXSS 構圖了檢視層的程式碼,WXML 通過 wcc 工具轉換成 VDOM,WXSS 通過 wxsc 轉化 style 標籤。底層通過 WAWebview.js 來提供底層的封裝,每一個檢視就會有一個 webView 來渲染,這也就提高了頁面渲染效能的問題,多個檢視頁面時就會有多個 webView 程式,所以小程式對頁面層級是有限制的,記憶體受限。檢視層主要包括以下內容:

  • WeixinJSBridge 封裝和上述的 hybrid 的 jsBridge 一樣
  • 小程式提供的元件註冊,一些能操作 DOM 的 API
  • 渲染的實現:VDOM、diff、render UI(在高人知道下了解到渲染出來的本質還是 webview,在原生端只支援 flex 佈局,但是小程式裡還支援 web 的佈局,由此可以看出,這裡一定是 webView 的渲染,並非原生)
  • 頁面生命週期管理

APP Service

邏輯處理的程式碼全部載入到一個程式 APP service 中,和檢視 webView 不同,所有的程式碼邏輯都會一次性全部載入到這個程式中,因為主要的瓶頸還是來自於渲染效能,並且所有的邏輯程式碼都載入到程式中保證檢視切換的流程性,並且加上小程式有 2MB 大小的限制,在現在的網路環境下一次載入體驗會更好。APP Service 包含以下內容:

  • WeixinJSBridge 封裝和上述的 hybrid 的 jsBridge 一樣
  • 所有小程式提供的 API 方法注入,全域性方法注入
  • AMD 模組化實現

小程式的開發環境

小程式執行在開發環境中和線上環境是不同的,線上環境 iOS 和 android 都有真正的 webView 環境提供,在開發過程中小程式提供了一個 IDE,IDE 是基於 nwjs 實現的,釘釘客戶端也是基於這個實現的。其實就是在 PC 端的客戶端環境下儘可能提供原生能力,如果是移動端才會有的差異化能力就會 mock 掉。兩邊環境不同還體現在 APP Service 中,APP Service 主要是呼叫客戶端底層,所以底層的不同也影響著這層的封裝。

APP View 與 APP service 通訊

當我們理解了前面的 hybrid 的通訊原理,這裡的通訊就比較好理解了。小程式的 bridge 實現原理就和 hybrid 一樣了。iOS 和 android 就不多說了。基於 nwjs 的客戶端是通過 window.postMessage 實現的,使用 chrome 擴充套件的介面注入一個 contentScript.js,封裝了 postMessage 方法。

// 傳送訊息通過 
window.postMessage(data, ‘*’);
// 接受訊息通過
window.addEventListener(‘message’, messageHandler);
複製程式碼

小程式的推動主要來自微信平臺的大流量,這就是所謂的微信流量紅利,公眾號已經承載了傳播和拉新的低成本方式,但是體驗一直被詬病,限制於 hybrid 的體驗問題讓追求體驗的開發者逐漸無法忍受,此時小程式原生的元件,良好多頁面切換,幾乎沒有白屏時間的等待,讓大家又有了探索無限的可能。

優點:

  • 首先具有所有 hybrid 所有的優點
  • 無需安裝,極速開啟
  • 原生的元件有了體驗上質的提升
  • 效能上也有了新的飛躍,白屏時間,頁面切換也有了更好的體驗(為了減少白屏時間,小程式採用預載入的方案,而分不清哪個會是邏輯裡的下一個頁面,所以小程式將所有 webView 全域性預載入,這也是頁面層級和包大小限制的主要原因)

缺點

  • 只能用於微信平臺,如果有多端的使用者需求,開發成本增加了
  • 元件還是較少,很多操作 DOM 的方式也會有所限制,完成需求受限
  • 為了效能的體驗,包的大小受限,開啟頁面的層級受限

代表產品:

  • 各種客戶端的小程式

快應用

淺談混合應用的演進

快應用是對標微信小程式的一場阻截,幾大手機廠商聯合釋出這個方案,一瞬間吸引了大家的眼球,越來越多端讓前端追都追不過來(這麼多技術確實讓人很絕望,甚至前段時間大家去惡意灌水了很多大專案的 issue,但這也是前端蓬勃發展的表現,當這些前沿的技術落地在專案中甚至你只是完成一個 demo 的時候,你還是會有抑制不住的興奮和成就感)

快應用對自我的介紹是基於手機硬體平臺的新型應用形態,用的是新型應用形態,並非新技術,類似這樣的實現有 PWA,只是 PWA 缺少了手機硬體平臺的支援。

圖片來源:快應用釋出會PPT

快應用標準是由手機廠商組成的快應用聯盟聯合制定,快應用標準的誕生將在研發介面、能力接入、開發者服務等層面建設標準平臺。底層的硬體平臺提供底層 API 讓開發者呼叫,原生渲染元件,hybrid bridge 通訊,原理大致也與小程式實現類似,這裡就不詳細說明,下面是幾張快應用釋出會的 PPT 截圖,如果理解了上面的原理,這個應該就是比較好理解了。

淺談混合應用的演進

淺談混合應用的演進

淺談混合應用的演進

之所以說是小程式的一場阻截,小程式曾放話說,未來兩年內,小程式將取代 80% 的 APP 市場,而手機廠商並不希望大量的 APP 被取代,所以催生了快應用的落地。但是建立在幾大國內手機廠商硬體平臺上的方案,就目前來看支援性,通用性,社交性上都是比不上小程式的。兩者的前景不敢妄加揣測,但是小程式憑藉微信平臺的使用者量和使用者粘性,比幾大手機廠商實現的標準化還是一目瞭然的。

優缺點就不詳述了,一目瞭然

Flutter

淺談混合應用的演進

ReactNative 的開疆擴土進一步奠定了,React 的霸主地位,React 也由一個框架演進成了,以 React 為基礎的前端多端解決方案,技術棧的生態方案。google 怎麼可能放棄自己在科技領域的地位,即使是前端相關的技術,所以出了 Flutter 技術方案完成 APP 的一環。

藉由本身的 android 和 chrome 的 平臺優勢,準備重磅推出 Fuchsia OS,打造自己不基於 Linux 的底層系統,而 Fuchsia OS 欽定 UI Toolkit 就是 Flutter。Flutter 最大的改進就是自己重做了渲染引擎去渲染頁面,將混合應用的渲染效能推向了另一個高度。

Flutter 之於 RN 來講最大的區別在於渲染,脫離了 JSFramework 的 Component 遞迴傳遞和逐個計算繪製,更像是 canvas 繪製,將 UI 直接繪製出來,Flutter 都是在狀態變更時重新構建 Widget Tree,Flutter 的渲染引擎在將 Widget Tree 轉化成渲染的 Render Tree,最後交給作業系統呼叫 GPU 去渲染,Flutter 由 Dart 程式寫的,Dart 和 native 之間仍然存在一個介面,可以進行資料編碼和解碼,這可能比 JavaScript bridge 快好幾個數量級。

淺談混合應用的演進

使用 Dart 是整個框架不太被前端所接受的問題,但是程式碼都是相通的,上手還是很快,嘗試 demo 期間還是很快就能模仿出一個頁面,語言上的爭論就不說了,畢竟都不如 PHP。

由於自己使用 Flutter 還在 demo 階段,並沒有真正圍繞 Flutter 做過相關的解決方案,具體的細節實現也沒有清楚的認知,也不適合展開詳述,很早之前以向量圖起家的 Adobe 也嘗試過類似的方案,但是最終沒有把這條路走下去。

如果有興趣可以移步:

weex 和 ReactNative

淺談混合應用的演進

在講這兩種混合應用之前,再囉嗦幾句,上面大致瞭解了各種混合應用的方案,這些方案瞭解其原理和使用場景,在合適的場景去使用對應的方案,不要為了落地某項方案而把業務生搬硬套,沒有一種方案是絕對的好,在不同的業務需求的驅動下權衡利弊再做決策。

這兩者一直有人在試圖去比較分析得出利弊,看哪種更好,甚至有人偏激的認為 Weex 就不配合 RN 相提並論,但是我還是想說理性的看待這個問題,客觀的面對前端技術,曾經 React 和 Vue 也是這樣的差距,直到現在依舊有人認為使用 Vue 低俗,使用 React 高雅,但雅俗之分真的如此嗎?還是應該理解其原理,辨別自己的業務場景,團隊學習成本,開發體驗等等一系列的原因,然後再做評判。

就目前的各方面情況講,RN 確實更優,橫空出世,背靠當時火的不行 React,一路都是風光無限。這種解決方案出來之後,如果沒有競爭者的挑戰,沒有對比,沒有選擇,也不一定是好事兒,雖然現在兩者還有很大的差距。

我猜 Weex 始於 KPI,畢竟大廠造輪子來升級是非常好的途徑之一,但是往後發展,卻成了兩大陣營完善生態的方案,現在基於 React 的一整套的前端解決方案覆蓋PC、Web、Native 可謂是成了大公司前端方案的標準套路,後起之秀 Vue 用良好的開發體驗和低門檻的入門方式開始搶佔使用者,各種前端培訓學校讓一些前端不懂 js 基礎,但是 Vue 溜的飛起。但Vue 並沒有形成對 Native 的覆蓋,這個可能也是 Weex 和 Vue 一拍即合的原因,雙方都有需求,就開始了合作。

扯會正題,在大前端逐漸融合的背景下,作為以 Vue 建立技術棧的團隊開始尋找客戶端的方案,做技術選型開始考慮業務達成、團隊學習成本、開發效率,效能效率等問題,我們一開始也是將 Weex 和 RN 作為比較,在上一家公司使用的是 RN,但是現團隊建立技術棧基於 Vue,考慮到第二個因素偏向 Weex,實際調研過程中發現 Weex 的坑確實很多,但是好在有很多問題已經有解決方案了,當然不管想要使用上述兩種方案,都需要有一定的原生能力。實際開發過程中發現隨著對 Weex 的瞭解越來越多,開發效率也越來越快,入坑之後才發現了第三個和第四個甚至第五第六個優勢。

至於 Weex 最大的賣點,相容三端,Web 端這個優勢每個人都有自己的看法,我們嘗試了去相容 Web 但是發現反而犧牲了開發效率,有相容的時間,單獨開發一套也出來了,並且更重要的是由於使用者習慣的不一致,Web 端和 Native 針對的使用者群體也不一樣,在這個流量就是金子的環境下犧牲使用者體驗和開發效率去相容 Web 並非是我們的初衷。

當然也遇到了一些問題,一開始 Weex 沒有託管 Apache 的時候還有 issue,很多問題確實不能及時得到解決,所以決定脫離 Weex 的所有 module,自行開發所有 module,重新設計,這也讓我們對專案有了一些控制。

決定了自行開發 module 和元件之後,減少了對 Weex 本身的依賴,專案本身受到的限制也越來越小,業務很快也完成了。當然現在類似 demo 跑不起來,毀滅式的升級,市場元件無法接入,bug 橫飛,元件不足以完成業務功能,相容性不足,熱更新,公共檔案導致包過大,社群經營不好等等這些問題,也都是一個技術產品成長的必經之路。

兩種方案在選型的時候,一定有可取的地方才會選擇,工程師的精神就是趟坑,找準正確的方向然後一往無前,兩種方案都有已經上線的優秀產品,說明是這條路至少是能走通的,當然我們也在過程中總結了我們的解決方案,希望能幫助在 Weex 路上舉步維艱的同行人,不管選擇哪種方案,選擇了就把他做好。Eros專案地址請戳(不要吝嗇你的 star)Eros文件地址請戳。我們公司已有三個專案通過 Eros 上線,也有幾十個應用通過 Eros 釋出上線。

當然還有很多優秀的方案沒有一一列舉,比如:kotlin、WebAssembly,每個方案都沉澱了很多前端工程師的積累,提供了各種能落地可實行的方案 phonegap -> cordova、mui、appcan、apicloud 等等

下一篇文章會詳細的講述 Weex 的原理

相關文章