1. 程式人生 > 其它 >跨端開發浪潮中的變與不變

跨端開發浪潮中的變與不變

大家好,我是莫覺。今年我將擔任阿里巴巴 D2 終端技術大會「跨端技術」的出品人,藉由此次機會,寫下本文聊聊跨端技術的現狀與未來,希望可以給大家帶來一些新的啟迪。

自 90 年代初開啟 PC 時代以來,隨著行動網路的快速普及,在 2010 年左右,進入移動時代、IOT 時代,各種移動互聯裝置不斷湧現,除了最常見的 PC、Pad、智慧手機外,它還可能是小小的一塊智慧手錶,也可以是一個大屏終端。智慧裝置層出不窮,填滿了人們生活的各個角落,裝置的系統型別、螢幕大小等也是愈發碎片化。

資料顯示,當前使用者平均擁有 5 臺智慧裝置;預計到 2022 年底,中國物聯連線量將會超過 100 億裝置。智慧裝置的增長勢頭迅猛,使用者對於智慧家居、智慧辦公等跨裝置互聯需求愈發旺盛,意味著跨端開發的需求也將激增。

過去,不同型別的硬體開發是相互獨立的,手機的歸手機,電腦的歸電腦。同一型別的硬體如果系統不同,開發也是相互獨立的,iOS 的歸 iOS,Android 的歸 Android。這背後是大量的重複勞動,一次開發滿足全場景使用是必然趨勢。正因如此才有了層出不窮的跨端方案探索。

 

跨端技術的變與不變

縱觀跨端技術的演進歷程,從 Web 容器 ,到泛 Web 化容器,再到自渲染,技術方案一直都在快速變化,從一個方案遷移到另一個方案,其成本與二次開發相當。如何才能做到無論跨端技術方案怎麼變化,業務程式碼始終保持不變呢?要解決這個問題,我們還得重新回顧一下跨端技術演進。

跨端技術演進

1. Web容器方案:

瀏覽器和 WebView 本來就都是 W3C 規範下的標準化 Web 容器,因此 Web 頁面天生就能輕鬆投放到任意瀏覽器、WebView 之中。從開發成本、標準統一、生態繁榮上來說,Web 方案基本是不二之選;不過 Web 本身也存在一些問題,例如頁面載入慢、記憶體消耗大、互動體驗差。儘管在 Web 基礎上又衍生出了 Hybrid、PWA、PHA 等一系列 Web 能力增強的方案,讓效能和體驗得到了非常不錯的提升,但相對於 Native 效能和體驗的劣勢卻仍然存在。Web 的高效和動態性是 Native 開發難以企及的,Native 的效能和體驗也是Web一直追求的,有沒有一種倆全齊美的方式讓我們在倆者之間找到一個平衡點?React Native 的出現給開發者帶來了新的思路。

2. 容器化 Native 方案:RN / Weex

為了彌補 Web 容器方案效能和體驗上的不足,同時也能擁有 Web 的研發效率;類 RN 容器儘可能的取長補短,保留了 JS 引擎,以便最大程度的對接前端生態,提升開發效率;出於效能和體驗上的考慮在渲染上則複用了 Native 的渲染管線,使用原生渲染保障了效能和體驗;通過類似的容器方案即可實現跨端,主流的 RN、Weex 都是採用這種方案。容器化 Native 方案看起來既能擁有 Native 的體驗又能擁抱 Web 的繁榮生態非常完美,但它實際上還是存在問題:比如難以抹平的一致性、W3C標準支援不足、研發體驗、周邊生態缺失等。儘管如此容器化 Native 方案仍是成功的,它迅速拓展了前端的邊界。

3. 自渲染方案: Flutter

Web 容器存在效能問題,Native 容器化存在一致性問題;那麼是否可以繞開 Native 渲染管線自建渲染引擎,解決跨端一致性問題呢?答案是必然的,Flutter 基於 Skia 實現了一套自繪引擎;因此 Flutter 的特點是一致性高,效能好;但它也有著自身的缺點由於設計上採用全新的思路,拋棄 JS 而使用 Dart 作為開發語言,所以不管對於 Native 研發還是前端研發都有一定的學習成本,不過站在開發者的角度來說學習成本並不是特別高,更大的問題是前端生態需要重建,工程相關的 CI、CD,生態相關的搭投、智慧化都需要重新建設,成本巨大。正是這樣的原因,讓不少前端開發者望而卻步;那麼自然而然的就有各種各樣的探索;上層讓 Flutter 更好的對接前端生態,底層使用 Flutter 自繪渲染保證多端的渲染一致性,這裡我們就不再展開了。

4. 適配小程式的一碼多投跨 App方案:

小程式幫助頭部 App 建立起封閉流量體系和容器管控的同時,也因其雙執行緒模型及自建 DSL 引入帶來了新的跨端問題。隨著各大廠商紛紛實現自己的小程式容器、快應用,跨端容器的碎片化愈演愈烈。其實現方案大致可分為兩類:編譯時與執行時。

  • 編譯時思路:在編譯時將框架的業務程式碼轉換為小程式原生 DSL;

  • 執行時思路:通過執行時框架對接小程式 setData 的方式來實現跨端。

