基于 Flutter 的 Web 渲染引擎「北?!拐介_源
阿里巴巴歷時(shí) 3 年自研開發(fā)的 Web 渲染引擎 北海(英文名:Kraken)正式開源,致力打造易擴(kuò)展,跨平臺(tái),高性能的渲染引擎,并已在優(yōu)酷、大麥、天貓等業(yè)務(wù)場(chǎng)景中使用。
官網(wǎng):https://openkraken.com
Github:https://github.com/openkraken/kraken
背景
互聯(lián)網(wǎng)業(yè)務(wù)如火如荼地發(fā)展離不開跨平臺(tái)技術(shù),而最成熟的跨平臺(tái)技術(shù)就是大家熟悉的瀏覽器了,它與生俱來的跨平臺(tái)能力、開放的標(biāo)準(zhǔn)以及強(qiáng)大的生態(tài)使它成為炙手可熱的容器之一。而由于其本身不是為了性能而設(shè)計(jì)的,并且歷史包袱重、兼容性、廠商更新慢等問題,瀏覽器在移動(dòng)端的表現(xiàn)并不突出。盡管網(wǎng)絡(luò)以及硬件的發(fā)展帶來了足夠多的性能紅利,但是日益復(fù)雜的業(yè)務(wù)總能把已有的性能吃透。
過去也有很多對(duì)跨平臺(tái)方案的探索與實(shí)踐,新的技術(shù)方案也隨著歷史的浪潮不斷地發(fā)展。從最早的 H5 方案到 Hybrid 方案,以及后來的 Weex/React Native 方案,到現(xiàn)在如火如荼的 Flutter。

熟悉 Flutter 的同學(xué)肯定知道 Flutter 是用 Dart 語言以及 Widget 來開發(fā)的,雖說 Dart 語言對(duì)熟悉 JavaScript 的前端同學(xué)來說上手成本并不是很高,對(duì)于 Widget 這種基于狀態(tài)驅(qū)動(dòng)的開發(fā)模式也已經(jīng)是非常熟悉,但是整體上與已有基建與前端生態(tài)割裂的矛盾是無法接受的。再者,動(dòng)態(tài)化能力對(duì)于互聯(lián)網(wǎng)業(yè)務(wù)來說簡(jiǎn)直就是剛需,而目前來看 Flutter for Web 并不理想。
畢竟,引入一項(xiàng)新技術(shù)的第一步是解決引入這項(xiàng)新技術(shù)的成本問題。所以我們積極探索一種向上對(duì)接前端生態(tài),向下使用原生渲染的跨平臺(tái)方案。
于是誕生了這款基于 W3C 標(biāo)準(zhǔn)的高性能跨終端渲染引擎——北海(Kraken)。

基于 W3C 標(biāo)準(zhǔn)
Kraken 最終要服務(wù)的用戶還是前端開發(fā)者,那么如何降低前端開發(fā)者的學(xué)習(xí)熟悉成本以及如何將老項(xiàng)目快速地遷移到 Kraken 之上呢?我們并不想重新創(chuàng)造一套新的 DSL 作為研發(fā)框架來給開發(fā)者用,如果需要的話,那 Flutter 本身的 Widget + Dart 已經(jīng)做得很不錯(cuò)了。前端開發(fā)者可能是用 Rax,也有可能是用 Vue 或是 React 的,我們都期望 Kraken 的用戶能夠做到“零成本”的快速接入。那么,就需要依賴一套開發(fā)者非常熟悉的標(biāo)準(zhǔn)來實(shí)現(xiàn) Kraken。

W3C 標(biāo)準(zhǔn)是互聯(lián)網(wǎng)最重要的標(biāo)準(zhǔn)之一,也是前端開發(fā)者非常熟悉的標(biāo)準(zhǔn),基于 W3C 標(biāo)準(zhǔn)來實(shí)現(xiàn)渲染引擎,對(duì)于熟悉瀏覽器的前端開發(fā)者可以做到近乎“零成本”的快速上手。同時(shí),我們可以擯棄一些沉重的歷史包袱,使得 Kraken 的渲染效率更高。
強(qiáng)大的前端開發(fā)者生態(tài)
受益于基于 W3C 標(biāo)準(zhǔn)來開發(fā),在 Kraken 上前端開發(fā)者完全可以使用目前熟悉的龐大的前端生態(tài)。
首先,在研發(fā)框架的選擇上,無論開發(fā)者使用的是 Rax 或者 Vue ,還是 React 或者 Angular 的,都可以保證在 Kraken 上很好地完成渲染。

