首頁 > web前端 > js教程 > React 開發人員的初始負載效能:深入研究

React 開發人員的初始負載效能:深入研究

Patricia Arquette
發布: 2025-01-27 18:33:10
原創
159 人瀏覽過

深入探討網頁首屏加載性能及優化策略

Initial load performance for React developers: investigative deep dive

目錄

  1. 初始加載性能指標介紹
  2. 性能 DevTools 概述
    1. 項目設置
    2. 探索必要的 DevTools
  3. 探索不同的網絡條件
    1. 非常慢的服務器
    2. 模擬不同的帶寬和延遲
    3. CDN 的重要性
  4. 重複訪問性能
    1. 使用 Cache-Control 頭控制瀏覽器緩存
    2. Cache-Control 和現代打包工具
    3. 我簡單的用例真的需要了解所有這些嗎?

在 AI 驅動的代碼生成蓬勃發展的今天,編寫 React 代碼的重要性正在下降。現在任何人和任何東西都可以用 React 編寫應用程序。但是編寫代碼一直只是難題的一部分。我們仍然需要將我們的應用程序部署到某個地方,向用戶展示它們,使它們健壯,使它們快速,並做一百萬件其他事情。沒有 AI 可以接管這些。至少現在還不行。

因此,讓我們專注於今天如何使應用程序快速運行。為此,我們需要暫時離開 React。因為在使某些東西變快之前,我們首先需要知道“快”是什麼,如何衡量它,以及什麼可以影響這種“快”。

劇透警告:除了學習項目之外,本文不會出現 React。今天都是關於基礎知識的:如何使用性能工具,Core Web Vitals 簡介,Chrome 性能面板,初始加載性能是什麼,哪些指標可以衡量它,以及緩存控制和不同的網絡條件如何影響它。

初始加載性能指標介紹

當我打開瀏覽器並嘗試導航到我喜歡的網站時會發生什麼?我在地址欄中輸入“https://www.php.cn/link/63ea3fef646010a7255aec506626ea32 GET 請求,並接收 HTML 頁面作為返回。

Initial load performance for React developers: investigative deep dive

執行此操作所需的時間稱為“Time To First Byte”(TTFB):從發送請求到結果開始到達之間的時間。接收 HTML 後,瀏覽器現在必須盡快將此 HTML 轉換為可用的網站。

它首先在屏幕上渲染所謂的“關鍵路徑”:可以向用戶顯示的最小和最重要的內容。

Initial load performance for React developers: investigative deep dive

關鍵路徑中究竟應該包含什麼是一個複雜的問題。理想情況下,一切都是為了讓用戶立即看到完整的體驗。但是同樣 - 什麼也沒有,因為它需要盡可能快,因為它是一條“關鍵”路徑。兩者同時是不可能的,所以需要妥協。

妥協是這樣的。瀏覽器假設要構建“關鍵路徑”,它絕對至少需要以下類型的資源:

  • 它從服務器接收的初始 HTML - 用於構建實際的 DOM 元素,從中構建體驗。
  • 樣式化這些初始元素的重要 CSS 文件 - 否則,如果它在不等待它們的情況下繼續,用戶會在一開始看到奇怪的未樣式化內容“閃爍”。
  • 同步修改佈局的關鍵 JavaScript 文件。

瀏覽器在服務器的初始請求中獲取第一個(HTML)。它開始解析它,並在這樣做的過程中提取它需要完成“關鍵路徑”的 CSS 和 JS 文件的鏈接。然後,它發送請求以從服務器獲取它們,等待它們下載完畢,處理它們,將所有這些組合在一起,並在某個時刻結束時,在屏幕上繪製“關鍵路徑”像素。

由於瀏覽器在沒有這些關鍵資源的情況下無法完成初始渲染,因此它們被稱為“渲染阻塞資源”。當然,並非所有 CSS 和 JS 資源都是渲染阻塞的。通常只有:

  • 大多數 CSS,無論是內聯的還是通過 標籤。
  • 標籤中不是異步或延遲的 JavaScript 資源。

