大前端效能總結

Gavin1995發表於2018-05-21

Node端效能

效能評估

  1. 通過效能測試工具評估:

    • wrk:支援lua指令碼,可以輕鬆應對各種測試需求,如
    -- 帶隨機引數請求
    function request()
        wrk.headers["Connection"] = "keep-Alive"
        arg = math.random(1, 500)
        path = "/random?arg=" .. arg
        return wrk.format("GET", path)
    end
    複製程式碼
  2. 通過v8 profiling檢視程式執行過程資料,與Webstorm聯合使用,可以在Webstorm【Run/Debug Configurations】裡面配置,注意需要先安裝:v8-profiler

常見優化方案

  1. 併發請求,例如:promise.all併發三方HTTP介面呼叫、RPC呼叫
  2. 如果用到mysql
    • 使用資料庫連線池,重用連線
    • 常用查詢建立索引
    • 用程式避免聯合查詢
    • 讀寫分離
  3. 加入快取策略

前端效能

DNS查詢

  • 減少DNS查詢次數

TCP/HTTP

優化核心

  1. 消除和減少不必要的網路延遲
  2. 把傳輸位元組數降到最少

具體步驟

  • 減少HTTP請求:對於HTTP1.0/1.1 減少請求資源數(打包、壓縮、合併等)
  • 使用CDN
  • 新增Expires首部並配置ETag標籤
  • GZip資源
  • 避免HTTP重定向
  • 持久化連線:避免TCP的三次握手,HTTP1.1預設開啟,HTTP1.0可以使用:Connection: Keep-Alive
  • HTTP1 不支援多路複用,可以為一臺主機並行開啟多個TCP會話(一般為6個)
  • 消除不必要的請求位元組(HTTP1 請求、響應頭不會被壓縮)
  • 嵌入資源,如:Base64嵌入資源(針對小的靜態圖片資源)

客戶端渲染

關鍵渲染路徑:DOM -> CSSDOM / JS -> RenderTree -> Layout -> Paint

大前端效能總結

大前端效能總結

瀏覽器渲染過程

構建DOM

  • 構建過程:character -> token -> node -> DOM
  • 增量構建

構建CSSOM(CSS Object Model)

  • 構建過程:character、token、node、CSSOM
  • 選擇器越複雜,匹配用的時間約多

構建RenderTree

  • RenderTree包含所有需要呈現在頁面上的節點資訊
  • display: none的元素不會被新增到RenderTree中,因為它不需要被渲染,visibility: hidden的元素會被新增到RenderTree中

Layout

  • 計算需要渲染的節點的大小和位置
  • 節點位置和大小是基於將viewport計算的
  • 在移動端通常將viewport設定為瀏覽器推薦的理想視口,以保證字型顯示大小易於閱讀
  • 旋轉螢幕、修改瀏覽器視窗大小,修改位置大小相關的CSS屬性,都可能觸發Layout

Paint

  • 根據background、border、box-shadow等樣式,將Layout生成的區域填充為最終將顯示在螢幕上的畫素

資源優化

CSS效能優化(防止資源阻塞初次渲染)

  • media query(link裡面加上media)
    • 此時樣式表仍然會載入,當瀏覽器環境不匹配媒體查詢條件時,該樣式表不會阻塞渲染
    • 針對不同媒體環境拆分CSS檔案,避免為了載入非關鍵CSS資源,而阻塞初次渲染
  • 使用DOM API新增link不會阻塞初次渲染
var style = document.createElement('lin');
style.rel = 'stylesheet';
style.href = 'index.css';
document.head.appendChild(style);
複製程式碼
  • preload & prefetch & prerender(不止可以用於CSS)
    • rel="preload",不是stylesheet不會阻塞渲染
    • preload是resource hint規範中定義的一個功能,resource hint告知瀏覽器提前建立連線或載入資源,以提高資源載入的速度:
      • preload:https://www.w3.org/TR/preload/
      • prefetch & prerender:https://w3c.github.io/resource-hints/#prefetch
    • 瀏覽器遇到標記為preload的link時,會開始載入它
    • 當onload事件發生時,將rel改為stylesheet,即可應用此樣式
    • 可以通過 loadCSS.js 使用preload (CSS preload polyfill):原理其實就是使用DOM API
<link rel="preload" type="text/css" href="./style.css" as="style" onload="this.rel='stylesheet'"/>
複製程式碼

JS效能優化

  • JS會阻塞HTML Parse(HTML解析器,增量),因而會阻塞出現在指令碼後面的HTML標記的渲染
  • 原因:JS可以通過document.write修改HTML文件流,因此在執行JS時,瀏覽器會暫停解析DOM的工作
  • CSS會阻塞JS
  • 瀏覽器資源載入策略(preload,與前面CSS preload不一樣,詳見:https://juejin.im/post/5a4ed917f265da3e317df515)
    • 當HTML Parser被指令碼阻塞時,Parser雖然會停止構建DOM,但仍會識別該指令碼後面的資源,並提前載入
  • 效能優化(防止阻塞)
    • 將資源放到body底部
    • 使用defer延遲指令碼執行:使用defer,該指令碼會被推遲到整個HTML文件解析完後,再開始執行。被defer的指令碼,在執行時會嚴格按照在HTML文件中出現的順序執行。使用defer方法,可以提早指令碼資源載入
    • 使用async非同步載入指令碼:該指令碼不會阻塞HTML parser,也不會被CSS阻塞,指令碼載入完就開始執行。async適用於無依賴的獨立資源(比如百度統計程式碼)

大前端效能總結

圖片

  • 使用blob非同步載入
  • 使用img-2代替img標籤(原理與上面一樣),對於圖片多的網站輕鬆提升五倍以上訪問速度

字型

  • 瀏覽器為了避免FOUT(Flash Of Unstyled Text),會盡量等待字型載入完成後,再顯示應用了該字型的內容。帶來了FOIT(Flash Of Invisible Text 問題),導致空白
  • 設定多字型,降級方法:使用預設字型
  • 非同步載入字型檔案:通過非同步載入CSS,即可避免字型阻塞渲染,還是會空白

其它

優化關鍵渲染路徑

優化目標

  • 關鍵資源數
  • 關鍵資源體積
  • 關鍵資源網路來回數

勿盲目內聯資源

  • 若啟用HTTP2,則無需內聯資源
  • 若資源被多個頁面共享,則無法充分利用快取,導致重複得下載

內聯與快取結合

  • 首次訪問,使用內聯,並通過非同步(如:rel="prefetch")請求快取資源,快取成功通過cookie標記,下次訪問時,則只返回外部資源標記

其它

常用工具

效能測試工具

相關資料

補充

TTFB(Time To First Byte):

  • 從客戶端發出請求到接收到第一個響應位元組所花費時間(Transfer-Encoding: chunked)

HTTP2.0主要設計:

  • 解決HTTP中“隊首阻塞”;
  • 二進位制分幀機制,無需建立多個TCP連線,從而改進TCP利用率
  • 保持HTTP1.1語義

隊首阻塞:

  • HTTP應用層隊首阻塞:按照優先順序傳送請求
  • TCP傳輸層隊首阻塞:TCP要求分組嚴格按照順序交付

React效能優化Time Slicing(附Suspence):

相關文章