聊聊前端性能指標那些事兒

来源:https://www.cnblogs.com/jingdongkeji/archive/2023/03/28/17264361.html
-Advertisement-
Play Games

作為 C 端前端研發,除了攻剋業務難點以外,也要有更深層的自我目標,那就是性能優化。這事兒說大不大,說小也不小,但難度絕對不一般,所涉及的範圍優化點深入工程每個細胞。做好前端性能優化絕非簡單之事!文章主要內容介紹前端性能考核指標及優化方案。 ...


作者:京東科技 郝梁

前言:作為 C 端前端研發,除了攻剋業務難點以外,也要有更深層的自我目標,那就是性能優化。這事兒說大不大,說小也不小,但難度絕對不一般,所涉及的範圍優化點深入工程每個細胞。做好前端性能優化絕非簡單之事!文章主要內容介紹前端性能考核指標及優化方案。

一、前端性能指標有哪些?

根據 chrome Lighthouse 最新規則,前端性能指標考量主要有 FCP(First Contenful Paint)、SI(Speed Index)、LCP(Largest Contentful Paint)、TBT(Total Blocking Time)、CLS(Cumulative Layout Shift) ,占比分別如下。

二、什麼是 FCP ?

FCP: First Contentful Paint 首次內容繪製是指測量頁面從開始載入到頁面內容(文本、圖片、背景圖、svg 元素或非白色 canvas 元素)的任何部分在屏幕上完成渲染的時間,是測量載入速度感知的重要指標之一。

示例:

從上圖可以觀察到,頁面載入開始到頁面渲染完成的時間軸中,FCP 發生在第二幀,首批文本和圖片在屏幕上已經渲染完成。

雖然頁面一部分內容已完成渲染,但這並非頁面所有內容全部完成渲染;這就是首次內容繪製(FCP)與最大內容繪製(LCP)最重要的區別。

FCP 性能值:首次內容繪製完成渲染時間應控制在 1.8s 以內。

我們可以從以下方向點優化 FCP :

消除阻塞渲染的資源: <script> 標簽:在 <head> 標簽內的,並且沒有 defer/async 屬性 <link rel="stylesheet"> 標簽:沒有 disabled 屬性,有 media="all" 屬性被認為是渲染阻塞 縮小 CSS 體積:寫法,壓縮 CSS 移除未使用的 CSS 預連接到所需的來源: <link rel="preconnect"> 減少伺服器響應時間(TTFB) 避免多個頁面重定向:瀏覽器請求已定向的資源時,伺服器會返回一個 HTTP 響應,然後瀏覽器必須在新位置發出另一個 HTTP 請求來檢索資源。這種額外的網路傳輸會使資源載入延遲數百毫秒。 預載入關鍵請求:<link rel="preload" href="styles,css" as="style" /> 避免巨大的網路負載:網路負載的中位數在 1700 到 1900 KiB 之間。 Lighthouse 會標記總網路請求超過 5000 KiB 的頁面。將總位元組大小保持在 1600 KiB 以下。 縮小和壓縮網路有效負載:縮小(代碼),數據壓縮(Gzip,Brotli) 圖片使用 Webp JPEG 圖片壓縮級別設置為 85 對靜態資源使用高效的緩存策略:可緩存資源 字體、圖像、媒體文件、腳本或樣式表 資源具有 200 、 203 、 206 HTTP 狀態碼 資源沒有明確的無緩存策略 避免 DOM 過大: 會造成網路效率和負載性能差 頁面交互時,會導致重新計算節點的位置和樣式,降低渲染速度 可能會不知不覺存儲大量節點的引用,造成記憶體過大 最小化關鍵請求深度:鏈的長度越長,下載量越大,對頁面載入性能的影響就越大 減少關鍵資源數量(刪除,推遲下載,標記 async 等) 優化關鍵位元組數減少下載時間 優化剩餘關鍵資源的載入順序,儘早下載所有關鍵資源,縮短關鍵路徑長度 確保文本在網頁字體載入期間保持可見:預載入網路字體 保持較低的請求數和較小的傳輸大小: CSS 和 JavaScript ,圖片,字體,文件,媒體
 

三、什麼是 Speed Index ?

SI:Speed Index 衡量頁面載入期間內容以視覺方式顯示的速度。 Lighthouse 首先捕獲瀏覽器中頁面載入的視頻,並計算幀之間的視覺速度。通俗的講,就是網頁從有東西到完全顯示內容的可見填充速度。

Speed Index 指標值:

 


 

我們可以從以下方向點優化 Speed Index 的方法:

減少主線程工作 減少 JavaScript 執行時間 確保文本在 webfont 載入期間保持可見
 