渲染“關鍵路徑”的整個過程大致如下所示:

  • 瀏覽器開始解析初始 HTML
  • 在此過程中,它從標籤中提取 CSS 和 JS 資源的鏈接。
  • 然後,它啟動下載過程並等待阻塞資源完成下載。
  • 在等待的同時,如果可能,它會繼續處理 HTML。
  • 接收所有關鍵資源後,也會處理它們。
  • 最後,它完成需要完成的工作並繪製界面的實際像素。

這個時間點就是我們所說的首次繪製 (FP)。這是用戶第一次有機會在屏幕上看到某些東西。是否會發生取決於服務器發送的 HTML。如果那裡有一些有意義的東西,例如文本或圖像,那麼這一點也將是首次內容繪製 (FCP) 發生的時間。如果 HTML 只是一個空 div,那麼 FCP 將稍後發生。

Initial load performance for React developers: investigative deep dive

首次內容繪製 (FCP) 是最重要的性能指標之一,因為它衡量的是感知到的初始加載。基本上,這是用戶對您的網站速度的初步印象。

直到這一刻,使用者只是在盯著空白螢幕咬指甲。根據 Google 的說法,良好的 FCP 數字是低於 1.8 秒。之後,用戶將開始對您的網站可以提供的內容失去興趣,並可能開始離開。

但是,FCP 並不完美。如果網站以旋轉器或某些加載畫面開始加載,則 FCP 指標將表示該內容。但用戶不太可能只是為了查看花哨的加載畫面而導航到該網站。大多數時候,他們想要存取內容。

為此,瀏覽器需要完成它開始的工作。它等待其餘的非阻塞 JavaScript,執行它,將源自它的更改應用於螢幕上的 DOM,下載圖像,並以其他方式完善用戶體驗。

在這個過程中的某個時間點,就會發生最大內容繪製 (LCP) 時間。它不是像 FCP 那樣非常第一個元素,而是頁面上的主要內容區域 - 視窗中可見的最大文字、圖像或影片。根據 Google 的說法,這個數字理想情況下應該低於 2.5 秒。超過這個數字,用戶會認為網站速度慢。

Initial load performance for React developers: investigative deep dive

所有這些指標都是 Google 的 Web Vitals 的一部分 - 一組代表頁面上使用者體驗的指標。 LCP 是三個核心 Web Vitals之一 - 三個指標代表使用者體驗的不同部分。 LCP 負責載入效能

這些指標可以透過 Lighthouse 來衡量。 Lighthouse 是 Google 的效能工具,它整合到 Chrome DevTools 中,也可以透過 shell 腳本、Web 介面或節點模組運作。您可以將其作為節點模組使用,以便在建置中運行它並在生產環境中出現回歸之前檢測到它們。使用整合的 DevTools 版本進行本地調試和測試。以及 Web 版本來檢查競爭對手的效能。

效能 DevTools 概述

以上是對過程的非常簡短和簡化的解釋。但這已經有很多縮寫和理論讓人的頭腦混亂。對我個人而言,閱讀這樣的內容是沒有用的。除非我能看到它在行動中,並能親自動手操作,否則我會立即忘記所有內容。

對於這個特定主題,我發現完全理解這些概念的最簡單方法是在半真實的頁面上模擬不同的場景,並查看它們如何改變結果。所以在進行更多理論(還有很多!)之前,讓我們先這樣做。

項目設定

如果您願意,您可以在您自己的專案上進行以下所有模擬 - 結果應該或多或少相同。但是,為了更受控制和簡化的環境,我建議您使用我為本文準備的學習項目。您可以在這裡訪問它:https://www.php.cn/link/def14e8541708294d7558fdf2126ef27

先安裝所有相依性:

<code>npm install</code>
登入後複製

建置專案:

<code>npm run build</code>
登入後複製

啟動伺服器:

<code>npm run start</code>
登入後複製

您應該在「https://www.php.cn/link/66e8d052ec2230c66bd11ee6b5a0e3c8

探索必要的 DevTools

在 Chrome 中開啟要分析的網站並開啟 Chrome DevTools。找到那裡的“性能”和“Lighthouse”面板並將它們放在一起。我們需要兩者。

