如何在持續升級的項目中保持項目的高性能?如何更加準確的定位和解決性能問題?實際上,WPO的最主要目的是改善用戶體驗,而用戶體驗的好壞則能夠根據幾個核心性能指標來衡量。從用戶體驗出發的幾個核心時間指標包括:Start Render、DOM Ready、Page Load、TTI。不一樣的性能指標對用戶體驗的影響是不一樣的,而指標自己受哪些因素的影響也是不一樣的。優化某個指標又該具體採用什麼樣的方式?接下來將一一介紹,本文集中介紹DOM Ready。html
定義web
DOM Ready,指的是頁面解析完成的時間,在高級瀏覽器裏有對應的DOM事件 - DOMContentLoaded,Firefox官方的解析以下:瀏覽器
Fired at the page’s Document object when parsing of the document is finished. By the time this event fires, the page’s DOM is ready, but the referenced stylesheets, images, and subframes may not be done loading; use the "load" event to detect a fully-loaded page.緩存
即該事件在文檔解析完成時會觸發。那麼文檔解析到底包括哪些操做呢?雖然暫不能給出一個徹底的答案,但文檔的解析至少應該包括如下操做:HTML文檔分析以及DOM樹的建立、外鏈腳本的加載、外鏈腳本的執行以及內聯腳本的執行,可是不包括圖片、iframe等其它資源的加載。正由於如此,該事件觸發的時機通常比window.onload要早,並且是在全部DOM元素均可以操做之時。服務器
目前,HTML5也對該事件進行了規範,IE9也開始支持該事件了。app
Start Render指標直接決定着用戶對頁面速度的體驗,與此不一樣,DOM Ready指標並不直接影響感官體驗,每每影響的是交互功能什麼時候可用。爲什麼影響的是交互呢?因爲DOMContentLoaded事件觸發時是全部DOM節點能夠進行操做的時候,好比添加事件、增刪改節點等,所以用Javascript實現的一些交互功能每每會在DOMContentLoaded事件中去初始化,也只有在DOMContentLoaded事件觸發後這項功能纔可用。框架
因此說DOM Ready指標影響的是交互功能的最先可用時間,DOM Ready時間若是過長的話,用戶會發現頁面已經出來了,可是不少功能倒是不可用的,也許點擊某個連接會跳到頁面頂部。所以,DOM
Ready時間也是越短越好,這樣交互功能才能儘早可用。異步
先來看看一個粗略的時間組成公式:性能
Time To Dom Ready = TTSR + TTDC + TTST優化
其中:
TTSR(Time To Start Render):瀏覽器開始渲染的時間
TTDC(Time To Dom Created):DOM樹建立所耗時間
TTST(Time To Script):BODY中全部腳本加載和執行的時間
經過以上公式能夠看到Start Render主要受如下因素影響(開發人員可控):
(1) DOM結構的複雜程度
(2) BODY中腳本使用狀況
經過對一些實際監控數據的分析得出,在一個經過正常方式加載腳本的頁面中,腳本的加載和執行時間每每能佔DOM
Ready時間的50%左右,因而可知腳本的使用對DOM Ready指標的影響如何的顯著!所以,對DOM Ready指標的優化也應該着重從腳本的使用入手。
監控方式目前各個框架都有本身的實現方案,大體的狀況是在「現代」瀏覽器中經過註冊document的DOMContentLoaded事件來監控,而像相似IE9如下各個不支持該事件的瀏覽器則使用模擬的手段來處理。關於主流框架中的實現方案能夠參考《主流框架中DOMContentLoaded事件的實現》。
從DOM Ready時間的影響因素着手分析:
(a) 減小服務器響應時間
(b) 減少HTML文檔體積
(c) 減小Head中資源使用(腳本個數、執行時間)
(2) 減小BODY中腳本的使用(重點)
腳本的加載和執行時間是影響DOM
Ready指標的最關鍵因素。外鏈腳本在加載和執行的過程當中會阻塞頁面的解析,內聯腳本在執行的過程當中也會阻塞頁面的解析,所以腳本加載和執行的時間越長則DOM
Ready的時間就越長。
優化腳本應該從加載和執行兩方面考慮:
(a) 加載:動態加載腳本時將不會阻塞文檔的解析,所以全部外鏈腳本都應該儘量的經過動態加載的方式來加載,關於動態加載相關的技術能夠參考《Loading Scripts Without
Blocking》。目前最爲經常使用的方案是文中提到的"Script DOM Element"。
(b) 執行:雖然動態加載的腳本在加載過程當中並不會阻塞文檔的解析,可是假如在DOM
Ready前加載完成,則腳本在執行的過程當中仍然會阻塞文檔的解析,包括渲染。此外,若是是內聯腳本,若是執行時間長依然會阻塞文檔解析,這種狀況能夠考慮將內聯腳本放在DOM
Ready後執行或者經過異步方式來執行。而對於外鏈腳本的執行問題目前大多數方案都是讓外鏈腳本先加載可是儘量遲的去執行,例如DOM
Ready後執行亦或是按需執行。對於外鏈腳本的延遲執行,也有很多人給出了具體的解決方案,例如Steve Souders的ControlJS就是將各類技術結合起來提供了一整套的解決方案。其主要思路是在頁面解析進行時,經過Image或者Object預加載腳本,這時候加載的內容是被瀏覽器緩存的,可是由於不是腳本所以不會當即執行,但須要執行時則建立script標籤從新請求,因爲瀏覽器有緩存於是會當即執行。
(3) 減小或延遲加載BODY中腳本以外的資源
雖說DOM Ready不會受圖片等資源加載的影響,但因爲若是圖片數量過多並且較大時會較長時間的佔用HTTP鏈接數,這會致使這些資源以後的腳本資源加載受阻,而按傳統方式加載的腳本加載得越晚則意味着DOM Ready時間也會越靠後,所以若是圖片數過多或者圖片過大的話能夠考慮使用延遲加載或者對圖片自己進行優化,減小圖片對鏈接數的佔用。