前端效能優化:客戶端從輸入到展示講解

仲強發表於2017-10-11

效能優化的根本目的:
  要思考的是使用者使用網站的體驗如何,而不是我們可以節省多少位元組,只有準確感知使用者的感受,我們才有必要談毫秒、位元組和請求數量等問題。

針對優化注意事項:

  • 防止過早優化:沒必要在剛開始階段就對一個細節進行放大型的優化,因為這樣的成本很高,除了程式碼可讀性方面的東西,甚至還可能會引入更多的bug,所以,針對這個問題,我們可以在上線和運營的時候進行監控,當快暴露到問題的時候,進行整體優化。
  • 本末倒置的關注:網站內容是最重要的,應該檢視頁面的每個部分,看是否滿足網站頁面的主要目的,暫時不需要將額外的注意力全部放到一些不關乎本質的東西上。

對於效能的分析:

  • 使用瀏覽器的效能分析工具,得到效能分析圖表,最著名的就是反向火焰圖表,針對瀏覽器的載入和渲染一目瞭然。
  • 投入使用之前缺乏壓力測試和效能測試

 

效能優化(從使用者輸入網址到客戶端展現,一步一步優化)
  1.   輸入網址           ==> 告訴瀏覽器你要去哪裡

  2.   瀏覽器查詢DNS        ==> 網路世界是IP地址的世界,DNS就是ip地址的別名。從本地DNS到最頂級DNS一步一步的網上爬,直到命中需要訪問的IP地址
    a.   DNS預解析 使用CDN快取,加快解析CDN尋找到目標地址(dns-prefetch)

 

  3. 客戶端和伺服器建立連線   ==>建立TCP的安全通道,3次握手
    a.  CDN加速 使用內容分發網路,讓使用者更快的獲取到所要內容
    b.  啟用壓縮 在http協議中,使用類似Gzip壓縮的方案(對伺服器資源不足的時候進行權衡)
    c.  使用HTTP/2協議 http2.0針對1.0優化了很多東西,包括非同步連線複用,頭壓縮等等,使傳輸更快

 

  4.  瀏覽器傳送http請求      ==> 預設長連線(複用一個tcp通道,短連線:每次連線完就銷燬)
    a.  減少http請求 每個請求從建立到銷燬都會消耗很多資源和時間,減少請求就可以相對來說更快展示內容
      1).  壓縮合並js檔案以及css檔案
      2).  針對圖片,可將圖片進行合併然後下載,通過css Sprites切割展示(控制大小,太大的話反而適得其反)
    b.  使用http快取 快取原則:越多越好,越久越好。讓客戶端傳送更少請求,直接從本地獲取,加快效能。
    c.  減少cookie請求 針對非必要資料(靜態資源)請求,進行跨域隔離,減少傳輸內容大小。
    d.  預載入請求 針對一些業務中場景可預載入的內容,提前載入,在之後的使用者操作中更少的請求,更快的響應
    e.  選擇get和post 在http定義的時候,get本質上就是獲取資料,post是傳送資料的。get可以在一個TCP報文完成請求,但是post先發header,再傳送資料。so,考慮好請求選型。
    f.   快取方案選型 遞進式快取更新(防止一次性丟失大量快取,導致負載驟多)

 

  5.  伺服器響應請求        ==> tomcat、IIS等伺服器通過本地對映檔案關係找到地址或者通過資料庫查詢到資料,處理完成返回給瀏覽器
    a.  後端框架選型   
               ==> 更快的響應,前端更快的操作。
    b.  資料庫選型和優化 /

 

  6.  瀏覽器接受響應 ==> 瀏覽器根據報文頭裡面的資料進行不同的響應處理
    a.  解耦第三方依賴 越多的第三方的不確定因素,會導致web的不穩定性和不確定性
    b.  避免404資源 請求資源不到浪費了從請求到接受的所有資源

 

  7.  瀏覽器渲染順序 ==> a.HTML解析開始構建dom樹
    b. 外部指令碼和樣式表載入完畢
      a).  儘快載入css,首先將CSSOM物件渲染出來,然後進行頁面渲染,否則導致頁面閃屏,使用者體驗差
      b).  css選擇器是從右往左解析的,so類似#test a {color: #444},css解析器會查詢所有a標籤的祖先節點,所以效率不是那麼高
      c).  在css的媒介查詢中,最好不要直接和任何css規則直接相關。最好寫到link標籤中,告訴瀏覽器,只有在這個媒介下,載入指定這個css
    c. 指令碼在文件內解析並執行
      a).  按需載入指令碼,例如現在的webpack就可以打包和按需載入js指令碼
      b).  將指令碼標記為非同步,不阻塞頁面渲染,獲得最佳啟動,保證無關主要的指令碼不會阻塞頁
      c). 慎重選型框架和類庫,避免只是用類庫和框架的一個功能或者函式,而引用整個檔案。
    d. HTML DOM完全構造起來
      a).  DOM 的多個讀操作(或多個寫操作),應該放在一起。原則:統一讀、統一寫。
    e. 圖片和外部內容載入
      a).  對多媒體內容進行適當優化,包括恰當使用檔案格式,檔案處理、漸進式渲染等
      b).  避免空的src,空的src仍然會傳送請求到伺服器
      c).  避免在html內容中縮放圖片,如果你需要使用小圖,則直接使用小圖
    f. 網頁完成載入
      a).  服務端渲染,特別針對首屏載入很重要的網站,可以考慮這個方案。後端渲染結束,前端接管展示。

 

    a) 針對首屏展示優化

      1).  圖片懶載入 針對展示只載入第一屏,等使用者進行滾動的時候再進行載入。如果使用者對下面內容不感興趣,那麼節省的請求。

      2).  瀏覽器本地快取模組   可以通過按模組去劃分,將頁面的模組快取到localStory中,每次請求核對模組版本號,丟失或者版本不一致重新請求,否則直接從本地拿(參考京東)

    b) javascript優化
      1).  減少對dom節點的查詢,因為每次都會重新去索引這個集合或者元素。或者查詢一次快取起來,以待接下來使用
      2).  進行js操作DOM的時候,考慮清楚頁面的重繪和重排,因為這些操作相對來說十分損耗效能的。
      3).  避免使用eval和Function構造,因為解析器會將這些內容先轉換成可執行程式碼,然後再進行接下去的操作。
      4).  減少作用域鏈的查詢,如果一個閉包函式使用到全域性作用域的資料,那麼每次區域性作用域都會一層一層爬到最高作用域取得資料。
      5).  資料訪問,對非引用型別資料訪問和區域性變數的訪問是最快的。所以如果對引用型別的成員(物件的屬性或者陣列的成員)訪問超過一次,則快取
      6).  將前端可能會使用的一些演算法函式寫的更優化,在時間和空間複雜度上尋找到一個最優方案。
      7).  去除重複載入同一模組指令碼
      8).  智慧事件處理,比如在一個div下有10個按鈕,可以在冒泡過程中捕獲這個事件源,然後註冊

    c)  css優化
      1).  刪除無用規則
      2).  內聯關鍵CSS
      3).  避免@imports和Base64
      4).  啟用高價效比屬性(如opacity over rgba())
      5).  避免重複性工作
      6).  不要一條條地改變樣式,而要通過改變class,或者csstext屬性,一次性地改變樣式。
      7).  可將元素設為display: none(需要1次重排和重繪),然後N次操作,最後恢復顯示
      8).  position屬性為absolute或fixed的元素,重排的開銷會比較小,因為不用考慮它對其他元素的影響。

    d)  圖片優化(網路請求中80%都是靜態資源的請求)
      1).  圖片正確格式的選擇
      2).  圖片尺寸的選擇,在低解析度等狀況下考慮降級處理(考慮響應式圖片)
      3).  使用正確的工具進行優化(有失真壓縮、無失真壓縮)
      4).  能用css處理和代理的,優先考慮css實現(陰影,濾鏡等)
      5).  正確使用data url,比如說多地使用的地方,不建議data url,可考慮快取
      6).  考慮圖片的懶載入和元素可見載入方案
      7).  圖片的預載入,在正確的合理的設計節點進行圖片的預載入

所有效能優化總結為三個層面優化:物理層面的優化,設計層面的優化,程式碼層面的優化

注:設計層優化最主要的核心:衡量如何花費最少代價實現頁面功能
注:HTTP/2(超文字傳輸協議第2版,最初命名為HTTP 2.0),是HTTP協議的的第二個主要版本,HTTP/2的目標包括非同步連線複用,頭壓縮和請求反饋管線化並保留與HTTP 1.1的完全語義相容。Google Chrome、Mozilla Firefox、Microsoft Edge和Opera已支援HTTP/2,並預設啟用。Internet Explorer自IE 11開始支援HTTP/2,但僅限於Windows 10 Beta,並預設情況啟用。

 

github地址:   鄙人厚顏無恥要顆星,這樣才有動力持續更新

問題補充路徑:

  1. 部落格留言

  2. gerry.zhong@outlook.com

  3.github留言


相關文章