React Virtual DOM、Ember Glimmer和Incremental DOM技術哪家強

原文鏈接React Virtual DOM vs Incremental DOM vs Ember’s Glimmer: Fight 
TooNaiveMan 翻譯於2015/12/3


本文將探索3種構建動態DOM的技術,並通過一些基準測試對比3種技術的性能快慢,最後我會給出在項目中哪種技術更加適合以及爲什麼。
介紹
現在已經有許多DOM操作的框架和類庫。在這些類庫之中,專注於性能而被關注最多是React.js,Ember.js以及最新的Incremental DOM。React和Ember已經遠不是簡單的對DOM進行構建/更新,而Incremental DOM 專注在構建DOM樹和動態更新。下面將對比測試這三個類庫的快慢。

在深入細節之前,非web開發者可能會問什麼是 DOM 操作,這裏簡單介紹一下。網頁實際上是由不用元素構成的一個樹形結構。元素按照HTML規範定義工作。通過組合這些元素,我們可以構建任意複雜的網站。而DOM樹就是一個樹形HTML元素的抽象表示,它由W3C規範定義並且被所有主流瀏覽器實現支持。

除了幫助將模型綁定到視圖,這些類庫能高效更新DOM,一般情形下的多次DOM操作會被自動合併成單次(或更少)的調用。比如某一次操作需要進行:

  1. 刪除元素

  2. 添加元素

  3. 改變添加元素的屬性

通過DOM接口進行如上操作會導致高開銷的內容重新繪製和佈局。通過虛擬模型就可以把上述分次操作合併成一次。

模板

用模板技術生成DOM很流行。開發中通過模板語法告訴編譯器生成DOM樹(或者HTML文檔)。模板技術可以是HTML的擴展或者是全新設計語法。

本文介紹的三種技術並非都用了模板。比如React使用了JSX:一種Javascript的拓展語法,通過預編譯的方式支持在Javascript裏面插入類HTML的代碼。然而Ember使用了一種叫Handlebars的模板語言。
Incremental DOM 並沒有偏向特定的模板引擎,然而,Google贊助一個名叫Closure templates 的項目將被支持,Incremental DOM還可以和superviews.jsstarplate甚至JSX一起工作。

React.js 的虛擬DOM

React開發者對DOM操作引擎命名爲虛擬DOM,她通過一系列的Javascript調用告訴類庫生成一個內存的DOM樹並且和數據的變動同步起來。虛擬DOM的核心是智能差量算法(smart deffing algorithm):當數據模型變動更新到內存DOM樹上時,算法會生成同等效果,但最小需要更新DOM樹的指令。所以在不同的狀態下有兩份內存DOM樹。

聲明:本文一些圖出自:[excellent post explaining DOM manipulation libraries](http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html)

優點

  • 差量算法高效快速

  • 前端支持多種語法(JSX,hyperscript)

  • 對移動設備足夠輕量

  • 發展迅速,關注度高

  • 可以脫離React使用(僅僅使用引擎)

缺點

  • 內存DOM導致高內存消耗

  • 沒有區分靜態和動態元素*

React最近在實現一個通過檢測不變量來減少需要做差量化比較的元素。

Ember.js 的Glimmer

Glimmer是Ember.js最近的模板引擎,她借鑑引入了React的虛擬DOM技術同時保持了接口的一致性。需要指出的是開發者重寫了整個引擎,並沒有和虛擬DOM共享代碼。

Glimmer區分了**靜態****動態**的組件,因此減少了需要檢測的元素數量。這個區別得益於handlerbar引擎的高表述性。
Glimmer另外區分其他方案的關鍵實現是對於元素節點的存儲和比較,是被存放在一個簡單的流對象(就是一個簡單的對象隊列)而不是完整的類DOM節點。這樣如果要計算下次需要更新的節點,只要比較節點的值是否改變,如果沒有改變就不需要進行下一步操作。

優點

  • 高效快速的比較算法

  • 引擎區分靜態和動態元素

  • 100%對Ember接口兼容(現有Ember用戶不用改變代碼)

  • 輕量化DOM的內存表達方案

