国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > 深入解析基于 Flutter 的 Web 渲染引擎「北海 Kraken 」技術(shù)原理

深入解析基于 Flutter 的 Web 渲染引擎「北海 Kraken 」技術(shù)原理

時間:2023-08-16 14:57:02 | 來源:網(wǎng)站運(yùn)營

時間:2023-08-16 14:57:02 來源:網(wǎng)站運(yùn)營

深入解析基于 Flutter 的 Web 渲染引擎「北海 Kraken 」技術(shù)原理:

寫在前面

大家好,我是染陌,這是我在 全球開源技術(shù)峰會 GOTC 上的一個 topic ——《基于 Flutter 的 Web 渲染引擎「北海 Kraken」》。我主要從技術(shù)角度來分享 Kraken 的一些實現(xiàn)原理以及關(guān)鍵的技術(shù)特性,現(xiàn)在整理成文字版分享給大家。

Kraken Github:https://github.com/openkraken/kraken

Kraken 官網(wǎng):https://openkraken.com/

北海的技術(shù)背景

說到北海的技術(shù)背景就不得不提及跨端技術(shù)的演進(jìn),很多同學(xué)應(yīng)該都比較熟悉跨端技術(shù)的歷程了,我還是簡單講一些。

我們知道,瀏覽器是最成熟的天然跨平臺方案。早在 PC 時代,瀏覽器已經(jīng)成為了互聯(lián)網(wǎng)的入口,大家都會習(xí)慣性通過瀏覽器來進(jìn)行網(wǎng)頁的瀏覽以汲取各種信息,當(dāng)時我們把這種上網(wǎng)的方式叫做“沖浪”。然而到了移動時代,瀏覽器在移動設(shè)備上并沒有一個搶眼的表現(xiàn),反之因為內(nèi)存大、弱網(wǎng)環(huán)境白屏久、傳感器能力缺失(標(biāo)準(zhǔn)跟進(jìn)慢)等問題使各種質(zhì)疑不絕。

為了彌補(bǔ)上述瀏覽器在移動端的一些不足,出現(xiàn)了 Hybrid 技術(shù),在 Web 之上通過容器的能力實現(xiàn)一些非標(biāo)準(zhǔn)化的超集,同時也通過 prefetch、離線包等各種技術(shù)來提升首屏的加載性能。

此后,出現(xiàn)了類 RN 的方案(典型代表 React Native),它的原理是通過 JS engine 將 Native 控件與前端生態(tài)實現(xiàn)一個橋接,通過 Web 開發(fā)業(yè)務(wù)邏輯提升效率,而向下通過 Native 控件渲染來提升性能及體驗。但是這類方案的缺點是無法完全抹平兩端的差異,沒有解決一致性的問題,而最終將復(fù)雜度暴露給了開發(fā)者。

Flutter 作為跨端屆的新寵,這兩年也獲得了越來越多的關(guān)注,下面介紹一下 Flutter。

Flutter 的優(yōu)點是性能好、由于其通過自繪渲染使得跨端一致性高,但是它也有它自身的缺點,比如生態(tài)自成一派,既不是前端也不是 Android/iOS。

這就是引出了一系列的問題。

在面對如此多的問題以及切換的高成本的同時,我們也期望通過 Flutter 給我們的業(yè)務(wù)帶來更多的技術(shù)的可能性,同時改善 Web 容器在端上的一些性能及體驗問題。那么,引入一項新技術(shù)的第一步是解決引入這項新技術(shù)的成本問題,所以我們積極探索一種將前端生態(tài)與 Flutter 結(jié)合起來的方案。

于是產(chǎn)生了本次 topic 的主角——北海 Kraken。

Kraken 是一款高性能 Web 標(biāo)準(zhǔn)的自繪渲染引擎,具有高性能、易擴(kuò)展、基于 Flutter 以及 遵守 Web 標(biāo)準(zhǔn)的特點。

下面我列舉了一些北海在阿里的一些應(yīng)用場景,在 C 端 APP 或者 IoT 設(shè)備上,北海都有相關(guān)的落地。

北海的技術(shù)原理

在介紹 Kraken 的技術(shù)原理之前,我先演示一下如何開發(fā)一個 Kraken 應(yīng)用。因為 Kraken 是基于 W3C 標(biāo)準(zhǔn)來開發(fā)的 Web 渲染引擎,所以上層是框架無關(guān)的,無論開發(fā)者使用的是 Vue 或者 React 還是 Rax 都可以在 Kraken 上進(jìn)行一個應(yīng)用開發(fā)。