此類框架非常多。小程式的一碼多投實際是一種商業模式下的無奈與技術妥協。

演進中的變與不變

 

基於上述跨端技術演進的介紹,會發現無論跨端技術方案如何變化,跨端的目標始終不變,一直保持著對效能體驗、交付效率和多端一致性追求,其方案本質無非是如何做平衡與取捨而已。跨端技術方案一直在變化,基於方案的終端能力要求、容器、Bridge 等在變,業務開發框架、基礎設施也在變。如何在這些變化中尋找不變的存在,通過控制變數,讓混沌變得有序,讓跨端技術演進有跡可循?是否可以把每次方案迭代必然變化的「容器」作為唯一的變數,保持業務程式碼、基礎設施、研發生態、底層能力等的不變?

  • 換個新容器,業務程式碼無需改動依然能在新容器上穩定執行?

  • 換個新容器,周邊配套設施、研發生態是否可延續使用?

  • 換個新容器,對端能力的要求是否能保持不變?

基於上述變與不變的思考,「統一跨端容器規範,實現容器標準化」必然是一條正確的大道。只要按照該標準實現的容器,就能隨意進行切換,不影響上層業務、框架、基礎設施,讓跨端也能輕鬆“write once, run anywhere”。那麼該如何進行容器標準化呢?

如何進行標準化

 

從 Web 的思路來進行思考,很容易找到答案,那麼瀏覽器是怎麼進行標準化的呢?我們先來看看瀏覽器架構,Web是依託瀏覽器核心完成渲染的,瀏覽器核心執行 HTML、CSS 、JS 並渲染成開發者預期的 UI 介面。核心主要由瀏覽器引擎和 JS 引擎組成;JS 引擎執行 JS,遵照的是 TC39(ECMAScript) 標準,瀏覽器引擎負責除執行JS外的其他工作例如 DOM、CSS,遵照的是 W3C 的標準,兩者比較獨立又有很強的配合,這些引擎在不同瀏覽器中的實現也是不一樣的。


這種架構下最核心的部分是 WebCore,它是載入和渲染的基礎能力;對於這部分各瀏覽器是共享的;其他的部分(圖中灰色的部分)雖然遵循相同的標準,但實現存在差異,對於不同瀏覽器由於平臺差異/第三方依賴不同/需求不同等多方面原因,允許其按照自己的方式來設計和實現。借鑑瀏覽器的思想,在跨端容器上我們也完全可以這樣做,基於相同標準實現跨端容器能大大減輕我們的開發工作,基於 W3C 標準則能夠讓我們相對輕鬆的對接前端生態。在阿里內部也確實是這麼做的。

在阿里標準化實踐上,我們拉通了集團涉及跨端容器的幾大業務單元,並參考 W3C/WHATWG 標準和業務需要從 CSS/WebAPI/橋通道四個方面制定了標為什麼會選擇實現子集,而不是實現全集呢?主要是平衡了效能、效率後的考慮;如果實現規範全集研發效率、研發體驗上無疑是最棒的;但對於跨端容器來說則會遇到各種各樣的問題,例如圓角、陰影等;類似的案例還有很多,本質上是 Web 和 Native 最開始的設計思路就完全不同,強行適配會導致效能嚴重的下降;除此之外瀏覽器已經發展許多年了,相關的規範非常多,有大量的歷史包袱存在,在移動、IoT 上效能仍然是一個非常有挑戰的課題。

那麼是否制定了 HTML、CSS、Web API 標準子集,就能對接前端生態了嗎?我認為還不夠,從現狀上看不同的跨端容器對於標準的實現有著相當大的差異,也會導致跨端研發生態不能統一,很多情況下都需要自己造輪子;現有的前端生態,跨端生態很多都不能直接使用;例如我們常用的除錯能力,由於容器實現 inspector 各不相同,現有的 Devtools 也很難直接使用,大多會開發自己的 Devtools;比如 WeexDevtools、AJXDevtools 雖然都是基於遠端除錯協議來通訊的,但實現都是獨立的。再比如 List 元件,幾乎每個跨端容器都需要 List 元件解決列表渲染的問題,但又都是獨立實現的自定義 List 元件。在這些方面我們花費了大量的精力,如果核心能力上我們也能和 WebCore 一樣,共享 WebCore 的能力,那麼我們就能建設一個更好的跨端核心,也能把精力集中在優化業務領域上,構建更好的、更適合自己的業務容器。

跨端的核心訴求是一次開發全場景使用,我們通過跨端方案解決了多端開發問題,通過 Native 跨端容器解決了效能、體驗問題,通過自繪容器解決了雙端不一致問題;那麼該如何對接前端生態,提升研發效率,在生產環境中發揮他應有的價值則是我們要不斷思考的。標準化是趨勢,千里之行,始於足下;九層之臺,起於累土;API 的標準化已經走出了第一步,讓我們繼續建立容器標準,建立跨端研發標準;通過標準化更好的對接前端框架、前端生態,幫助企業實現降本增效,幫助業務實現快速增長。

作者 | 莫覺