四、什麼是 LCP ?(重點)

LCP: Largest Contentful Paint 最大(最有意義)內容繪製,是指根據頁面首次開始載入的時間點來報告可視區域內可見的最大圖像或者文本塊完成渲染的相對時間。

 


 

LCP 指標值:

LCP <= 2.5s 合格 2.5s < LCP <= 4s 需要優化 LCP > 4s 劣質
 

1. LCP 考量的元素有哪些?

主要考量以下幾種相關元素:

<img> 元素 內嵌在 <svg> 元素內的 <image> 元素 video 元素(使用封面圖片) 通過 url()函數載入的帶有背景圖像的元素 帶有文本或其他行內元素文本的塊級元素

2. LCP 元素大小是如何定義的?

最大內容繪製(LCP)的元素大小是指用戶在可視區域內可見的大小,所以考量都是基於可視區域為準,如果元素有延伸到可視區域外,或者元素被裁剪或包含不可見的溢出,這些部分不計入元素大小;

對於圖像元素的大小,指標會對比可見尺寸與原始尺寸,取尺寸小者為準;例如雙倍圖以可見尺寸為準,拉伸放大圖則以原始尺寸為準;

對於文本元素,元素的大小為文本節點的大小(包含所有文本節點的最小矩形);

WARNING: 所有元素通過 CSS 設置的任何邊距、填充或邊框都不在考量範圍內。另外如果設置了滿屏背景圖,但屏幕可視區域內有占比較大的元素(浮在背景圖上的元素),導致背景圖暴漏可視範圍較小,那麼最大內容會選擇可視區域內最大元素。

並且,一個元素只有在渲染完成後對用戶可見後才能視為最大內容元素。

3. LCP 繪製時間上報

因為網路或技術原因,網頁的載入通常是分段進行的, 所以最大元素也在發生變化。

為了應對這種變化,瀏覽器在繪製第一幀後立即分發一個 largest-contentful-paint 類型的 PerformanceEntry (代表了 performance 時間列表中單個 metric 數據;performance.getEntries() 獲取時間列表數據),用於識別最大內容元素。渲染後續幀之後,瀏覽器會在最大內容元素髮生變化時分發另一個 PerformanceEntry 。

頁面的元素(某一個元素)只有在渲染完成後並且對用戶可見後才能視為最大內容元素。未載入的圖像不會視為渲染完成,也就不能視為最大內容元素。字體阻塞期使用字體的文本也是如此。這些情況下,較小的元素會被報告為最大的元素,但一旦更大的元素渲染完成,則會上報另一個 PerformanceEntry 對象。

除了延遲載入的圖像與字體外,頁面可能會在新內容(介面請求等)可用時向 DOM 添加新元素內容。如果有一個新元素大於先前的最大內容元素,則瀏覽器還會上報一個新的 PerformanceEntry 對象。

如果當前的最大內容元素從可視區域被移除(甚至從 DOM 中被移除),那麼除非有一個更大的元素完成渲染,否則該元素將持續作為最大內容元素,不會更改 performanceEntry 對象。

當用戶與頁面進行交互(通過輕觸、滾動或按鍵)時,瀏覽器將立即停止上報 PerformanceEntry 對象,因為用戶交互通常會改變頁面原有內容。

瀏覽器出於安全考慮,對於缺少 Timing-Allow-Origin 標頭的跨域對象來說,是無法得到圖像渲染時間戳的,只有圖像載入時間戳。正確的設置 Timing-Allow-Origin 標頭,可以獲取更準確的指標值。

4. 當元素佈局和元素大小更改時,哪些情況會影響 LCP

情況1:對元素大小或位置修改不會生成新的 LCP 候選對象,只有元素在可視區域內的初始大小和位置會被納入考量範圍;

情況2:最初在可視範圍內渲染,然後被移除可視區域外的元素仍將報告他在可視區域內的初始大小;

情況3:而在屏幕可視範圍外渲染完成,過度到屏幕上的元素則不做報告。

示例:最大元素隨著內容載入完成而發生改變

 


 

 


 

第一個示例中,新內容渲染完成,因此使最大元素髮生了改變。

第二個示例中,由於佈局的改變,先前的最大內容從可視區域中被移除了。

如果延遲內容沒有初始最大元素大,則 LCP 取初始值。

5. 最大元素並非重要元素

頁面上最重要元素並非最大元素,這個時候開發者考核指標是最重要元素。

6. 更快的渲染主要內容,降低 LCP 值

影響頁面渲染性能主要原因有以下幾點,通過優化它們可以降低 LCP 指標值

(1) 伺服器響應速度:

