HTTP 中的壓縮
壓縮是提高網站效能的重要方法。對於某些文件,大小減少高達 70% 可以降低頻寬容量需求。多年來,演算法也變得更高效,並且客戶端和伺服器都支援新的演算法。
在實踐中,Web 開發者不需要實現壓縮機制,瀏覽器和伺服器都已實現,但他們必須確保伺服器配置得當。壓縮發生在三個不同的層面:
- 首先,一些檔案格式使用特定的最佳化方法進行壓縮;
- 然後,可以在 HTTP 級別進行通用壓縮(資源從頭到尾進行壓縮傳輸);
- 最後,可以在連線級別,即 HTTP 連線的兩個節點之間定義壓縮。
檔案格式壓縮
每種資料型別都存在一些冗餘,即浪費的空間。如果文字通常可以有高達 60% 的冗餘,那麼對於音訊和影片等其他媒體型別,這個比例可能會更高。與文字不同,這些其他媒體型別使用大量空間來儲存資料,因此最佳化儲存和回收空間的需求很早就顯現出來。工程師們設計了用於專門為此目的而設計的檔案格式的最佳化壓縮演算法。用於檔案的壓縮演算法可以分為兩大類:
- 無失真壓縮,其中壓縮-解壓縮迴圈不會改變恢復的資料。它與原始資料(位元組到位元組)匹配。對於影像,
gif或png使用無失真壓縮。 - 有失真壓縮,其中迴圈以(希望)使用者無法察覺的方式改變原始資料。Web 上的影片格式是有損的;
jpeg影像格式也是有損的。
某些格式可以用於無損或有失真壓縮,例如 webp,並且通常有損演算法可以配置為或多或少地壓縮,這當然會導致或多或少的質量。為了獲得更好的網站效能,理想的做法是儘可能多地壓縮,同時保持可接受的質量水平。對於影像,工具生成的影像可能未針對 Web 充分最佳化;建議使用能夠以所需質量儘可能多地壓縮的工具。有許多專門的工具。
有失真壓縮演算法通常比無失真壓縮演算法更高效。
注意:由於壓縮對特定型別的檔案效果更好,因此通常不需要再次壓縮它們。事實上,這往往適得其反,因為開銷成本(演算法通常需要一個會增加初始大小的字典)可能高於壓縮的額外增益,從而導致檔案更大。請勿對已壓縮格式的檔案使用以下兩種技術。
端到端壓縮
對於壓縮,端到端壓縮是網站效能最大提升所在。端到端壓縮是指伺服器對訊息正文進行的壓縮,並且將保持不變直到到達客戶端。無論中間節點是什麼,它們都不會觸及正文。
所有現代瀏覽器和伺服器都支援它,唯一需要協商的是要使用的壓縮演算法。這些演算法針對文字進行了最佳化。在 1990 年代,壓縮技術快速發展,並且在可選演算法集中添加了許多連續的演算法。如今,只有兩種相關:gzip,最常見的一種,以及新挑戰者 br。
為了選擇要使用的演算法,瀏覽器和伺服器使用主動內容協商。瀏覽器傳送一個帶有它支援的演算法及其優先順序順序的Accept-Encoding頭,伺服器選擇一個,用它來壓縮響應的正文,並使用Content-Encoding頭告訴瀏覽器它選擇的演算法。由於內容協商已用於根據其編碼選擇表示形式,伺服器必須在響應中傳送一個至少包含Accept-Encoding的Vary頭;這樣,快取將能夠快取資源的不同表示形式。
由於壓縮帶來顯著的效能提升,建議對所有檔案啟用壓縮,除了已經壓縮的檔案,如影像、音訊檔案和影片。
Apache 支援壓縮並使用mod_deflate;對於 Nginx,有ngx_http_gzip_module;對於 IIS,有<httpCompression>元素。
壓縮字典傳輸
現代壓縮格式,如Brotli 壓縮和Zstandard 壓縮,可以使用常用資料字典來進一步提高壓縮率,而不僅僅是從正在壓縮的檔案內部引用這些資料。通常,對於 HTTP 響應,這會使用該格式中包含的預定義靜態字典(例如,Brotli 靜態字典可在原始碼中找到)。
壓縮字典傳輸使開發者能夠指定一個資源,該資源可以用作未來請求的字典。這既可以是特定的字典檔案,也可以是現有資源(例如,在下載 app.v2.js 時使用 app.v1.js 作為字典)。這通常會改善壓縮效果,從而縮短載入時間。在 app.vX.js 示例中,大部分下載將僅包含兩個版本之間的增量,並且通用位元組可以從已下載的原始 app.v1.js 檔案中引用。
逐跳壓縮
逐跳壓縮,儘管與端到端壓縮相似,但有一個根本區別:壓縮不是在伺服器上的資源上發生,從而建立並傳輸特定表示形式,而是在客戶端和伺服器之間路徑上任意兩個節點之間的訊息體上發生。連續中間節點之間的連線可以應用不同的壓縮。
為此,HTTP 使用類似於端到端壓縮的內容協商機制:傳送請求的節點透過 TE 標頭來表明其意圖,另一個節點選擇適當的方法,應用它,並使用 Transfer-Encoding 標頭來指示其選擇。
實際上,逐跳壓縮對於伺服器和客戶端是透明的,並且很少使用。TE 和 Transfer-Encoding 主要用於分塊傳送響應,允許在不知道資源長度的情況下開始傳輸資源。
請注意,在跳級別使用 Transfer-Encoding 和壓縮非常罕見,以至於大多數伺服器(如 Apache、Nginx 或 IIS)都沒有簡單的方法來配置它。此類配置通常發生在代理級別。