背景:
1. 對構建的改造已經完成,目前構建的能力可以較為靈活地支撐進一步的優化
2. 希望進一步減少首屏時間,將首屏時間控制在2秒以內
頁面情況:
優化之前,並沒有上報首屏時間,頁面載入時間約為2.4秒。
研究認為,使用者最滿意的網頁開啟時間是2秒以內。作為一個相對簡單的頁面,我們就應該最可能將首屏時間甚至載入時間控制在2秒以內,讓使用者體驗到最佳的頁面體驗。
定義頁面的首屏與載入時間:
首屏時間,英文稱之為above the fold(首屏線之上)。我們以手Q群成員分佈的頁面作為例子。在iPhone5螢幕下,這個頁面在沒有往下滾動的時候,如左圖。滾動到底部時,如右圖。
我們所說的首屏時間,就是指使用者在沒有滾動時候看到的內容渲染完成並且可以互動的時間。至於載入時間,則是整個頁面滾動到底部,所有內容載入完畢並可互動的時間。
在這個頁面中,我們可以劃分成四個部份,分別是活躍 群成員、男女比例、省市分佈及年齡。我們將前三個部份歸入首屏渲染時間。剩下的內容載入時間加上首屏載入時間即是頁面載入時間。
另外值得一提的是,由於之前專案的開發將動畫渲染時間也納入統計,因此為了方便對比,我也將渲染時間納入統計。實際上,如果除去動畫渲染時間,首屏及載入時間會快300 – 500ms。
已經做好的優化:
除非各種效能優化書籍提出的要點之外,在這篇優化之前已經做到的優化並值得簡單提出來的有兩點。
1. 活躍群成員頭像的懶載入。由於手Q的頭像允許gif,因此直接載入頭像效能會比較低下。因此之前在完成這塊業務的邏輯的時候,已經新增上懶載入,業務渲染的時候顯示預設頭像,等真實頭像載入完成的時候再進行渲染。而且,在這次的優化專案中,我們並不將頭像的載入時間也納入首屏時間內。
2. 其它內容動畫的滾動渲染。其它部份的內容是會由滾動渲染效果的(這些邏輯並不由本人寫)。感謝前人做比較模組化地做好了這部份邏輯,因此我能夠比較容易地進行程式碼的搬遷與更改。
純前端手段優化頁面載入及渲染模式:
上圖是專案舊有的載入模式,是比較通常的頁面載入渲染模式。將css放在head標籤內,為了避免阻塞將js放在底部。因此頁面渲染完成後,還需要等待js的載入,js拉取資料以及js的渲染。 這便大大地減慢了首屏及載入時間。
從效能的角度看,將整個載入渲染模式換成下面的模式更有利於首屏的渲染,我們可以稱之為首屏優先載入渲染模式。
根據上述的模型,我們可以將首屏優先模式總結為三個原則,一是首屏資料拉取邏輯置於頂部,二是首屏渲染css及js邏輯優先內聯HTML,三是次屏邏輯延後處理和執行。
原則一:首屏資料拉取邏輯置於頂部,是為了資料能夠第一時間返回,相比起將資料拉取邏輯放在外部資源會少了一個JS資源載入的往返時間。
原則二:首屏渲染css及js邏輯優先內聯HTML,這是為了當HTML文件返回時CSS和JS能夠立即執行。但要注意的是HTML文件最好不要超過14kb。這是由於,TCP協議裡面有一個流控機制,被稱為 slow start,也就是在連線建立過程中逐漸增加傳輸的分段(segments)大小,根據Paul Irish在他的演講“Delivering the Goods”給出的結論是,一個Web應用最開始的 14kb 資料是最重要的。
原則三:次屏邏輯延後處理和執行,各種資料上報最好是延時上報,這樣可以減少阻塞。對於首屏的資料上報,可以先將資料存在變數裡面,等上報元件report.js載入完畢後,再呼叫回撥進行上報。
新人可能會問將這麼多程式碼內聯很不優雅,而且很麻煩呀。如果你用的構建是一個合格的構建,你大可以用構建幫你進行內聯,這並不是很費時的事情(這也是為什麼我將構建作為優化的第一篇章,構建給優化帶來便利)。
經過優化以後,首屏時間方面,非離線包版本達到1400ms左右,離線包版本則達到850ms左右。
頁面渲染完成時間方面,非離線包版本從平均2400ms左右,降至平均1600ms,效能提升33%。離線包版本從平均1350ms,降至平均970ms,效能提升28%。