是指瀏覽器從伺服器接收內容所需的時間越長,用戶在屏幕上所渲染內容的時間就越長。更快的伺服器將直接影響包括 LCP 各項指標的載入值。

可優化方向:

優化伺服器性能 將用戶路由到附近的 CDN 緩存資源 優先使用緩存提供 HTML 頁面 儘早建立第三方鏈接 使用簽名交換
(2) 阻塞渲染的 JS 和 CSS :

瀏覽器渲染內容之前需要先解析 DOM 樹,解析過程中,如果遇到任何外部樣式表(<link rel="stylesheet">)或同步 JavaScript 標簽(<script src="main.js">),則會暫停解析。

所以腳本跟樣式都是阻塞渲染的資源,這些資源都會導致 FCP 延遲,從而導致 LCP 延遲。所以延遲載入非必要的 JS 和 CSS ,從而提高網頁主要內容載入速度。

減少 CSS 阻塞時間的方法:

消減 CSS : 刪除 CSS 中的空格、換行、縮進、註釋等字元 延遲載入非關鍵 CSS : 將初始渲染時不需要的 CSS 提取到一個文件,進行非同步載入 內聯關鍵 CSS : 把首屏內容的關鍵 CSS 直接包在 <head> 中,將 CSS 內聯; Critters 是一個 webpack 插件,能夠內聯關鍵 CSS 並對其餘部分進行懶載入

減少阻塞渲染的 JavaScript 數量能夠讓渲染速度更快,降低 LCP 值

減少 JS 阻塞時間的方法:

消減壓縮 JavaScript 文件 延遲載入未使用的 JavaScript 文件 最大限度的減少未使用的 polyfill
(3) 緩慢的資源載入速度 :

雖然 CSS 或 JavaScript 阻塞時間的增加會直接導致性能下降,但載入許多其他類型資源所需的時間也會影響繪製時間。

影響 LCP 的元素有以下幾種:

<img> 標簽 內嵌 <svg> 的 <image> 標簽 <video> 元素的封面圖 通過 url() 函數載入的帶有背景圖的元素 包含文本節點或其他行內級文本元素的塊級元素

優化方法:

優化圖片: 壓縮圖片,使用 webp 格式,圖片資源上傳 CDN ;當然能用代碼實現儘量不使用圖片;、 預載入重要資源: 使用 <link rel="preload"> 提高優先順序進行下載和緩存; 壓縮文本文件: Gzip、Brotli (google 出版) 基於網路連接交付不同資產(自適應服務): navigator.connection.effectiveType (有效連接類型 4G), navigator.connection.saveData (啟用/禁用數據保護程式), navigator.hardwareConcurrency (cpu 核心數), navigator.deviceMemory (設備記憶體) 緩存資源: service woker 在 worker 上下文中運行: 因此它沒有 DOM 訪問許可權,並且是運行在不同線程上,因此它是非阻塞的。
(4) 客戶端渲染:

如 React 、 Vue 、 Angular 這類框架所搭建的單頁面應用,是完全在客戶端中處理邏輯的。

優化方法:

最小化關鍵 JavaScript : 精簡 JavaScript , 延遲載入未使用的 JavaScript , 最大限度減少未使用的 polyfill 使用服務端渲染: 用伺服器將主要內容首先在伺服器渲染為 HTML , 客戶端將所有 JavaScript 及所需數據"水合"到相同的 DOM 內容中 使用預渲染: 使用無頭瀏覽器,提前搭建每個路由的靜態 HTML 文件,然後將這些文件與應用程式所需的 JavaScript 包一起運送
 

五、什麼是 TBT ?

TBT: Total Blocking Time 總阻塞時間,是頁面被阻塞響應用戶交互的總時間。 TBT = LCP (首次最大內容繪製)和可交互時間之間所有長時間任務的阻塞部分之和。是測量頁面載入響應的重要指標。

超過 50 毫秒的任務即為長任務。 超出 50 毫秒的時間量為阻塞部分。

例如:檢測到一個 90 毫秒的任務,則阻塞部分為 40 毫秒(90 - 50 = 40)

TBT 指標:

 


 

優化方法:

減少不必要的 JavaScript 載入、解析或執行。減少 JavaScript 負載、刪除未使用的代碼或有效載入第三方 JavaScript 可以提高 TBT 分數。 減少低效的 JavaScript 語句。例如: document.querySelectorAll('a') 會返回所有符合的節點
 

六、什麼是 CLS ?

CLS: 累計佈局偏移(CLS)是測量視覺穩定性的重要指標。是整個頁面聲明周期內發生的所有意外佈局偏移中最大一連串的佈局偏移分數。

