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

本文提供一個優化網頁性能的大概思路,具體操做網上資料不少。css

緩存優化

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

瀏覽器緩存機制

  1. 訪問頁面,請求各類資源,瀏覽器檢查本地是否有緩存。
  2. 若是有,檢查資源是否過時。沒過時,直接使用緩存。過時了,便向服務器發出請求。
  3. 發出的請求中會帶上etag和last-modified首部字段。
  4. 服務器會經過Etag和last-modified來判斷瀏覽器緩存的資源是否已經不可用。
  5. 若是資源仍然有效,便返回304告知瀏覽器使用緩存。不然返回更新後的資源。

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

若是資源提早過時,如何通知瀏覽器更新資源?

一般沒法作到這一點,由於瀏覽器發現資源沒過時,根本不會發出請求。
可是能夠經過修改資源的網址來實現。因此須要給資源文件名加上版本號或者隨機標記。例如 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. 將各個節點繪製到屏幕上。

說人話:瀏覽器先解析HTML,發現<link>就去請求CSS文件,發現<script>就去請求js文件。
當CSS文件徹底取回,便會開始構建CSSOM樹,當CSSOM樹和DOM樹都構建完成,纔會開始渲染頁面。
當JS文件徹底取回,並不必定馬上執行,須要等待CSSOM樹構建完成。同時,若是DOM樹還沒有構建完成,就會暫停構建,等待JS執行完成。由於瀏覽器不知道JS文件是否會修改CSS和DOM。
因此,在網頁中隨意擺放<link>和<script>,極有可能形成各類阻塞,必須精心安排。
優化關鍵渲染路徑,即是指優化這個渲染過程,讓網頁儘快呈現出來。服務器

css

  • CSS文件會阻塞渲染。瀏覽器構建好DOM樹後,必須等待CSSOM樹構建完成。
  • 在文檔頂部放置外聯CSS的標籤,讓瀏覽器儘快請求CSS文件。
  • 避免在css文件中使用@import,由於只有包含import的文件被下載編譯後,瀏覽器纔會發現並下載import的css。
  • 能夠考慮使用內聯CSS,無需額外請求,不會阻塞渲染。

js

  • 在CSSOM構建完成前,js不會開始執行。
  • js也會阻止DOM樹構建。除非在<script>標籤上標記async。
  • 用Chrome開發者工具的audits檢查網頁。

動畫優化

重繪過程:
rendering異步

  1. js修改元素樣式
  2. 瀏覽器從新計算CSSOM樹
  3. 若是佈局發生變化,則計算出新的佈局
  4. 按不一樣的layer來計算出繪製元素所需的每一個像素。
  5. 按順序合併不一樣的layer

優化動畫即是優化以上步驟使動畫達到60幀。
CSS選擇器要簡單,避免瀏覽器遍歷DOM樹來尋找元素。
js修改的元素要避免牽連過多致使佈局發生變化。
要減小須要重繪的元素。重繪時,同一個layer的元素都會被重繪。重繪也是很是耗費性能的一步。async

CSS選擇器

  • 選擇器越複雜,瀏覽器計算得越久。最糟狀況下,瀏覽器須要遍歷整個DOM-tree,計算量等於元素總個數乘以選擇器個數。
  • 儘可能不要使選擇器太複雜,事先給須要被操做的元素加上類名。

reflow, layout

即佈局發生變化。Chrome, Opera, Safari, Internet Explorer中叫layout. 火狐稱之爲Reflow。
  • reflow, repaint次數越少越好,牽連的元素越少越好。
reflow老是牽涉整個文檔流。
  • 千萬不能修改元素css後馬上讀取css計算值。由於瀏覽器必須從新計算佈局,才能知道所需值。而js中相關API都是同步的,因此這將致使瀏覽器同步reflow,阻塞js線程。

Paint(重繪)

由於動畫一直在運動,因此要避免使用會致使佈局發生變化,和致使必須從新計算元素像素(重繪)的CSS屬性製做動畫。而transform和opacity兩個CSS屬性正是咱們所需的。
由於瀏覽器渲染網頁時,會將網頁分層(layer),最後將不一樣層合併,而後完成渲染。
同一層中,哪怕只有一個小小的元素髮生變化,整個層都會被repaint。函數

開發者工具的Paint Profiler界面中觀察到每一層的繪製過程
因此,能夠考慮將動畫放在單獨的layer中。

建立新layer

CSS的will-change和 transform: translateZ(0)能夠用來建立新layer;
再搭配transform和opacity,用CSS3製做動畫。根據個人實驗,能夠徹底避免reflow和重繪

可是過多layer也消耗內存和性能,用開發者工具中的 Performance判斷新layer是否帶來優化,不然不要建立新layer。
開發者工具的layer界面中能夠觀察網頁有多少個layer,每一個layer包含哪些元素。

優化交互

網頁時給人用的,因此最惱人的是鼠標或手指操做頁面時,頁面卡卡的。
而響應用戶操做的JS都是異步的。若是JS線程太繁忙,遲遲不能進入下一個事件循環,就會致使響應用戶操做不及時。
儘可能增長線程空閒時間,讓事件循環能夠及時取出回調函數。提升響應的優先級,用戶交互時,停下其餘耗時的JS。
響應沒必要過於及時,在100ms內獲得反饋,人類都不會察覺到卡頓,能夠把一些耗時的工做分解成不少步,利用這個時間差去執行它們。
活用requestAnimationFrame方法。

requestAnimationFrame在下一幀開始前調用函數。優於setInterval的地方是每一幀只會調用一次,而setInterval則不必定。

監聽函數

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

監聽函數可能會調用preventDefault, 致使瀏覽器必須等待監聽函數執行完成。
不過新擴展的addEventListener方法第三個參數能夠是一個對象,對象的passive屬性用來事先承諾不會調用preventDefault方法,瀏覽器則不會等待監聽函數。

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

由於監聽函數會在requestAnimationFrame以前執行,若是監聽函數中修改了樣式,又用到requestAnimationFrame來製做動畫,便會致使強制同步reflow。

某些交互事件觸發極頻繁,注意要debounce。

debounce:不要高頻率調用函數,事件連續觸發時,只調用一次函數。
相關文章
相關標籤/搜索