大前端性能總結

NO IMAGE

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/6844903545016156174)
    • 當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):

相關文章

微前端說明書

深入理解Webpack打包分塊(上)

WebAssembly系列一:WebAssembly介紹

Flutter系列一:Flutter快速入門