頁面內容的意外偏移大多是由於非同步資源載入,或者動態添加 DOM 元素到頁面現有內容上方導致的。罪魁禍首可能是未知尺寸的圖像或視頻、實際渲染後比後備字體更大或更小的字體等。

CLS 指標:

 


 

註意: 只有當現有元素的起始位置發生變更時才算做佈局偏移。如果將新元素添加到 DOM 或是現有元素更改大小,則不算做佈局偏移。只有當元素的變更會導致其他可見元素的起始位置發生變化,才叫偏移。

計算公式: 佈局偏移分數 = 影響分數 x 距離分數

影響分數: 前一幀和當前幀的所有不穩定元素的課件區域集合(占總可視區域的部分)就是當前幀的影響分數。

距離分數: 指的是任何不穩定元素在一幀中位移的最大距離(水平或垂直)除以可視區域的最大尺寸維度(寬度或高度,以較大者為準)。

產生 CLS 的常見原因:

無尺寸的圖片 無尺寸的廣告,嵌入和 iframe 動態註入的內容 導致不可見文本閃爍(FOIT)、無樣式文本閃爍(FOUT)的網路字體 在更新 DOM 之前等待網路響應的操作

優化方法:

在圖片和視頻元素上包含尺寸屬性 非用戶交互響應的情況下,都不要在現有的內容上方插入其他內容 首選轉換動畫,而不是觸發佈局偏移的屬性動畫
 

以上五個指標就是目前前端性能指標考量點,以及產生問題原因,優化方法等。每個優化點都可以擴展出很多知識以及學習點,所以前端優化這個工作鏈路依然很長;單一點的優化效果可能並不明顯,但五個點全部優化,定然會有質的飛躍。

在實際項目中,優先從前端自身出發,優化完自身後,再去優化協同項。

另外前端優化是一件可持續,並長久的事情,工具技術升級的迭代也會提升項目性能,針對優化這樣的工作一定要持續下去,而不是做一次就OK了。

前端性能優化這條路,道阻且長,行則將至,專研就會有進步,最終定然會成功達到目標。

文章參考: https://web.dev/ https://developer.chrome.com/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Admin.NET 是一套基於Furion/.NET 6實現的通用管理平臺,模塊插件式開發,框架包含了常規的許可權管理、字典等管理模塊,以及一些Vue3的Demo案例,框架前後端分離。後端基於基於Furion/.NET 6實現,底層集成SqlSugar;前端則是採用Vue-Next-Admin的前端框... ...
  • Element UI 是一套基於 Vue.js 的組件庫,它提供了一系列常用的 UI 組件,包括表單、彈窗、佈局、導航等等。Element UI 的設計風格簡潔、易用、美觀,且易於定製。 Element UI 的主要特點包括: 基於 Vue.js 開發,組件易於使用和定製。 提供了豐富的 UI 組件 ...
  • 配置開發環境 腳手架工具create-react-app 儲備知識:終端或命令行、代碼編輯器 React官方中文文檔 create-react-app 其是基於Node的快速搭建React項目的腳手架工具。 npx create-react-app testdemo cd testdemo npm ...
  • 其他章節請看: webgl 系列 著色器語言 本篇開始學習著色器語言 —— GLSL全稱是 Graphics Library Shader Language (圖形庫著色器語言) GLSL 是一門獨立的語言,和其他語言一樣有自己的變數、運算符、函數、迴圈(for)、控制語句(if)、函數、數組等等。 ...
  • 本博文介紹HTML中的表單標簽,包含form表單域、input輸入表單、label標簽、select下拉表單和textarea文本域。 ...
  • ECMAScript(簡稱 ES)是一種由 Ecma 國際組織定義的腳本語言標準,它定義了 JavaScript 語言的基本規範和特性。JavaScript 是一種基於 ECMAScript 標準的編程語言,因此 ECMAScript 對於 JavaScript 開發來說非常重要。 ECMAScri ...
  • TS:是JS的超集,即對JS的擴展,主要提供了類型系統和對ES6+的支持,但TS最終會轉換為js代碼去執行。 特點: 1. 始於JavaScript, 歸於JavaScript 2. 強大的類型系統 3. 先進的JavaScript | | TypeScript | JavaScript | | | ...
  • Vue.js 是一個前端開發框架,它可以幫助我們快速構建單頁應用和複雜的交互界面。而 Webpack 則是一個前端資源打包工具,它可以將多個 JavaScript、CSS、HTML、圖片等資源打包成一個或多個文件,並提供模塊化載入、壓縮、混淆等功能,以便於前端開發和部署。 在使用 Vue.js 開發 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...