此外,在本文中執行任何其他操作之前,請確保已啟用「停用快取」複選框。它應該位於最頂部的“網路”面板中。

Initial load performance for React developers: investigative deep dive

這樣我們就可以模擬首次訪客 - 從未造訪過我們網站的人,而且瀏覽器還沒有快取任何資源。

探索 Lighthouse 面板

現在打開 Lighthouse 面板。您應該在那裡看到一些設定和“分析頁面載入”按鈕。

Initial load performance for React developers: investigative deep dive

對於本節,我們感興趣的是「導航」模式 - 它將對頁面的初始載入進行詳細分析。該報告將為您提供以下分數:

Initial load performance for React developers: investigative deep dive

本地性能完美無缺,這並不奇怪 - 一切都「在我的機器上運行」。

還會有以下指標:

Initial load performance for React developers: investigative deep dive

我們本文所需的 FCP 和 LCP 值就在頂部。

下面,您將看到一個可以幫助您提高分數的建議清單。

Initial load performance for React developers: investigative deep dive

每個建議都可以展開,您將在那裡找到更詳細的信息,有時還會找到解釋該特定主題的連結。並非所有這些都可以採取行動,但它是一個開始學習表現並了解可以改進它的不同事物的絕佳工具。光是閱讀這些報告和相關連結就可以花費數小時。

但是,Lighthouse 只提供表面信息,不允許您模擬慢速網路或低 ​​CPU 等不同場景。它只是一個很好的切入點和一個追蹤性能隨時間變化的絕佳工具。要更深入地了解正在發生的事情,我們需要「性能」面板。

探索性能面板

首次載入時,「效能」面板應如下所示:

Initial load performance for React developers: investigative deep dive

它顯示了三個核心 Web Vitals 指標,其中一個是我們的 LCP,使您可以模擬慢速網絡和 CPU,以及隨著時間推移記錄性能詳細信息的能力。

在面板頂部找到並選中“屏幕截圖”複選框,然後單擊“記錄並重新加載”按鈕,當網站重新加載自身時 - 停止記錄。這將是您對頁面在初始加載期間發生情況的詳細報告。

此報告將包含幾個部分。

最頂部是常規的“時間軸概述”部分。

Initial load performance for React developers: investigative deep dive

您將在這裡看到網站上正在發生某些事情,但沒有更多內容。當您將鼠標懸停在其上時 - 將顯示正在發生的事情的屏幕截圖,並且您將能夠選擇並放大到特定範圍以仔細查看。

在下面是網絡部分。展開後,您將看到所有正在下載的外部資源以及它們在時間軸上的確切時間。當將鼠標懸停在特定資源上時,您將看到有關在下載的哪個階段花費多少時間的詳細信息。帶有紅色角的資源將指示阻塞資源。

Initial load performance for React developers: investigative deep dive

如果您正在使用學習項目,您將看到完全相同的圖片,並且此圖片與我們在上一節中逐字逐句進行的內容相匹配:

  • 一開始,有一個藍色塊 - 獲取網站 HTML 的請求
  • 加載完成後,稍作暫停(解析 HTML),兩個獲取更多資源的請求發出。
  • 其中一個(黃色)用於 JavaScript - 非阻塞。
  • 另一個(紫色)用於 CSS,這是一個阻塞。

如果您現在打開您的學習項目代碼並查看 dist 文件夾,源代碼將與這種行為相匹配:

  • 將有一個 index.html 文件和 assets 文件夾中的 .css 和 .js 文件
  • 在 index.html 文件中的部分中,將有一個 標籤指向 CSS 文件。正如我們所知, 標籤中的 CSS 資源是渲染阻塞的,所以這可以檢查出來。
  • 此外,在其中還有一個 <script> 標籤指向 asset 文件夾中的 JavaScript 文件。它既不是延遲的也不是異步的,但它具有 type="module"。這些是自動延遲的,所以這也檢查出來了 - 面板中的 JavaScript 文件是非阻塞的。 </script>

附加練習