以 Vue.js 開發(fā)為例,下面是我用 Vue 官方提供的 vue-cli 起的一個項目。具體的代碼見官方示例。

可以看到的是,最左邊是 Vue 的相關(guān)代碼,右邊分別是該應(yīng)用在 Chrome(左)上跑的結(jié)果以及在 Kraken(右)上跑的結(jié)果,大家可以看到結(jié)果是完全一致的。

了解了如何開發(fā)一個 Kraken 應(yīng)用 ,我們再來理解一下 Kraken 的技術(shù)原理。為了大家更好地理解,首先我們來比較一下 Flutter 于 Webview 的渲染流程。

WebView 的渲染流程相信大家非常熟悉了,面試中非常經(jīng)典的題目就是一個 URL 輸入如何最終渲染到屏幕上了??偟膩碚f就是解析 HTML、JS 以及 CSS 文件,執(zhí)行相應(yīng) JS 調(diào)用 DOM API,最終會生成 DOM Tree 以及 CSSOM Tree,然后會計算最終得到 Render Tree,經(jīng)過 Layout 以及 Paint 流程生成一系列的 Layer,最終通過合成以及光柵化渲染到屏幕上。

再看 Flutter 這邊,F(xiàn)lutter 經(jīng)典的三棵樹——Widget Tree、Element Tree 以及 RenderObject Tree。Widget Tree 對應(yīng)到前端類似于前端框架這層,而 Element 與 DOM Tree,RenderObject Tree 與 Render Tree 分別對應(yīng),最終也會通過 Layout 以及 Paint 一系列計算生成 Layer,然后通過合成以及光柵化渲染到屏幕上。

那么,我們再將前端框架加入到我們整個流程中進(jìn)行一個更加直觀的對比,這里還是以 Vue.js 為例。

Vue.js 會在運(yùn)行時生成一系列 Vdom 產(chǎn)生 Vdom Tree,再通過 platfom 的抽象調(diào)用具體平臺的 API。

那么我們就會發(fā)現(xiàn),只需要把我用紅框圈出來的部分的流程進(jìn)行互換,就可以實現(xiàn)我們最終想要實現(xiàn)的效果(上層 Web 開發(fā),下層基于 Flutter 進(jìn)行渲染)。

基于以上設(shè)想,那么北海的渲染流程就出來了。

目前主流的前端框架都會將產(chǎn)物打成一個 JS Bundle,通過標(biāo)準(zhǔn)的 DOM API 去操作具體的視圖,而 HTML 內(nèi)一般只有一個根結(jié)點。在 Web 下,頁面會先請求 HTML 文件,再解析 Script 標(biāo)簽去加載對應(yīng)的 JS 文件。而 Kraken 的入口設(shè)計成了一個 JS 文件,這樣做可以減少一次請求,加快首屏的渲染。

該 JS 文件會在 JS Engine 中執(zhí)行,Kraken 的 runtime 通過 JS Engine Binding 的方式提供了一系列 Web 標(biāo)準(zhǔn)的 API 接口,調(diào)用相應(yīng) API 會執(zhí)行相關(guān)邏輯并創(chuàng)建一系列需要發(fā)送給 Dart 層處理的指令,指令通過一個 struct 進(jìn)行存儲。C++ 通過 FFI 將相應(yīng)的指令底層的 address 發(fā)送到 Dart 這邊,Dart 處理相關(guān)指令并生成 Dom Tree。同樣的,CSS 也會通過 Parser 生成對應(yīng)的 CSSOM Tree,最終會結(jié)合生成 Flutter 的 RenderObject Tree,經(jīng)過 Layout 以及 Paint 的一系列計算,生成對應(yīng)的一系列 Layter,然后通過合成光柵化最終上屏顯示。

同樣的,在最新的實現(xiàn)中,我們考慮到了 SSR 應(yīng)用的場景,所以加入了 HTML 為入口的北海應(yīng)用開發(fā)方式,通過 HTML Parser 即可解析對應(yīng)的 HTML 文件,后續(xù)流程是一樣的。SSR 的支持也讓首屏的秒開率更上一層樓。

那么了解了 Kraken 的整個渲染流程,那么我們?nèi)绾位?Flutter 去完成 Web 標(biāo)準(zhǔn)的渲染引擎的開發(fā)呢?

那么要基于 Flutter 去做這個事情,就必須先了解 Flutter 的架構(gòu)。