再次,前端擁有非常繁榮的生態(tài),社區(qū)海量的 NPM 包都可以在 Kraken 項(xiàng)目上直接使用,大量成熟的模塊保證了業(yè)務(wù)開發(fā)的效率。

除此之外,開發(fā)者平時(shí)在開發(fā)項(xiàng)目使用的各式各樣的工具,都可以在 Kraken 項(xiàng)目上直接使用,無需任何額外的熟悉以及學(xué)習(xí)成本。

通過對(duì)接了 Chrome DevTools Protocol,使開發(fā)者可以直接使用非常熟悉的 Chrome DevTools 來調(diào)試所開發(fā)的頁面。無論開發(fā)者需要修改 CSS 樣式,還是查看 DOM 結(jié)構(gòu),或者是通過斷點(diǎn)調(diào)試 JavaScript 代碼,都能保證跟 Web 開發(fā)一致的調(diào)試體驗(yàn)。
渲染一致性
Kraken 的渲染能力是對(duì)其 W3C 標(biāo)準(zhǔn)的,所以可以保證跟 Web 渲染的結(jié)果完全一致。
下圖是實(shí)際業(yè)務(wù)的截圖,從左到右分別是 Kraken(iOS),Kraken(Android)以及 Web 版本,可以看出渲染結(jié)果是完全一致的。
比 Web 更好的體驗(yàn)與能力
那么到這里會(huì)有同學(xué)想問了,除了與目前前端開發(fā)一致的開發(fā)及調(diào)試體驗(yàn),以及渲染一致性,那么最終到底能得到怎么樣的能力,以及跟瀏覽器比,到底可以獲得哪些收益呢?
無限滾動(dòng)列表
在業(yè)務(wù)開發(fā)中,有時(shí)開發(fā)者會(huì)遇到一些無法用分頁卻又大量數(shù)據(jù)的「無限滾動(dòng)列表」。在客戶端開發(fā)中有 RecyclerView/UITableView 來實(shí)現(xiàn)滾動(dòng)回收的布局容器,而 Web 標(biāo)準(zhǔn)上盡管也有很多前端側(cè)的優(yōu)化方案來處理這個(gè)問題,但也一直是個(gè)難題。Kraken 嘗試在容器側(cè)解決了此問題,增加 CSS Display 屬性值——sliver。
當(dāng) Sliver 容器中的子元素滾動(dòng)出該容器的 Viewport 時(shí),可以將該子元素中用于渲染的 renderobject 回收以達(dá)到節(jié)省內(nèi)存占用的目的。當(dāng)子元素重新出現(xiàn)時(shí),根據(jù) DOM 描述重新生成 renderobject。
這是一個(gè)上萬個(gè)節(jié)點(diǎn)的 demo,左邊是 overflow: scroll 的容器,而右邊是 display: sliver 的容器,可以看到 sliver 容器在「無限滾動(dòng)列表」場(chǎng)景下滾動(dòng)明顯流暢很多。左上角有 FPS 的數(shù)據(jù),可以看到 display: sliver 的容器 FPS 一直維持正常水平,而 overflow: scroll 的容器 FPS 明顯下降。此外,在內(nèi)存方面也有較大收益。
同步光柵化
在瀏覽器中,光柵化是異步進(jìn)行的,進(jìn)行慣性滾動(dòng)時(shí),會(huì)出現(xiàn)白屏,這個(gè)是 WebView 始終無法避免的問題。而借助 Flutter 足夠高效的同步光柵化實(shí)現(xiàn),Kraken 可以做到長(zhǎng)列表快速滾動(dòng)不白屏。
增強(qiáng)的手勢(shì)能力
Kraken 通過對(duì)常用手勢(shì)進(jìn)行內(nèi)置,使業(yè)務(wù)開發(fā)者使用手勢(shì)能力的時(shí)候,再也不需要引入一個(gè) JavaScript lib 以劫持 Touch event 來做開發(fā)了。
以輕掃手勢(shì)“swipe”為例,開發(fā)者只需要通過以下方式就可以獲得一個(gè) element 上默認(rèn)提供的手勢(shì)能力。直接使用內(nèi)置增強(qiáng)的手勢(shì)能力,能夠更快速地開發(fā)復(fù)雜的可交互應(yīng)用。
element.addEventLisenter('swipe',(gestureEvent) => {
///...
})
增強(qiáng)的手勢(shì)能力解決了 Web 下原本需要頻繁傳遞事件的性能問題以及 JavaScript 處理手勢(shì)占用 UI 線程的問題。此外,通過容器內(nèi)部實(shí)現(xiàn)的競(jìng)爭(zhēng)場(chǎng)能力,可以解決 Web 下手勢(shì)穿透等問題。
而內(nèi)置的標(biāo)準(zhǔn)化手勢(shì)能力,也保證同個(gè)容器的不同應(yīng)用下,手勢(shì)交互能力的標(biāo)準(zhǔn)化以及統(tǒng)一性。
插件化能力
除了上面的那些超越 Web 的體驗(yàn)與能力以外,Kraken 非常重要的一個(gè)特性就是插件化能力,插件化能力提供給前端工程師重新定義瀏覽器能力的機(jī)會(huì),開發(fā)者只需要編碼一個(gè) Flutter plugin,就可以擴(kuò)展 Kraken 本身的能力。
通過插件化能力,開發(fā)者可以在內(nèi)部實(shí)現(xiàn)許多自定義的標(biāo)簽(譬如說 Camera 或者自定義的視頻播放器等),也可以基于性能的考慮將常用的業(yè)務(wù)組件(譬如說 Slider)下沉到容器層。由于瀏覽器廠商開發(fā)以及標(biāo)準(zhǔn)制定往往是滯后的,用插件化能力開發(fā)者可以快速地自定義各種渲染能力,使業(yè)務(wù)開發(fā)可以用到最新的或者增強(qiáng)的各種能力。
除了擴(kuò)展渲染能力,開發(fā)者還可以擴(kuò)展手勢(shì)能力,擴(kuò)展手勢(shì)能力可以將以往需要在前端劫持 Touch Event 實(shí)現(xiàn)的能力下沉到容器本身,除了增強(qiáng)了交互體驗(yàn),也給交互提供了更多可能性。
穩(wěn)定性保障
渲染引擎非常復(fù)雜,經(jīng)常出現(xiàn)改一個(gè) Bug 牽一發(fā)而動(dòng)全身,所以需要高覆蓋率的自動(dòng)化測(cè)試來保障渲染引擎的穩(wěn)定性,每次修改后都需要保障已有的 case 沒有問題。通過自動(dòng)化測(cè)試來保障每個(gè) case 與修改之前的結(jié)果做對(duì)比,如果有差異,可以通過 case 以及差異的 diff 來修改 Bug。
這套自動(dòng)化測(cè)試系統(tǒng)保證了 Kraken 每次修改前后得到的 case 結(jié)果的一致性,以確保渲染引擎本身的穩(wěn)定性。
目前已經(jīng)有近 3000 個(gè)測(cè)試用例,未來還會(huì)根據(jù)更多的場(chǎng)景繼續(xù)增加,以此來保證 Kraken 的穩(wěn)定性。

