前端效能優化——採用高效的快取策略提供靜態資源

2023-03-14 21:01:41

前端效能優化——採用高效的快取策略提供靜態資源

一、發現效能問題

通過 Chrome 開發者工具的 Lighthouse 工具對目標站點的某個頁面進行分析,其生成的報告如圖所示:

由分析報告可知,該目標站點存在多項待優化的效能問題,如減少未使用的 JavaScript採用高效的快取策略提供靜態資源等問題,本文主要分析並解決採用高效的快取策略提供靜態資源問題。

二、分析效能問題

Lighthouse 會標記所有未被快取的靜態資源:

Lighthouse 認為一個資源是可快取的,當且僅當以下所有條件都滿足:

  • 該資源是字型、影象、媒體檔案、指令碼或樣式表。
  • 該資源具有 200、203 或 206 HTTP 狀態碼。
  • 該資源沒有顯式的 no-cache 策略。

當頁面未通過審計時,Lighthouse 會將結果列在一個具有三列的表格中:

列名 說明
網址 可快取資源的位置
快取 TTL 資源當前的快取持續時間
傳輸檔案大小 如果被標記的資源已經被快取,使用者可以節省多少資料的估算值

通過分析 Lighthouse 工具對目標站點生成的檢測報告,發現採用高效的快取策略提供靜態資源這一項中的快取 TTL 列,有一些靜態資原始檔的值為 None,也就是說該目標站點有部分靜態資源未被快取,那麼這部分資源在重複存取時,會重複向伺服器傳送請求,因此該情況將明顯影響目標站點效能。

三、解決效能問題

為了使靜態資源快取,需要在伺服器端設定 HTTP 響應檔頭。檔頭控制瀏覽器快取的行為。以下是一些有關快取的重要檔頭:

  • Cache-Control:用於控制資源的快取機制。通過設定值為 public 或 private 來指定資源是否可以被快取,並通過設定 max-age 指定資源應該被快取的時間長度。
  • Expires:允許指定一個過期時間,過期後,瀏覽器必須重新獲取資源。
  • ETag:允許伺服器標識資源,並使用 If-None-Match 請求頭進行快取驗證。
  • Last-Modified:允許伺服器指定資源最後修改的時間,並使用 If-Modified-Since 請求頭進行快取驗證。

請設定你的伺服器返回 Cache-Control HTTP 響應頭:

Cache-Control: max-age=31536000

max-age 引數告訴瀏覽器它應該將資源快取多長時間,單位為秒。以下範例將持續時間設定為 31536000,對應於 1 年:60 秒 × 60 分鐘 × 24 小時 × 365 天= 31536000 秒。

以在 Nginx 中設定 Cache-Control 響應頭為例:

http {
    server {
         location / {
            root /html;
            index index.html index.htm;

            # # 設定快取時間為 1 天
            # expires 1d;

            # 開啟快取,並設定一年的快取期
            add_header Cache-Control "public,max-age=31536000";
        }
    }
}

可以通過設定 expires 引數和 Cache-Control 的 max-age 來指定快取期。

add_header Cache-Control "public,max-age=31536000"; 開啟了快取,並指定了快取型別為 public,表示響應可以被使用者端和代理伺服器快取,max-age 指定了資源的快取期為 31536000 秒。

Nginx 伺服器端設定 Cache-Control 響應頭後,存取靜態資源的響應如圖所示:

需要注意的是,長時間的快取期存在一個問題:使用者可能看不到靜態檔案的更新。但是可以通過設定構建工具來解決該問題,在靜態資原始檔名中嵌入雜湊來避免這個問題,以便每個版本都是唯一的,從而促使瀏覽器從伺服器獲取新版本。(要了解如何使用 webpack 嵌入雜湊,請參閱 webpack 的快取指南。)

如果資源經常更新且實時性很重要,那麼可以將其快取設定為 no-cache,但瀏覽器仍會快取該資源,不過首先會與伺服器進行檢查,以確保資源仍然是最新的。

此外,並不是快取期越長越好。而是需要根據實際需求進行權衡,以決定資源的最佳快取期。

通過在 Nginx 開啟快取,並設定合適的快取期,目標站點的效能檢測報告如圖所示:

由上圖可知,效能評分並沒有改變,但在診斷結果下已沒有採用高效的快取策略提供靜態資源這一項,這一項已經被移入已通過的稽核,也就是該項通過在伺服器設定 Cache-Control 的方式得到了效能上的優化。