Flutter 最上層是 Dart 實現(xiàn)的 Framework,包含了響應(yīng)式框架、官網(wǎng)組件庫以及實現(xiàn)布局與繪制協(xié)議的部分。中間是 C++ 實現(xiàn)的 Flutter Engine,他是渲染流程的下半部分,提供了一些基礎(chǔ)能力,以及將 layer 合成以及光柵化后輸出。最下層的 Embedder 層,則負(fù)責(zé)具體 platform 的一些實現(xiàn),以實現(xiàn)跨平臺。

不難發(fā)現(xiàn),最 Dart Framework 的 Widget 是對 UI 的抽象,實現(xiàn)了一套響應(yīng)式框架,對應(yīng)到前端就是 Vue / React 等前端框架。而下方的布局協(xié)議,可以對應(yīng) W3C 的標(biāo)準(zhǔn)來實現(xiàn)一套基于前端標(biāo)準(zhǔn)的布局與繪制協(xié)議。

那么我們就可以得出北海的架構(gòu)設(shè)計。

先看左邊,左邊還是上面介紹的 Flutter 的整體架構(gòu),F(xiàn)lutter 的 Widget 能力可以通過插件的形式注冊到 Kraken 中去,成為一個前端標(biāo)準(zhǔn)的 Tag,JS 可以動態(tài)化地調(diào)用及控制渲染。整個左側(cè)的 Flutter 架構(gòu)支撐了上層的 Flutter 生態(tài),使 Flutter 生態(tài)也可以通過插件的形式融合到整個 Kraken 的渲染體系中去。

右邊是 Kraken 的架構(gòu)實現(xiàn),Kraken 的實現(xiàn)并沒有把實現(xiàn)侵入到 Flutter Engine 中去。在 Dart 層,通過實現(xiàn) W3C 標(biāo)準(zhǔn)的一系列布局與渲染能力,為上層提供了一些列標(biāo)準(zhǔn)化的能力,比如 Element、CSS、以及各種 Web 標(biāo)準(zhǔn)的 Module 等。在上層 Kraken 的 runtime 通過 JS Engine Binding 的方式提供了一系列 Web 標(biāo)準(zhǔn)的 API 接口,調(diào)用相應(yīng) API 會執(zhí)行相關(guān)邏輯并創(chuàng)建一系列需要發(fā)送給 Dart 層處理的指令,指令通過一個 struct 進(jìn)行存儲。C++ 通過 FFI 將相應(yīng)的指令底層的 address 發(fā)送到 Dart 這邊,最終 Dart 根據(jù)指令調(diào)用前面說的標(biāo)準(zhǔn)化能力,以完成對接。通過該實現(xiàn),為上層的前端生態(tài)提供了支撐,憑借豐富的前端生態(tài),開發(fā)者可以享受前端生態(tài)帶來的高效的開發(fā)體驗。

關(guān)鍵技術(shù)特性

首屏的加載性能是一個 C 端場景的關(guān)鍵指標(biāo),長時間的白屏?xí)O大地影響用戶體驗。

Kraken 在 首屏初始化時需要創(chuàng)建大量的節(jié)點,大量的時間耗費(fèi)在通信上,所以優(yōu)化首屏性能迫在眉睫。

在上面技術(shù)原理部分我們知道,Kraken 需要通過 Bridge 來完成 C++(JS Engine) 與 Dart 之間的通信,以達(dá)到將指令傳遞到 Dart 層的目的,Bridge 的架構(gòu)也進(jìn)行了三個版本的演進(jìn)。

最初的第一代方案,我們侵入了 Flutter Engine,使數(shù)據(jù)從 JS Engine 傳遞到 Flutter Engine 中,然后通過 native bingding 最終將數(shù)據(jù)發(fā)送給 Dart 層。這一代的方案非常明顯的缺點是侵入了 Flutter Engine,開發(fā)時需要編譯 Flutter Engine 需要耗費(fèi)大量的時間。同時,對于 Kraken 的架構(gòu)來說,侵入 Flutter Engine 也并不是一個合理的設(shè)計。

后來出現(xiàn)了 Dart FFI,可以實現(xiàn) C++ 與 Dart 之間的高效通信,所以產(chǎn)生了第二代方案。第二代 Bridge 方案通過將 JSON 數(shù)據(jù)序列化后,通過 Dart FFI 將數(shù)據(jù)傳遞到 Dart 層,Dart 層再通過 JSON 的反序列化以拿到最終的數(shù)據(jù)。這代方案比起上一代方案可以解決侵入 Flutter Engine 的缺點,但是引入了字符串的拷貝以及 JSON 序列化反序列化的時間長的問題。