如果您正在處理某個項目,請記錄其初始加載性能並查看“網絡”面板。您可能會看到更多正在下載的資源。

  • 您有多少個渲染阻塞資源?所有這些都是必要的嗎?
  • 您知道項目的“入口”點在哪里以及阻塞資源如何在 <script> 部分中出現嗎?嘗試使用您的 npm build 變體構建項目並蒐索它們。提示:- 如果您有一個純基於 webpack 的項目,請查找 webpack.config.js 文件。 HTML 入口點的路徑應該在裡面。 </script>
  • 如果您使用 Vite,請查看 dist 文件夾 - 與學習項目相同
  • 如果您使用 Next.js App 路由器 - 請查看 .next/server/app

在“網絡”部分下,您可以找到“幀”和“計時”部分。

Initial load performance for React developers: investigative deep dive

這些非常酷。在“計時”部分,您可以看到我們之前討論過的所有指標(FP、FCP、LCP),以及我們尚未討論的一些指標。當將鼠標懸停在指標上時,您可以看到它花費的確切時間。單擊它們將更新最底部的“摘要”選項卡,您將在其中找到有關此指標的信息和了解更多信息的鏈接。 DevTools 現在都是關於教育人們的。

最後是部分。這是在記錄的時間軸期間在主線程中發生的事情。

Initial load performance for React developers: investigative deep dive

我們在這裡可以看到諸如“解析 HTML”或“佈局”之類的內容以及它花費了多長時間。黃色部分與 JavaScript 相關,它們有點沒用,因為我們使用的是帶有壓縮 JavaScript 的生產版本。但即使在這種狀態下,它也能讓我們大致了解 JavaScript 執行與 HTML 解析和繪製佈局相比需要多長時間,例如。

網絡都打開並放大以佔據整個屏幕時,它對於性能分析尤其有用。

Initial load performance for React developers: investigative deep dive

從這裡,我可以看出我的服務器速度非常快,捆綁包也很快很小。沒有一個網絡任務是瓶頸;它們不需要任何大量時間,它們之間,瀏覽器只是在閒逛並做它自己的事情。因此,如果我想在這裡加快初始加載速度,我需要研究為什麼“解析 HTML”這麼慢 - 它是圖表上最長的任務。

或者,如果我們查看絕對數字 - 我不應該在這裡做任何事情,從性能方面來說。整個初始加載時間少於200 毫秒,遠低於Google 建議的閾值?但這正在發生,因為我是在本地運行此測試(因此沒有實際的網絡成本),在一台非常快的筆記本電腦上,並且使用非常基本的服務器。

是時候模擬現實生活了。

探索不同的網絡條件

非常慢的服務器

首先,讓我們使服務器更逼真。現在,第一個“藍色”步驟大約需要 50 毫秒,其中 40 毫秒只是在等待。

Initial load performance for React developers: investigative deep dive

在現實生活中,服務器將執行某些操作,檢查權限,生成某些內容,再次檢查權限(因為它有很多遺留代碼,並且三遍檢查丟失了),否則將很忙。