業(yè)務(wù)落地
講了那么多 Kraken 的能力,肯定有同學(xué)想知道 Kraken 在實(shí)際生產(chǎn)場(chǎng)景的表現(xiàn)如何。
目前 Kraken 在 C 端場(chǎng)景移動(dòng)設(shè)備以及低性能 IoT 設(shè)備均有相關(guān)業(yè)務(wù)接入,完全可以使用在實(shí)際生產(chǎn)場(chǎng)景。
在優(yōu)酷 APP 中,Kraken 已經(jīng)落地了大量業(yè)務(wù)。以下方所示身份詳情頁為例,Kraken 改造后啟動(dòng)有了一個(gè)質(zhì)的提升,相較于同個(gè)頁面的 原方案,首屏渲染提升28.4%,幀率提升 8.3%。
在 IoT 設(shè)備上,我們的天貓 U 先業(yè)務(wù)在線下低性能的 IoT 設(shè)備上,Kraken 也有非常不錯(cuò)的表現(xiàn)。在線下相對(duì)較復(fù)雜的 Slider 等場(chǎng)景下,動(dòng)畫以及交互性能都表現(xiàn)較好,長(zhǎng)時(shí)間運(yùn)行應(yīng)用,內(nèi)存穩(wěn)定并無明顯增長(zhǎng),保證線下 IoT 應(yīng)用的穩(wěn)定性。