為了解決上述問題,于是產(chǎn)生了第三代 Bridge 方案。第三代 Bridge 方案通過共享內(nèi)存的方式定義了一個標(biāo)準(zhǔn)的 40 Bytes 的 Struct 來存儲指令,而通過 Dart FFI 傳遞的只是指令的地址,C++ 跟 Dart 兩邊都依賴地址來訪問相關(guān)數(shù)據(jù)。這樣做解決了 JSON 序列化反序列化的問題,節(jié)約了時間,并且少一次數(shù)據(jù)拷貝。同時,由于內(nèi)存是 40 Bytes 對齊的,可以提高內(nèi)存的訪問效率。

下面是一些實際線上頁面帶來的首屏收益。

無限滾動的長列表是困擾前端開發(fā)者很久的歷史性問題了,大量的 layout 導(dǎo)致頁面卡頓,以及滾動時 Paint 的時間長導(dǎo)致滾動掉幀,頁面的體驗非常糟糕。社區(qū)也有非常多的前端的解決方案來處理該問題,而在 Kraken 上,我們也期望在容器層解決該問題。

在 Android 跟 iOS 上也分別有 RecyclerView 以及 TableView 來解決該問題,他們的原理分別是在可視區(qū)域 viewport 外定義一塊緩沖區(qū)域,當(dāng)節(jié)點超過該區(qū)域時進(jìn)行動態(tài)釋放,進(jìn)入該區(qū)域時動態(tài)創(chuàng)建,以及通過一系列節(jié)點進(jìn)行屬性替換的方式來保證節(jié)點數(shù)不爆炸。Flutter 中也提供了類似實現(xiàn) Sliver,那么我們能否用 Sliver 賦能前端解決該問題呢?

Kraken 定義了一個新的 display 屬性 sliver,通過將節(jié)點的 display 屬性設(shè)置為 sliver,則可以直接使用 Flutter 的 Sliver 能力,以達(dá)到節(jié)點超出可視及緩存區(qū)域后動態(tài)回收的一個能力??梢钥吹轿覀兪褂?1000 個卡片的 DEMO 進(jìn)行測試,sliver 下比起 block 有明顯的收益。

同時,該標(biāo)準(zhǔn)也已經(jīng)在 W3C 中文興趣小組 進(jìn)行了討論,期望在大家討論充分以及達(dá)成共識后,嘗試將此提案向 W3C 進(jìn)行提交,反哺前端社區(qū)。

一個大前端團(tuán)隊往往既有客戶端也有前端,會沉淀一系列的端上的能力。不同的需求會有不一樣的技術(shù)選型,譬如說一個播放器往往是通過 Native 技術(shù)去開發(fā)的。我們期望將端上的能力(包括 Flutter Widget、Web、Native 以及三方 SDK 等)進(jìn)行整合,融合成一個大前端的端開發(fā)體系,所以在 Kraken 內(nèi)我們?nèi)绾握隙松系倪@一系列能力呢?同時,我們也期望按需引入,能做到包體積的優(yōu)化。在不同的業(yè)務(wù)域,我們期望可以快速地進(jìn)行定制化開發(fā),快速形成一套垂直業(yè)務(wù)域的領(lǐng)域能力。

Kraken 提供了一套擴(kuò)展能力來解決上述問題,通過渲染能力擴(kuò)展接口,開發(fā)者可以將開發(fā)完成的符合標(biāo)準(zhǔn)的 Flutter Widget 以及 Native 的渲染能力快速集成到 Kraken 體系中去,最終通過 JavaScript 來提供一個動態(tài)化調(diào)用的能力。同樣的,通過 MethodChannel,開發(fā)者可以通過該通道調(diào)用一些 Native 或者 Dart API 的能力,譬如說一些二方或者三方的 SDK 能力。

開發(fā)者可以通過擴(kuò)展能力自定義業(yè)務(wù)域需要的能力,按需拔插以達(dá)到包體積優(yōu)化的目的。同樣的,注冊到 kraken 的插件都可以通過 JavaScript 代碼控制,提供了動態(tài)性。

下面是一系列在 Kraken 內(nèi)部擴(kuò)展 Flutter Widget、Native API 以及 Native 播放器的 Demo。

下面是提升可交互性。在介紹 Kraken 的可交互性之前,我們先來看一下在 Web 下的一些交互問題。

