網頁性能優化,緩存優化、加載時優化、動畫優化--摘抄
本文提供一個優化網頁性能的大概思路,具體操作網上資料很多。
緩存優化
性能優化第一步,便是管理好頁面的緩存,避免重復下載資源。否則,即增加服務器壓力,又折磨用戶的錢包。
瀏覽器緩存機制
-
訪問頁面,請求各種資源,瀏覽器檢查本地是否有緩存。
-
如果有,檢查資源是否過期。沒過期,直接使用緩存。過期了,便向服務器發出請求。
-
發出的請求中會帶上etag和last-modified首部字段。
-
服務器會通過Etag和last-modified來判斷瀏覽器緩存的資源是否已經不可用。
-
如果資源仍然有效,便返回304告知瀏覽器使用緩存。否則返回更新後的資源。
按照這一套邏輯,便可規劃好網站的緩存。
如果資源提前過期,如何通知瀏覽器更新資源?
通常無法做到這一點,因為瀏覽器發現資源沒過期,根本不會發出請求。 但是可以通過修改資源的網址來實現。所以需要給資源文件名加上版本號或者隨機標記。例如 style.1234.css。 也就是說,不要讓瀏覽器緩存html文件,否則,過期之前,瀏覽器都不會請求服務器。
加載時優化
消滅不必要的下載
最好的優化,便是根本不下載資源。所以要盡量減少比不要的資源。
-
評估所有依賴是否必要,權衡利弊。
-
依賴的下載路徑是否可靠,不可用時候是否會阻礙整個頁面。
-
產品設計時候就需要拋棄浪費帶寬的設計。
壓縮所有可以壓縮的資源
代碼自不用說,都是文本,全部壓縮。
優化圖片
-
去掉不必要的圖片
-
多使用css3來代替圖片
-
使用壓縮率更高的圖片。特別是gif動圖,一些視頻格式(H.264或WebM)的體積比gif小很多。
-
用藝術字字體,不要用圖片
-
仔細權衡圖片和文字的關系。要表達一個意思,可能一圖勝千言。多了一張圖片,反而節省了大量文字。
-
使用progressive jpeg。相比隨著數據下載從上到下顯示的baseline jpeg,progressive jpeg是由模糊到清晰,用戶體驗好,也不會導致reflow。
-
圖片分辨率要盡可能小,避免圖片分辨率大於顯示分辨率。
-
為使用更新瀏覽器的用戶提供更現代的圖片格式。
-
多種分辨率的位圖供不同頁面大小使用。
-
要給標簽指明寬高,否則會導致reflow。
-
使用HTTP/2。比如,精靈圖是由很多小圖片組成的一張大圖片,可以減少http請求。但是卻難以緩存,修改一個小圖片,導致所有小圖片緩存失效。HTTP/2,一個鏈接內可以發起多個請求,便無需使用精靈圖。
優化字體
-
@font-face 中unicode-range可以制定字符範圍,用來避免下載不需要的語言的字符。
-
確保字體都被壓縮過。
-
用@font-face的display屬性和FontFace對象管理好字體加載時的邏輯。
關鍵渲染路徑
瀏覽器渲染一張網頁通過以下步驟。
處理 HTML 標記並構建 DOM 樹。
處理 CSS 標記並構建 CSSOM 樹。
將 DOM 與 CSSOM 合並成一個渲染樹。
根據渲染樹來布局,以計算每個節點的幾何信息。
將各個節點繪制到屏幕上。
優化關鍵渲染路徑,便是指優化這個渲染過程,讓網頁盡快呈現出來。
css
-
CSS文件會阻塞渲染。瀏覽器構建好DOM樹後,必須等待CSSOM樹構建完成。
-
在文檔頂部防止外聯CSS的標簽,讓瀏覽器盡快請求CSS文件。
-
避免在css文件中使用@import,因為只有包含import的文件被下載編譯後,瀏覽器才會發現並下載import的css。
-
可以考慮使用內聯CSS,無需額外請求,不會阻塞渲染。
js
-
在CSSOM構建完成前,js不會開始執行。
-
js也會阻止DOM樹構建。除非在
<script>
標簽上標記async。 -
用Chrome開發者工具的audits檢查網頁。
動畫優化
重繪過程
CSS選擇器
-
選擇器越復雜,瀏覽器計算得越久。最糟情況下,瀏覽器需要遍歷整個DOM-tree,計算量等於元素總個數乘以選擇器個數。
-
盡量不要使選擇器太復雜,事先給需要被操作的元素加上類名。
reflow, layout
Chrome, Opera, Safari, Internet Explorer中叫layout. 火狐稱之為Reflow。
-
reflow, repaint次數越少越好,牽連的元素越少越好。
reflow總是牽涉整個文檔流。
-
修改元素css後立刻讀取css計算值,將導致瀏覽器同步reflow,阻塞js線程。
Paint
瀏覽器渲染網頁時,會將網頁分層(layer),最後將不同層合並,然後完成渲染。 同一層中,哪怕只有一個小小的元素發生變化,整個層都會被repaint。 這一點可以在開發者工具的Paint Profiler界面中觀察到,layer界面中可以觀察網頁有多少個layer。
-
paint是耗費性能的。
-
修改transform和opacity會導致repaint
-
創建新layer來減少repaint區域。
will-change屬性可以為元素創建新layer(works in Chrome, Opera and Firefox).或 transform: translateZ(0);(works in all browsers).
-
過多layer也消耗內存和性能,用Performance判斷新layer是否帶來優化,否則不要創建新layer。
-
高dpi屏幕下,fixed元素自動擁有自己的layer。低dpi需要自行創建。
-
repaint某個layer時,如果layer與其他元素重疊,將導致layer和重疊的元素都被repaint。
-
最好的動畫是跳過layout和paint直接composite。
用transform, opacity來制作動畫,可實現無layout和repaint. (Devtool Performance的main中無動畫相關事件。)
debounce
debounce:不要高頻率調用函數,事件連續觸發時,只調用一次函數。
-
交互事件的監聽函數的執行時間不能太長,否則會阻塞頁面滾動。
-
不要再交互事件的監聽函數中修改樣式,會導致強制同步reflow,阻塞js執行。
-
debounce,活用requestAnimationFrame方法。
監聽函數可能會調用perventDefault, 導致compositor線程必須等待監聽函數執行完成。 不過新擴展的addEventListener方法第三個參數可以解決此問題。
小技巧
-
動畫不能低於60幀。ui反饋不能低於100ms。
-
ui反饋不必追求最快,可故意拖延到100ms。並利用這個時間做其他事。
-
盡量增加線程空閑時間,以快速反饋。
-
ui反饋優先級最高,交互期間盡量停下其他任務。
網頁性能優化,緩存優化、加載時優化、動畫優化--摘抄