社區(qū)協(xié)作機(jī)制
kraken 團(tuán)隊(duì)期望通過一種良好的社區(qū)協(xié)作機(jī)制,來與社區(qū)的眾多開發(fā)者一起共建 Kraken 底層能力及生態(tài)。
kraken 團(tuán)隊(duì)期望通過協(xié)作者的方式來參與 Kraken 功能迭代以及 issue 討論等工作。同時(shí),通過由一部分協(xié)作者組成的技術(shù)委員會(huì)(TSC)來確定技術(shù)方向、發(fā)布以及定制標(biāo)準(zhǔn)等工作。
kraken 團(tuán)隊(duì)期望通過一種公平良好的協(xié)作機(jī)制,讓社區(qū)的開發(fā)者能夠更好地參與到對(duì) Web 標(biāo)準(zhǔn)的容器技術(shù)的演進(jìn)中去,讓每個(gè)人的聲音都能被聽到,共同促進(jìn) Kraken 以及行業(yè)的發(fā)展。
查看更詳細(xì)的協(xié)作機(jī)制可以移步github。
未來展望
以往我們?cè)谧銮岸诵阅軆?yōu)化的時(shí)候,往往優(yōu)化到瀏覽器層面就優(yōu)化不動(dòng)了,很難向下進(jìn)行進(jìn)一步的優(yōu)化。而 Kraken 的出現(xiàn),給予了前端工程師新的機(jī)會(huì)與挑戰(zhàn),它提供了前端工程師一個(gè)重新定義瀏覽器的能力的機(jī)會(huì),擁有非常大的想象空間:
超越 Web 的能力,比肩 Native 的性能與體驗(yàn)。 比瀏覽器廠商更快地實(shí)現(xiàn)標(biāo)準(zhǔn),站在標(biāo)準(zhǔn)的前沿定義問題,通過實(shí)現(xiàn)的能力去反推標(biāo)準(zhǔn),促進(jìn)行業(yè)的發(fā)展。 可以自頂向下看整個(gè)渲染鏈路的優(yōu)化及體驗(yàn),通過全鏈路的手段去優(yōu)化性能以及定義一些新的渲染能力。 目前日益復(fù)雜的前端應(yīng)用導(dǎo)致 JS bundle 的已經(jīng)顯得越來越臃腫,開發(fā)者也可以把常用能力抽象復(fù)用并下沉到容器層面,渲染與公用能力的復(fù)用不再只依賴于 NPM,可以通過下沉通用能力來做更多事情。 通過“云+端”的結(jié)合,也有機(jī)會(huì)去探索面向未來的新一代渲染技術(shù)。 基于 Kraken,探索更多的可能性......
最后,期望 Kraken 能給大家?guī)砀玫捏w驗(yàn)及能力,也希望大家可以積極參與到 Kraken 項(xiàng)目中去,大家一起共建 Kraken 生態(tài)。
官網(wǎng):https://openkraken.com
Github:https://github.com/openkraken/kraken
點(diǎn)擊下方【閱讀全文】訪問 Kraken Github,給 Kraken star 支持一下吧~