在 Web 下開發(fā)富交互能力的應(yīng)用時,前端開發(fā)者往往需要引入一個額外的 lib 來提供增強(qiáng)的手勢能力(譬如說 Hammer.js 這樣的手勢庫)。那么當(dāng)前端開發(fā)者引入 lib 時,就會導(dǎo)致加載 index.html 以后,還需要額外的請求對應(yīng)的 JS 庫,造成一次額外的請求開銷的同時延長了首屏的可交互時間。

當(dāng)用戶在屏幕上進(jìn)行某個操作時,由于用戶操作的方式可能是用戶的手,也可能是 Apple Pencil 或者鼠標(biāo)這樣的設(shè)備。所以在 W3C 標(biāo)準(zhǔn)中,將用戶操作可交互應(yīng)用的觸點抽象為一個 pointer,這些 pointer 會根據(jù)操作形成一個手勢,分別是 down、move、up 三個過程,其中 move 可省略(譬如說 click)。

在 Web 中,需要將這一系列 pointer 給 dispatch 到 element tree 上,通過冒泡將這些 pointer 頻繁地發(fā)送到 JS 層,然后 JS 再通過封裝 Touch API 來完成對交互的識別。這樣做帶來幾個問題,首先頻繁地將 pointer 從 C++ 傳遞到 JS 帶來了不必要的開銷,此外封裝標(biāo)準(zhǔn)的能力也會造成額外的開發(fā)成本,易用性并不突出。此時,如果使用社區(qū)的一些方案,也會導(dǎo)致非標(biāo)準(zhǔn)化使標(biāo)準(zhǔn)不對齊導(dǎo)致同個應(yīng)用中的不同頁面有不一致的交互體驗。

為了解決上述問題,我們期望從標(biāo)準(zhǔn)化、易用性、標(biāo)準(zhǔn)化幾個方面提供一套標(biāo)準(zhǔn)化的交互能力。通過封裝底層的 pointer 來得到不同的手勢能力,使開發(fā)者可以快速開發(fā)富交互的應(yīng)用。

下面是 Kraken 中增強(qiáng)交互能力的流程圖。當(dāng)用戶進(jìn)行某些交互操作以后,每一個觸點的 pointer 會從 Native 傳遞到 Kraken 中,Pointer 會同時分發(fā)給 GestureManager(手勢識別器管理類)以及 Scroll 識別器。GestureManager 會識別開發(fā)者通過 Web 標(biāo)準(zhǔn)的監(jiān)聽行為(EventTarget.addEventListener)來注冊以及分發(fā)給對應(yīng)的手勢識別器,同樣 Scroll 識別器也會被分發(fā) pointer。這些識別器被加入到 Flutter 的競爭場進(jìn)行手勢競爭,以保證只觸發(fā)某一個具體操作(交互可控)。Scroll 識別器會觸發(fā)滾動區(qū)域的滾動操作,手勢識別器則會通過標(biāo)準(zhǔn)的 Web 流程進(jìn)行冒泡以及 dispatch,最終開發(fā)者通過監(jiān)聽事件完成自定義行為。

開發(fā)應(yīng)用時,調(diào)試能力是必不可少的,前端開發(fā)效率高不止要歸功于繁榮的生態(tài),友好的開發(fā)調(diào)試體驗一樣是提升效率的神器。

Kraken 抽象了 Inspector 以通過 Chrome DevTools Protocol 來對接 Chrome DevTools,提供了一系列跟前端開發(fā) Web 應(yīng)用完全一致的調(diào)試體驗,無論開發(fā)者喜歡使用 Console.log 還是通過 JS Debugger ,都可以快速上手。

此外,Kraken 也通過支持 HMR 的所有標(biāo)準(zhǔn)的 Web API,來提供局部熱更新的能力,使開發(fā) Kraken 應(yīng)用能跟 Web 下一致的局部熱更新的調(diào)試體驗,大大提升了開發(fā)者的開發(fā)調(diào)試體驗。

最后,Kraken 的所有代碼都已經(jīng)開源,Kraken 提供了開放的 TSC 機(jī)制期望所有開發(fā)者可以平等地交流以及決策,使 Kraken 可以更好地發(fā)展,也歡迎更多的開發(fā)者一起來共建 Kraken。

Kraken Github:https://github.com/openkraken/kraken

Kraken 官網(wǎng):https://openkraken.com/

關(guān)鍵詞:引擎,渲染,北海,原理,技術(shù),深入

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