原文地址:http://www.sencha.com/blog/optimizing-ext-js-4-1-based-applications/
雖然Sencha在Ext JS 4.1提高了效能,但基於Ext JS的應用效能最佳化仍然是奮鬥目標。要最佳化應用效能,通常需要根據Ext JS的增強優勢對修改代碼。
本文將介紹如何?最佳化,還將介紹一個用於Ext JS 4.1的新的效能測量工具——頁面分析器。其主要功能是改善應用的效能。通過它,就可以定出測量指標兵測量它,從而找出代碼中的瓶頸,兵採取正確的步驟消除瓶頸。頁面分析可以做到這一點。最後,還將介紹Grid的最佳化,並介紹另一個新的用於評估Grid效能的Ext JS工具——Infinite Grid Tuner。
正如我們為Ext JS開發人員工作一樣,我們注意到幾個共同的趨勢,在編寫應用程式時要提供效能調整的辦法。雖然我們不能一一列舉拖垮應用程式的每個編碼技術,但通過以下介紹的方法,高開發人員就可在使用架構時提高應用程式的效能。
一般最佳化技巧
這裡有幾個方法可以避免在公用地區拖慢Ext JS代碼。
檢查事件監聽
在應用程式中如何使用事件監聽是一個提供效能的一個關鍵。例如,想在Store第一次載入資料時觸發load事件,如果不注意,就會造成Store每次載入資料時都會觸發load事件。這時候,在Store第一次載入資料觸發load事件後關閉它,將會提升應用程式的整體效能。方法就是在監聽中添加“single:true”:
- listeners: {
- load: onFirstLoadData,
- single: true
- }
另外一個經常忽略的是afterrender事件,它會在所有DOM元素都渲染後觸發。渲染後修改元素會引起迴流reflows),從而降低應用效能。相反,使用beforerender事件,在渲染前調整元素的樣式,可讓元素在渲染時就是正確的樣式。有時候,一些代碼必須在渲染後,元素的大小被確定後才能運行。這時候,在Ext JS 4.1,可以考慮使用其提供的一個新事件——boxready,它會在組件大小確定後觸發,
移除doLayout和doComponentLayout的調用
簡而言之,就是盡量移除這些昂貴的調用。在舊版本Ext JS4.0之前),doLayout會讓架構在組件或容器繼續前進時,重新計算其布局。即使在Ext JS 4.0,有時候,也需要在直接更新DOM後或解決某些缺陷時調用它。
在Ext JS 4.1,布局的觸發有點不同,因而,代碼基本不需要調用doLayout或doComponentLayout。如果你的應用事實上需要這些調用來解決錯誤,那麼請提交一個bug報告,一把我們能修複它。
唯一非錯誤時,需要調用doLayout或doComponentLayout,是在應用代碼直接修改DOM的時候。原因是架構不知道這樣的變化,因而需要調用它們更新受影響的布局。
減少容器嵌套
我們經常看到過多嵌套容器的應用,例如,一個容器內只有一個容器,而這個容器內有多個組件。這時候,可以取消外層容器,只使用一個容器完成同樣的工作。很重要的一點,必須記住,每個容器的初始化、渲染和布局都需要花費時間,因而,必須排除這些不必要的嵌套容器,這樣,應用將運行得更快。類似的代碼如下id屬性在實際上很少見到,添加在這裡是為了標記這裡有兩個容器):
- {
- id: 'container1',
- items: [{
- id: 'container2',
- items: [{
- id: 'component3'
- }]
- }]
- }
如果可能,上面代碼可減少為一個容器:
- {
- id: 'container1',
- items: [{
- id: 'component3'
- }]
- }
使用容器替換面板
請記住,Ext JS面板比容器功能強大,但也是很昂貴的。因而,最好指定“xtype: 'container'”,以避免應用使用預設的面板,如下所示:
譯者註:面板包含標題、工具列等很多組件,因而其執行個體化時要建立很多組件的執行個體,並做很多布局運算,而容器就是一個簡單的div,因而在非必要情況下使用容器,確實會大幅改善應用的效能,這個一定要切記)
- {
- xtype: 'container', // defaultType is 'panel'
- items: [ ... ]
- }
減少邊框布局borderLayout)嵌套
在Ext JS4.1,很多情況下,不再需要使用邊框布局嵌套。移除嵌套可以減少初始化、渲染和布局組件的時間。在ExtJS之前的版本很多情況下都需要嵌套,例如,在同一地區內有兩個或兩個以上相同的地區。在Center地區上有2個North地區的時候,你必須嵌套邊框布局。現在,使用一個邊框布局就可以實現兩個North地區。
在Ext JS4.1,地區可以根據需要動態添加,任何添加的地區可在最上層顯示並在不需要的時候隱藏它們。還可以通過weight屬性定義地區的優先權,例如,可以定義West地區的優先權在North地區之前。這些變化意味著不再需要嵌套邊框buutons,從而提高使用該布局的組件的渲染速度。
譯者註:該功能的改變非常方便,現在設計布局比之前版本的輕鬆多了)
減少DOM的讀取和寫入
在Ext JS4.1,我們已經儘可能的減少了布局對DOM的讀取和寫入。同樣,在你的代碼也需要這樣做。DOM在讀取自身時會降低應用速度,尤其是在混合了DOM寫入操作時的開銷相當高,而且這樣結合會引起迴流。嘗試使用beforerender來維護樣式,這樣可以在渲染時修改組件,而不是在渲染後。避免使用setStyle、addCls、removeCls以及其它直接修改DOM元素的語句,這些語句都會引起寫入操作。作為一般規則,為了獲得更好的效能,維護DOM時需要寫入時,多嘗試使用批量讀取和寫入。
使用Ext.suspendLayouts和Ext.resumeLayouts消除額外的布局操作
Ext JS 4.1提供了Ext.suspendLayouts和Ext.resumeLayouts兩個新方法來協調多個組件和容器的更新。例如,要迅速增加兩個組件到兩個連續容器,會導致多個布局和渲染操作被執行。如果在添加這些組件之前調用Ext.suspendLayouts方法,將不再單獨執行個別組件的布局操作。添加完成後,調用Ext.resumeLayouts方法,架構將只執行一次渲染和布局操作。
謹記,不單添加組件會觸發容器的布局操作,組件的其它操作或改變也會觸發容器的布局操作。重要的是針對在應用中的效能問題進行具體情況具體分析,以確保沒有多餘的布局操作被執行。
- {
- Ext.suspendLayouts();
- // batch of updates
- Ext.resumeLayouts(true);
- }
Ext JS頁面分析器介紹
Ext JS 4.1帶有一個新工具,可用來尋找和衡量應用程式的效能問題。通過它,可快速檢測代碼的修改對效能的影響。頁面分析器會在載入Ext JS 4.1頁面時與診斷工具掛鈎。頁面分析器包含了許多實驗性功能,本文將介紹其最有用的,用於最佳化應用效能的布局選項卡。
你可以在Ext JS 4.1 SDK包的樣本檔案夾Examples)下找到該工具:
- ./examples/page-analyzer/page-analyzer.html
複製整個“page-analyzer”檔案夾到要分析的應用主機上,因為瀏覽器安全問題,頁面分析器必須與分析頁面在同一伺服器上進行通訊,而且要確保頁面分析器的版本與Ext JS的版本號碼匹配。如果使用不同的版本,它會罷工。
謹記,該工具是首次發布的工具,還處於發展中,因而,請通過Ext JS論壇將工具的使用方式反饋給我們。
以下是使用頁面分析器的步驟:
- 開啟瀏覽器兵輸入頁面分析器的地址。
- 開啟後,在分析器中輸入測試頁面的地址。
- 頁面將在iframe中載入,這就是為什麼分析器必須與應用在同一伺服器的原因。開啟頁面後的分析器如所示:
650) this.width=650;" border="0" alt="" src="http://www.bkjia.com/uploads/allimg/131228/134240I38-0.png" />
- 單擊布局選項卡,將看到如所示的布局運行情況。
650) this.width=650;" border="0" alt="" src="http://www.bkjia.com/uploads/allimg/131228/134240E61-1.png" />
- 你可以在同一個組件中找到多個布局操作,然後查看你的代碼,看看是否可以通過減少布局操作來提高效能。
Grid最佳化
Ext JS Grid是造成Web應用效能問題的一個主要原因,尤其是在顯示大量資料的時候。當Grid在渲染小量資料的時候,速度不是問題。然而,在顯示大量資料的時候,如果不注意,虛擬無限滾動就會成為效能瓶頸。無限滾動依賴於頁面緩衝分頁,也就是在使用者對Grid中進行滾動操作顯示資料之前,需要在分頁滾動對象內儲存分頁資料。
當使用者滾動時,快取資料就變成可見的,而消失在頁面頂部的則不再存放在DOM中。調整的主要途徑是讓讓DOM的大小儘可能的小,並在用戶端快取資料從而減少與伺服器的互動。
滾動原理
當Store的配置項buffered為true時,會執行個體化一個PagingScroller對象用於監控視圖Grid內建的資料檢視)的滾動,同時要為視圖即將進行的遍曆操作提供即時資料而緩衝分頁資料。
說明了使用者滾動時視圖擷取資料的方式。PageingScroller會在往前方向維持一個前置緩衝地帶,而在往後方向則維持一個小的後向緩衝地帶。
650) this.width=650;" border="0" alt="" src="http://www.bkjia.com/uploads/allimg/131228/1342405139-2.png" />
PagingScroller要求Store確保後向緩衝地帶和前置緩衝地帶都在緩衝中,這就需要計算那些頁面是需要的,以確保它們被緩衝,而Store只需要通過Ajax請求不在緩衝中的頁面。
當視圖往下滾動時,渲染表格的邊界將會進入視圖,當距離邊距numFromEdge行的時候,Store就要載入繼續往下的資料,同時保證垂直座標同步以保證可視行在相同位置。當所需資料在頁面緩衝的時候,這個操作是在瞬間和無形中實現的。如果拖動捲軸超過了快取頁面面,將會發送yieldAjax請求,並顯示遮蔽直到資料返回。
如果滾動增量在一個合理的速度範圍內,請求地區的前置邊界進入另一不在緩衝的頁面時,會調用Ajax請求該頁。在大多數情況下,如果前置緩衝區域足夠大,它會在在到達緩衝行之前渲染表格。
預設情況下,頁面緩衝只會緩衝最近使用的5頁,這個根據瀏覽情況進行添加,讓更多的資料緩衝在用戶端,從而減少Ajax請求。Store的purgePageCount配置項可控制該行為。
如果資料不是太多,例如50000行,那可以將它們整個緩衝到用戶端。設定Store的配置項purgePageCount為0,頁面緩衝後將不會被丟棄。
如何設計大表取決於如何渲染和瀏覽速度。表越大,在視圖到邊界及從預取緩衝到更新資料之間的滾動範圍就越多。然而,從預取緩衝中擷取的資料越多,重新渲染的時間就越長。這需要在可視資料與重新渲染之間要保持一個平衡。如果應用的目標是快速探索器,可以選擇顯示更多的行和資料。如果是較慢的瀏覽器,則可使用顯示較小的行的較小的表,從而讓其更快到達可視邊界,適應經常的和更頻繁的重新整理。
為了協助你調試Grid,Ext JS 4.1包內Examples目錄下有一個名稱為“Infinite Grid Tuner”的樣本,它帶有1個5萬資料的資料集,可以讓你設定不同的方式通過預先處理緩衝為Store載入資料。例如,可以類比Ajax的延時、修改預取資料的行數以及調整表的大小。你可以通過修改左側上顯示的不同的參數,研究一下怎樣設定才能讓你的應用在瀏覽器上表現得更好。
650) this.width=650;" border="0" alt="" src="http://www.bkjia.com/uploads/allimg/131228/1342402V6-3.png" />
通過Infinite Grid Tuner,你可以調整Store的purgePageCount設定。該設定會在渲染後從頁緩衝中刪除大量資料。如果設定為0,它會在緩衝中儲存所有資料,這意味著,如果使用者滾動Grid,將不需要從伺服器中載入資料。
使用Infinite Grid Tuner,要清楚兩個概念:Grid內的可視資料可以被看作是一個滑動視窗。同樣,頁面緩衝也可以被看作與Grid相關的滑動視窗的所有資料。你可以使用tuner改變兩者的大小,還可以為它們分別補充規則,以確定從可視邊界到從Grid可視部分和頁面緩衝擷取資料之間,使用者的滾動行數所在位置。
附加資源
The following resources are also useful for application performance tuning:
- View a 50-minute webinar video version of this blog
- Suggestions from other Ext JS users in the Sencha Ext: Open Discussion forum Performance Best Practices thread
- Tips for optimizing Internet Explorer 8 and higher
- Information about dynaTrace performance management technology for Internet Explorer and FireFox
- Chrome Speed Tracer website and tutorial
- Firebug profiler tutorial
作者:Don Griffin
Don Griffin is a member of the Ext JS core team. He was an Ext JS user for 2 years before joining Sencha and has over 20 years of software engineering experience on a broad range of platforms. His experience includes designing web application front-ends and back-ends, native GUI applications, network protocols and device drivers. Don’s passion is to build world class products that people love to use.