缺點

  • 之能在Ember使用

  • 只有一種前端選擇

Incremental DOM

相比而言,Incremental DOM嘗試通過簡單的方案:與其維護DOM樹完整的、或者輕量話的內存拷貝,當數據改變的時候,Incremental DOM直接在真正的DOM元素上做比較。大家可能問爲什麼,如果就這麼簡單那爲什麼其它技術沒有采用這種方案。簡單的說:所有的方案都是在內存和速度上做一個權衡。而Incremental DOM,通過去除DOM樹拷貝來減少內存的佔用,實際上確實髒檢查導致了性能下降。節省的內存對於手機或者其他內存寶貴的設備來說非常關鍵。大家可以關注我的另一篇博文:our article on Incremental DOM

優點

  • 減少內存佔用

  • 接口簡單明瞭

  • 容易集成到其它的前端框架(當然需要一開始就以它作爲後端引擎)

缺點

  • 速度相對較慢(這個是有爭議的,看下面的測試結果)

  • 關注度和社區使用較少

性能測試

我們選擇這篇博文裏的 dbmonster test app來做測試。Dbmonster是針對數據庫集羣行爲的場景模擬出在table裏面進行大量的行更新,一來是被開發出來測試Ember的性能的程序。我們使用了最新的React,Ember 1.x 和 2.x(都使用了Glimmer)和Incremental DOM。所有的測試都跑在Linux環境的Chromium 46(Core i5-5200U CPU)。每種測試跑5遍然後取平均值。

在有大塊和小塊垃圾收集的場景中。Incremental DOM表現出了預期的高效。React緊隨第二但是在瑣碎垃圾收集場景中大幅落後Incremental DOM。有意思的是Ember 1 到 2 的改進還是比較大的。

Ember在佈局和繪畫操作中所花時間這個場景中表現突出。Incremental DOM由於犧牲性能獲取內存,不出意料的排在最後。React目前來看比較平衡。

這特圖標顯示出Chrome的丟幀數(不響應導致的停止繪畫)。丟幀的結果是幀率低和畫面停頓感。在這個場景中,Incremental DOM再次突起,更少用於處理GC的時間片段使得用戶繪畫的時間更多。React和Ember緊隨其後。
一個沒有反應在圖標中的有趣的現象是,主觀上會感覺Incremental DOM的響應更快。通過觀察收集的數據,發現Incremental Dom相比對比技術的Javascript操作更少。當然,這和Incremental DOM是一個單純的DOM操作類庫,而React和Ember處理的東西更多:時間,數據傳輸等等。一個不用React的虛擬DOM的測試會很有意思。
我們看看最後完整總結的結果

這裏有測試所用的代碼。你需要安裝ChromeDriver和所有Node.js的依賴(json2csv,brower-perf),然後運行命令 node run-benchmarks.js 。最後的測試結構卸載data.json(完整)和results.csv(總結)。

題外話:在Auth0使用React.js

在Autho,我們一直在評估最適合我們的技術。我們用React.js開發了 Passwordless Lock library。因爲React沒有對model技術的依賴使得它成爲我們最好的選擇,在其他方面,React在速度,內存佔用,集成難度和文檔、支持取得了一個很好的平衡。

註冊使用我們的Passwordless Lock library或者看看代碼
結論
虛擬DOM,Glimmer和Incremental DOM都是動態操作DOM樹的優秀方案。React.js的快速發展和輕量化是許多項目的不二選擇。雖然高內存佔用對於內存吃緊的移動設備上運行的大型網站會有問題,但是隨着移動設備的硬件發展,這個問題正在逐步淡化。Incremental DOM花小錢辦大事的效果讓人眼前一亮,我們期望她能集成到Closure和其他庫中。React和Ember在各自的實現方法中取得了很好的平衡。
當選擇這幾個技術的時候,最好關注技術的成熟度和是否容易集成。除非你對DOM的操作巨頻繁(意思就是一般情況下,性能問題沒那麼突出),如果這樣,請仔細的研究播客的結果並且針對你的場景生成測試數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章