導航到學習項目中的 backend/index.ts 文件 (https://www.php.cn/link/def14e8541708294d7558fdf2126ef27)。找到註釋掉的 // await sleep(500),並取消註釋它。這將使服務器在返回 HTML 之前延遲 500 毫秒 - 這對於舊的複雜服務器來說似乎足夠合理。

重新構建項目 (npm run build),重新啟動它 (npm run start) 並重新運行性能記錄。

除了初始藍線之外,時間軸上沒有任何變化 - 與其餘內容相比,它現在非常長。

Initial load performance for React developers: investigative deep dive

這種情況突出了在進行任何性能優化之前查看全局並識別瓶頸的重要性。 LCP 值約為 650 毫秒,其中約 560 毫秒用於等待初始 HTML。它的 React 部分約為 50 毫秒。即使我設法將其減半並將其減少到 25 毫秒,在整體情況中,它也只有 4%。而將其減半將需要大量的努力。更有效的策略可能是專注於服務器並找出它為什麼這麼慢。

模擬不同的帶寬和延遲

並非每個人都生活在 1 千兆位連接的世界中。例如,在澳大利亞,50 兆位/秒是高速互聯網連接之一,每月將花費您約 90 澳元。當然,它不是 3G,全世界很多人都被困住了。但仍然,每次我聽到歐洲人吹噓他們的 1 千兆位/秒或 10 歐元的互聯網計劃時,我都會哭泣。

無論如何。讓我們模擬這個不太好的澳大利亞互聯網,看看性能指標會發生什麼。為此,清除性能選項卡中的現有記錄(重新加載和記錄按鈕附近的按鈕)。網絡設置面板應該顯示出來:

Initial load performance for React developers: investigative deep dive

如果它沒有出現在您的 Chrome 版本中,則相同的設置應該在“網絡”選項卡中可用。

在“網絡”下拉菜單中添加一個新的配置文件,使用以下數字:

  • 配置文件名稱:“平均互聯網帶寬”
  • 下載:50000(50 Mbps)
  • 上傳:15000(15 Mbps)
  • 延遲:40(一般互聯網連接的平均值)

Initial load performance for React developers: investigative deep dive

現在在下拉菜單中選擇該配置文件並再次運行性能記錄。

你看到了什麼?對我來說,它看起來像這樣。

LCP 值幾乎沒有變化 - 從 640 毫秒略微增加到 700 毫秒。初始藍色“服務器”部分沒有任何變化,這是可以解釋的:它只發送最基本的 HTML,因此下載它不應該花費很長時間。

但是可下載資源和主線程之間的關係發生了巨大變化。

Initial load performance for React developers: investigative deep dive

我現在可以清楚地看到渲染阻塞 CSS文件的影響。 “解析 HTML”任務已經完成,但瀏覽器正在閒置並等待 CSS - 在下載之前無法繪製任何內容。將其與之前的圖片進行比較,在之前的圖片中,資源幾乎是即時下載的,而瀏覽器正在解析 HTML。

之後,從技術上講,瀏覽器本可以繪製某些內容 - 但沒有任何內容,我們只在 HTML 文件中發送一個空 div。因此,瀏覽器繼續等待,直到下載並執行 javascript 文件。

這個大約 60 毫秒的等待差距正是我看到的 LCP 的增加。

進一步降低速度以查看它的進展情況。創建一個新的網絡配置文件,將其命名為“低互聯網帶寬”,從“低互聯網帶寬”配置文件複製下載/上傳數字,並將延遲設置為 40 毫秒。

Initial load performance for React developers: investigative deep dive

並再次運行測試。

LCP 值現在已增加到近 500 毫秒。 JavaScript 下載大約需要 300 毫秒。相對而言,“解析 HTML”任務和 JavaScript 執行任務的重要性正在減小。

Initial load performance for React developers: investigative deep dive

附加練習

如果您有自己的項目,請嘗試在其上運行此測試。

  • 下載所有關鍵路徑資源需要多長時間?
  • 下載所有 JavaScript 檔案需要多長時間?
  • 此下載在「解析 HTML」任務之後會導致多大的差距?
  • 在主執行緒中,「解析 HTML」和 JavaScript 執行任務相對於資源下載有多大?
  • 它如何影響 LCP 指標?

資源列內部發生的事情也很有趣。將滑鼠懸停在黃色 JavaScript 條上。您應該在那裡看到類似這樣的內容:

Initial load performance for React developers: investigative deep dive

這裡最有趣的部分是“發送請求並等待”,大約需要 40 毫秒。將滑鼠懸停在其餘的網路資源上 - 所有這些都將擁有它。那是我們的延遲,我們設定為 40 的網路延遲。許多事情都會影響延遲數字。網路連線的類型就是其中之一。例如,平均 3G 連線的頻寬為 10/1 Mbps,延遲在 100 到 300 毫秒之間。

要模擬這一點,請建立一個新的網路設定文件,將其命名為“平均 3G”,從“低網路頻寬”設定檔複製下載/上傳數字,並將延遲設定為 300 毫秒。

再次運行分析。所有網路資源的「發送請求並等待」都應增加到約 300 毫秒。這將進一步推動 LCP 數字:對我來說是1.2 秒

現在是有趣的部分:如果我將頻寬恢復到超高速但保持低延遲會發生什麼?讓我們嘗試此設定:

  • 下載:1000 Mbps
  • 上傳:100 Mbps
  • 延遲:300 毫秒

如果您的伺服器位於挪威某個地方,而客戶端是富有的澳洲人,則很容易發生這種情況。

這是結果:

Initial load performance for React developers: investigative deep dive

LCP 數字約為960 毫秒。它比我們之前嘗試過的最慢的網路速度還要差!在這種情況下,捆綁包大小並不重要,CSS 大小根本不重要。即使您將兩者都減半,LCP 指標幾乎不會移動。高延遲勝過一切。

這讓我想到了每個人都應該實現的第一個效能改進,如果他們還沒有實現的話。它被稱為「確保靜態資源始終透過 CDN 提供服務」。

CDN 的重要性

CDN(內容分發網路)基本上是任何前端效能相關工作的第 0 步,甚至在開始考慮更花俏的東西(如程式碼分割或伺服器元件)之前。

任何 CDN(內容分發網路)的主要目的是減少延遲並儘快將內容交付給最終用戶。它們為此實施了多種策略。本文最重要的兩個是「分散式伺服器」和「快取」。

CDN 供應商將在不同的地理位置擁有多個伺服器。這些伺服器可以儲存靜態資源的副本,並在瀏覽器請求它們時將它們傳送給使用者。 CDN 基本上是您原始伺服器周圍的一個軟層,可以保護它免受外部影響並最大限度地減少它與外部世界的互動。它有點像內向者的 AI 助手,它可以在無需讓真人參與的情況下處理典型的對話。

在上面的範例中,我們的伺服器位於挪威,客戶端位於澳大利亞,我們有這樣的圖片:

Initial load performance for React developers: investigative deep dive

有了中間的 CDN,圖片就會改變。 CDN 將在更靠近用戶的地方擁有一個伺服器,例如,也在澳洲某個地方。在某個時刻,CDN 將從原始伺服器接收靜態資源的副本。之後,來自澳洲或附近任何地方的用戶都將獲得這些副本,而不是來自挪威伺服器的原始副本。

它實現了兩個重要的事情。首先,原始伺服器上的負載減少了,因為用戶不再需要直接存取它。其次,用戶現在可以更快地獲得這些資源,因為他們不再需要跨越海洋來下載一些 JavaScript 檔案了。

Initial load performance for React developers: investigative deep dive

而我們上面模擬中的 LCP 值從960 毫秒下降到 640 毫秒?

重複存取效能

到目前為止,我們只討論了首次訪問性能 - 從未訪問過您網站的人的性能。但希望該網站如此出色,以至於大多數首次訪客都會變成常客。或者至少他們在第一次加載後不會離開,瀏覽幾個頁面,也許會購買一些東西。在這種情況下,我們通常期望瀏覽器會快取靜態資源(如 CSS 和 JS)- 即在本地保存它們的副本,而不是總是下載它們。

讓我們看看在這種情況下表現圖表和數字如何變化。

再次開啟學習項目。在開發工具中,將“網路”設定為我們之前創建的“平均 3G” - 具有高延遲和低頻寬,這樣我們就可以立即看到差異。並確保「停用網路快取」複選框未選取。

Initial load performance for React developers: investigative deep dive

首先,刷新瀏覽器以確保我們正在消除首次訪客的情況。然後刷新並測量性能。

如果您使用的是學習項目,最終結果可能會有些令人驚訝,因為它看起來像這樣:

Initial load performance for React developers: investigative deep dive

CSS 和 JavaScript 檔案在網路標籤中仍然非常突出,我看到它們在「發送請求並等待」中大約有 300 毫秒 - 我們在「平均 3G」設定檔中設定的延遲設定。結果,LCP 並不像它可能的那麼低,而且當瀏覽器只是等待阻塞 CSS 時,我有一個 300 毫秒的差距。

發生了什麼事?瀏覽器不應該快取這些東西嗎?

使用 Cache-Control 頭控制瀏覽器快取

我們現在需要使用「網路」面板來了解發生了什麼。打開它並在那裡找到 CSS 文件。它應該如下圖所示:

Initial load performance for React developers: investigative deep dive

這裡最有趣的是「狀態」列和「大小」。在「大小」中,它絕對不是整個 CSS 檔案的大小。它太小了。在「狀態」中,它不是我們通常的 200「一切正常」狀態,而是不同的東西 - 304 狀態。

這裡有兩個問題 - 為什麼是 304 而不是 200,以及為什麼根本發送了請求?為什麼快取不起作用?

首先,304 回應。這是一個配置良好的伺服器為條件請求發送的回應 - 其中回應根據各種規則而變化。此類請求經常用於控制瀏覽器快取。

例如,當伺服器接收到 CSS 檔案的請求時,它可以檢查上次修改檔案的時間。如果此日期與瀏覽器端快取檔案中的日期相同,則它將傳回帶有空白正文的 304(這就是為什麼它只有 223 B)。這表示瀏覽器可以安全地重新使用它已經擁有的檔案。無需浪費頻寬並再次重新下載它。

這就是為什麼我們在效能圖片中看到很大的「發送請求並等待」數字 - 瀏覽器要求伺服器確認 CSS 檔案是否仍然是最新的。這就是為什麼那裡的“內容下載”是 0.33 毫秒 - 伺服器返回“304 未修改”,瀏覽器只是重新使用了先前下載的檔案。

附加練習

  1. 在學習專案中,前往 dist/assets 資料夾並重新命名 CSS 檔案
  2. 前往 dist/index.html 檔案並更新重命名 CSS 檔案的路徑
  3. 刷新已開啟的頁面並開啟「網路」選項卡,您應該會看到 CSS 檔案以新名稱、200 狀態和正確的大小出現 - 它已再次下載。這被稱為“快取清除” - 一種強制瀏覽器重新下載它可能已快取的資源的方法。
  4. 再次刷新頁面 - 它已返回到 304 狀態並重新使用快取的檔案。

現在,對於第二個問題 - 為什麼根本發送了這個請求?

此行為由伺服器設定為回應的 Cache-Control 標頭控制。點擊“網頁”面板中的 CSS 檔案以查看請求/回應的詳細資訊。在「標頭」標籤的「回應標頭」區塊中尋找「Cache-Control」值:

Initial load performance for React developers: investigative deep dive

在此標頭內,可以以不同的組合組合多個指令,用逗號分隔。在我們的例子中,有兩個:

  • max-age 帶有一個數字 - 它控制此特定響應將存儲多長時間(以秒為單位)
  • must-revalidate - 它指示瀏覽器如果響應已過期,則始終向服務器發送新鮮版本的請求。如果響應在緩存中存在的時間超過 max-age 值,則響應將過期。

因此,基本上,此標頭告訴瀏覽器:

  • 可以將此響應存儲在您的緩存中,但過一段時間後要再次與我核實。
  • 順便說一句,您可以保留該緩存的時間正好是秒。祝你好運。

結果,瀏覽器總是與服務器核實,並且從不立即使用緩存。

但是,我們可以很容易地改變這一點 - 我們只需要將 max-age 數字更改為 0 到 31536000(一年,允許的最大秒數)之間即可。為此,在您的學習項目中,轉到 backend/index.ts 文件,找到設置 max-age=0 的位置,並將其更改為 31536000(一年)。刷新頁面幾次,您應該在“網絡”選項卡中看到 CSS 文件的以下內容:

Initial load performance for React developers: investigative deep dive

請注意,現在“狀態”列已變灰,對於“大小”,我們看到“(內存緩存)”。 CSS 文件現在從瀏覽器的緩存中提供服務,並且一年內將一直如此。刷新頁面幾次以查看它不會更改。

現在,對於處理緩存標頭的全部要點:讓我們再次測量頁面的性能。不要忘記設置“平均 3G”配置文件設置並保持“禁用緩存”設置未選中。

結果應該類似於:

Initial load performance for React developers: investigative deep dive

儘管延遲很高,“發送請求並等待”部分幾乎減少到零,“解析 HTML”和 JavaScript 評估之間的差距幾乎消失了,我們的 LCP 值又回到了 ~650 毫秒。

附加練習

  1. 將 max-age 值更改為 10(10 秒)
  2. 選中“禁用緩存”複選框並刷新頁面以刪除緩存。
  3. 取消選中復選框並再次刷新頁面 - 這次應該從內存緩存中提供服務。
  4. 等待 10 秒,然後再次刷新頁面。因為 max-age 只有 10 秒,所以瀏覽器將再次檢查資源,服務器將再次返回 304。
  5. 立即刷新頁面 - 它應該再次從內存中提供服務。

Cache-Control 和現代打包工具

上述信息是否意味著緩存是我們的性能靈丹妙藥,我們應該盡可能積極地緩存所有內容?絕對不是!除了其他一切之外,創建“不精通技術的客戶”和“需要通過電話解釋如何清除瀏覽器緩存”的組合的可能性將導致最資深的開發人員出現恐慌性發作。

有數百萬種優化緩存的方法,數百萬種在Cache-Control 標頭中的指令與其他可能或可能不會影響緩存持續時間的標頭的組合,這也可能或可能不取決於服務器的實現。可能僅關於此主題本身就可以編寫幾本書的信息。如果您想成為緩存大師,請從https://web.dev/和 MDN 資源上的文章開始,然後按照麵包屑進行操作。

不幸的是,沒有人能告訴你,“這是適用於所有內容的五種最佳緩存策略”。充其量,答案可能是:“如果您有這個用例,結合這個、這個和這個,那麼這個緩存設置組合是一個不錯的選擇,但要注意這些問題”。這一切都歸結於了解您的資源、構建系統、資源更改的頻率、緩存的安全性以及錯誤操作的後果。

但是,有一個例外。一種例外,即存在明確的“最佳實踐”:使用現代工具構建的網站的 JavaScript 和 CSS 文件。現代打包工具(如 Vite、Rollup、Webpack 等)可以創建“不可變”的 JS 和 CSS 文件。它們當然不是真正“不可變”的。但是這些工具使用依賴於文件內容的哈希字符串生成文件名稱。如果文件內容髮生更改,則哈希會更改,文件名稱也會更改。結果,當網站部署時,無論緩存設置如何,瀏覽器都將重新獲取文件的全新副本。緩存已“清除”,就像我們之前手動重命名 CSS 文件時一樣。

例如,查看學習項目中的 dist/assets 文件夾。 JS 和 CSS 文件都有 index-[hash] 文件名。記住這些名稱並運行 npm run build 幾次。名稱保持不變,因為這些文件的內容沒有改變。

現在轉到 src/App.tsx 文件並在某個地方添加類似 console.log('bla') 的內容。再次運行 npm run build 並檢查生成的文件。您應該看到 CSS 文件名保持不變,但 JS 文件名已更改。當此網站部署時,下次重複用戶訪問它時,瀏覽器將請求一個在其緩存中從未出現過的完全不同的 JS 文件。緩存已清除。

附加練習

查找項目的 dist 文件夾的等效項並運行您的構建命令。

  • 文件名是什麼樣的?類似於哈希,還是普通的 index.js、index.css 等?
  • 當您再次運行構建命令時,文件名是否會更改?
  • 如果您在代碼中的某個位置進行簡單的更改,有多少文件名會更改?

如果您的構建系統就是這樣配置的 - 您很幸運。您可以安全地配置服務器以設置生成資產的最大 max-age 標頭。如果您同樣對所有圖像進行版本控制 - 更好的是,您還可以將圖像包含到列表中。

根據網站及其用戶及其行為,這可能會為您免費提供初始加載的相當不錯的性能提升。

我簡單的用例真的需要了解所有這些嗎?

此時,您可能正在想類似這樣的事情,“你瘋了。我周末用Next.js 構建了一個簡單的網站,並在2 分鐘內將其部署到Vercel/Netlify/HottestNewProvider。當然,這些現代工具會為我處理所有這些。”這很公平。我也這麼認為。但後來我實際上檢查了一下,哇,我很驚訝?

我的兩個項目對 CSS 和 JS 文件都有 max-age=0 和 must-revalidate。事實證明,這是我的 CDN 提供商的默認設置??‍♀️。當然,他們有理由

以上是React 開發人員的初始負載效能:深入研究的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板