網頁性能優化,緩存優化、加載時優化、動畫優化

本文提供一個優化網頁性能的大概思路,具體操作網上資料很多。

緩存優化

性能優化第一步,便是管理好頁面的緩存,避免重複下載資源。否則,即增加服務器壓力,又折磨用戶的錢包。

瀏覽器緩存機制

  1. 訪問頁面,請求各種資源,瀏覽器檢查本地是否有緩存。

  2. 如果有,檢查資源是否過期。沒過期,直接使用緩存。過期了,便向服務器發出請求。

  3. 發出的請求中會帶上etag和last-modified首部字段。

  4. 服務器會通過Etag和last-modified來判斷瀏覽器緩存的資源是否已經不可用。

  5. 如果資源仍然有效,便返回304告知瀏覽器使用緩存。否則返回更新後的資源。

按照這一套邏輯,便可規劃好網站的緩存。

如果資源提前過期,如何通知瀏覽器更新資源?

通常無法做到這一點,因爲瀏覽器發現資源沒過期,根本不會發出請求。 但是可以通過修改資源的網址來實現。所以需要給資源文件名加上版本號或者隨機標記。例如 style.1234.css。 也就是說,不要讓瀏覽器緩存html文件,否則,過期之前,瀏覽器都不會請求服務器。

加載時優化

消滅不必要的下載

最好的優化,便是根本不下載資源。所以要儘量減少比不要的資源。

  1. 評估所有依賴是否必要,權衡利弊。

  2. 依賴的下載路徑是否可靠,不可用時候是否會阻礙整個頁面。

  3. 產品設計時候就需要拋棄浪費帶寬的設計

壓縮所有可以壓縮的資源

代碼自不用說,都是文本,全部壓縮。

優化圖片

  1. 去掉不必要的圖片

  2. 多使用css3來代替圖片

  3. 使用壓縮率更高的圖片。特別是gif動圖,一些視頻格式(H.264或WebM)的體積比gif小很多。

  4. 用藝術字字體,不要用圖片

  5. 仔細權衡圖片和文字的關係。要表達一個意思,可能一圖勝千言。多了一張圖片,反而節省了大量文字。

  6. 使用progressive jpeg。相比隨着數據下載從上到下顯示的baseline jpeg,progressive jpeg是由模糊到清晰,用戶體驗好,也不會導致reflow。

  7. 圖片分辨率要儘可能小,避免圖片分辨率大於顯示分辨率。

  8. 爲使用更新瀏覽器的用戶提供更現代的圖片格式。

  9. 多種分辨率的位圖供不同頁面大小使用。

  10. 要給標籤指明寬高,否則會導致reflow。

  11. 使用HTTP/2。比如,精靈圖是由很多小圖片組成的一張大圖片,可以減少http請求。但是卻難以緩存,修改一個小圖片,導致所有小圖片緩存失效。HTTP/2,一個鏈接內可以發起多個請求,便無需使用精靈圖。

優化字體

  1. @font-face 中unicode-range可以制定字符範圍,用來避免下載不需要的語言的字符。

  2. 確保字體都被壓縮過。

  3. 用@font-face的display屬性和FontFace對象管理好字體加載時的邏輯。

關鍵渲染路徑

瀏覽器渲染一張網頁通過以下步驟。

  1. 處理 HTML 標記並構建 DOM 樹。

  2. 處理 CSS 標記並構建 CSSOM 樹。

  3. 將 DOM 與 CSSOM 合併成一個渲染樹。

  4. 根據渲染樹來佈局,以計算每個節點的幾何信息。

  5. 將各個節點繪製到屏幕上。

優化關鍵渲染路徑,便是指優化這個渲染過程,讓網頁儘快呈現出來。

css

  • CSS文件會阻塞渲染。瀏覽器構建好DOM樹後,必須等待CSSOM樹構建完成。

  • 在文檔頂部防止外聯CSS的標籤,讓瀏覽器儘快請求CSS文件。

  • 避免在css文件中使用@import,因爲只有包含import的文件被下載編譯後,瀏覽器纔會發現並下載import的css。

  • 可以考慮使用內聯CSS,無需額外請求,不會阻塞渲染。

js

  • 在CSSOM構建完成前,js不會開始執行。

  • js也會阻止DOM樹構建。除非在 <script>標籤上標記async。

  • 用Chrome開發者工具的audits檢查網頁。

動畫優化

重繪過程

640?wx_fmt=jpeg

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:不要高頻率調用函數,事件連續觸發時,只調用一次函數。

  1. 交互事件的監聽函數的執行時間不能太長,否則會阻塞頁面滾動。

  2. 不要再交互事件的監聽函數中修改樣式,會導致強制同步reflow,阻塞js執行。

  3. debounce,活用requestAnimationFrame方法。

監聽函數可能會調用perventDefault, 導致compositor線程必須等待監聽函數執行完成。 不過新擴展的addEventListener方法第三個參數可以解決此問題。

小技巧

  • 動畫不能低於60幀。ui反饋不能低於100ms。

  • ui反饋不必追求最快,可故意拖延到100ms。並利用這個時間做其他事。

  • 儘量增加線程空閒時間,以快速反饋。

  • ui反饋優先級最高,交互期間儘量停下其他任務。


原文:https://segmentfault.com/a/1190000013279030?utm_source=channel-newest

發佈了26 篇原創文章 · 獲贊 80 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章