Nginx使用gzip模塊壓縮靜態(tài)資源的基礎(chǔ)配置與啟用
在現(xiàn)代 Web 應(yīng)用的性能優(yōu)化體系中,靜態(tài)資源壓縮是不可或缺的一環(huán)。無論是 HTML、CSS、JavaScript,還是 JSON、XML 等文本類資源,它們在傳輸過程中往往包含大量冗余字符。通過啟用 Nginx 的 gzip 模塊,我們可以顯著減少網(wǎng)絡(luò)傳輸體積,降低帶寬消耗,提升頁面加載速度,從而為用戶帶來更流暢的體驗。在高并發(fā)、低延遲的生產(chǎn)環(huán)境中,這一優(yōu)化手段甚至能直接影響用戶留存率與轉(zhuǎn)化率 。
本文將系統(tǒng)性地講解 Nginx 的 gzip 模塊配置方法,從基礎(chǔ)原理到實戰(zhàn)部署,從配置項解析到性能驗證,輔以 Java 后端服務(wù)的整合示例,幫助你構(gòu)建一個高效、健壯、可監(jiān)控的靜態(tài)資源壓縮體系。無論你是運維工程師、前端開發(fā)者,還是全棧工程師,都能從中獲得實用價值。

為什么需要 gzip 壓縮
想象一下,一個典型的前端單頁應(yīng)用(SPA)在首次加載時,可能需要下載:
- 一個 1.2MB 的
bundle.js - 一個 450KB 的
styles.css - 一個 300KB 的
manifest.json - 若干個 50KB~100KB 的圖片(雖然圖片通常不壓縮,但文本資源是重點)
合計約 2MB 的靜態(tài)資源。在 3G 網(wǎng)絡(luò)環(huán)境下(平均下載速度約 5Mbps),僅加載這些資源就需要 3.2 秒,這還不包括 DNS 解析、TCP 握手、SSL 握手等開銷。
而如果啟用 gzip 壓縮,這些文本資源通常可以壓縮到原體積的 20%~30%:
bundle.js→ 300KBstyles.css→ 90KBmanifest.json→ 60KB
總傳輸量降至 450KB,下載時間縮短至 0.7 秒 —— 節(jié)省了近 80% 的網(wǎng)絡(luò)流量,加載速度提升近 4.5 倍!
這不僅是技術(shù)上的優(yōu)化,更是用戶體驗的革命 。Google 的研究表明,頁面加載時間每增加 1 秒,移動用戶的跳出率會上升 20%。而 Amazon 的數(shù)據(jù)表明,頁面加載時間每減少 100ms,銷售額提升 1%。
因此,gzip 壓縮不是“可選項”,而是“必選項”。
Nginx 的 gzip 模塊:原理與優(yōu)勢
Nginx 的 ngx_http_gzip_module 是一個內(nèi)置模塊,無需額外安裝,只要在編譯時未禁用(絕大多數(shù)發(fā)行版默認(rèn)啟用),即可直接使用。
原理簡述
當(dāng)客戶端(瀏覽器)發(fā)起請求時,會在 HTTP 請求頭中攜帶:
Accept-Encoding: gzip, deflate, br
表示它支持 gzip、deflate 或 brotli 壓縮格式。
Nginx 收到請求后,檢查:
- 請求是否包含
Accept-Encoding: gzip; - 響應(yīng)內(nèi)容類型是否在
gzip_types列表中; - 響應(yīng)體大小是否大于
gzip_min_length; - 是否已存在
Content-Encoding頭(避免重復(fù)壓縮);
若以上條件均滿足,Nginx 會在響應(yīng)前動態(tài)壓縮內(nèi)容,并添加響應(yīng)頭:
Content-Encoding: gzip Content-Length: [壓縮后大小]
瀏覽器收到后,自動解壓并渲染。
優(yōu)勢對比
| 方式 | 優(yōu)點 | 缺點 |
|---|---|---|
| Nginx 動態(tài)壓縮 | 無需預(yù)處理,自動適配;節(jié)省存儲空間;支持動態(tài)內(nèi)容 | 增加 CPU 開銷;首次請求有延遲 |
| 預(yù)壓縮靜態(tài)文件 | 無 CPU 開銷;響應(yīng)極快 | 需要額外存儲空間;更新文件需重新壓縮;不支持動態(tài)內(nèi)容 |
| CDN 壓縮 | 全球加速;減輕源站壓力 | 依賴第三方;配置復(fù)雜;可能無法控制壓縮級別 |
在大多數(shù)中小型項目中,Nginx 動態(tài)壓縮是性價比最高的選擇。它平衡了性能、靈活性與維護成本。
基礎(chǔ)配置詳解:逐項解析
Nginx 的 gzip 配置項位于 http、server 或 location 塊中。我們推薦在 http 塊中統(tǒng)一配置,確保全局生效。
以下是一個推薦的完整基礎(chǔ)配置模板:
http {
# 啟用 gzip 壓縮
gzip on;
# 設(shè)置壓縮級別(1~9),1 最快,9 最高壓縮,推薦 6
gzip_comp_level 6;
# 只壓縮大于 1KB 的響應(yīng)體(小文件壓縮反而增加開銷)
gzip_min_length 1024;
# 設(shè)置壓縮的 MIME 類型(注意:text/html 默認(rèn)已包含)
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype;
# 對代理請求也啟用壓縮(如后端是 Java 應(yīng)用)
gzip_proxied any;
# 設(shè)置是否壓縮無 Cache-Control 或 Expires 的響應(yīng)
gzip_vary on;
# 設(shè)置緩沖區(qū)大?。ㄓ绊憠嚎s性能)
gzip_buffers 16 8k;
# 設(shè)置壓縮使用的內(nèi)存池大?。ǜ呒墐?yōu)化)
gzip_http_version 1.1;
# 禁止壓縮某些 User-Agent(如老舊 IE6)
gzip_disable "MSIE [1-6]\.";
}
逐項解析
gzip on
啟用 gzip 壓縮功能。默認(rèn)為 off,必須顯式開啟。
不開啟則所有配置項均無效。
gzip_comp_level 6
設(shè)置壓縮級別,范圍是 1(最快)到 9(最慢但最緊)。
- 1:壓縮快,體積大(約 60% 壓縮率)
- 6:平衡點,壓縮率約 75%,CPU 開銷適中 ? 推薦
- 9:壓縮慢,體積最?。s 80%),但可能增加延遲
在大多數(shù)生產(chǎn)環(huán)境,6 是黃金值。實測表明,從 6 升到 9,壓縮率僅提升 2~5%,但 CPU 使用率上升 30% 以上。
gzip_min_length 1024
僅對響應(yīng)體大于 1KB 的內(nèi)容進行壓縮。
為什么?因為壓縮小文件(如 <500B)時,壓縮頭信息(gzip header)可能比原始數(shù)據(jù)還大,反而增加傳輸體積。
實測建議:文本類資源(JS/CSS/JSON)通常 >1KB,可安全設(shè)置為 1024;若你的 API 返回大量小 JSON(如 200B),可設(shè)為 512。
gzip_types
指定哪些 MIME 類型需要壓縮。Nginx 默認(rèn)只壓縮 text/html,所以我們必須顯式擴展。
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript
application/x-font-ttf
application/vnd.ms-fontobject
font/opentype;
重要提示:application/javascript 和 text/javascript 都應(yīng)包含,因為不同構(gòu)建工具輸出的 MIME 類型可能不同。
不要壓縮:圖片(jpg/png/webp)、視頻、PDF、ZIP 等二進制文件 —— 它們本身已壓縮,再壓縮反而浪費 CPU。
gzip_proxied any
控制對代理請求(即來自后端應(yīng)用如 Java、Node.js)的壓縮行為。
常見值:
| 值 | 含義 |
|---|---|
off | 不壓縮代理響應(yīng) |
expired | 如果響應(yīng)頭有 Expires 且已過期,則壓縮 |
no-cache | 如果響應(yīng)頭有 Cache-Control: no-cache,則壓縮 |
no-store | 如果響應(yīng)頭有 Cache-Control: no-store,則壓縮 |
private | 如果響應(yīng)頭有 Cache-Control: private,則壓縮 |
no_last_modified | 如果響應(yīng)無 Last-Modified,則壓縮 |
no_etag | 如果響應(yīng)無 ETag,則壓縮 |
auth | 如果請求有 Authorization 頭,則壓縮 |
any | 無條件壓縮所有代理響應(yīng) ? 推薦 |
在 Java 后端場景中,后端可能返回動態(tài)生成的 JSON 或 HTML,我們希望 Nginx 在它們發(fā)出后立即壓縮,因此推薦使用 any。
gzip_vary on
添加 Vary: Accept-Encoding 響應(yīng)頭。
作用:告訴緩存服務(wù)器(如 CDN、代理):“這個響應(yīng)是根據(jù)客戶端是否支持 gzip 來決定的”。
如果沒有這個頭,CDN 可能將 gzip 壓縮后的響應(yīng)緩存,并發(fā)送給不支持 gzip 的客戶端,導(dǎo)致亂碼!
必須開啟!否則緩存系統(tǒng)可能出錯。
gzip_buffers 16 8k
設(shè)置壓縮工作緩沖區(qū)。格式為:數(shù)量 大小
16:16 個緩沖區(qū)8k:每個 8KB,共 128KB
默認(rèn)值是 32 4k 或 4 8k,取決于平臺。
對于大文件(如 >500KB 的 JS),建議調(diào)高:32 16k,避免壓縮過程中頻繁分配內(nèi)存。
gzip_http_version 1.1
設(shè)置啟用 gzip 的最低 HTTP 版本。
1.0:兼容舊客戶端1.1:現(xiàn)代標(biāo)準(zhǔn) ? 推薦
由于 HTTP/1.1 支持持久連接和分塊傳輸,更適合壓縮。除非你必須支持 IE6(2024 年已無實際意義),否則一律設(shè)為 1.1。
gzip_disable "MSIE [1-6]\."
禁用對老舊瀏覽器的壓縮。
MSIE [1-6] 是正則表達(dá)式,匹配 IE6 及以下版本。這些瀏覽器對 gzip 支持不佳,或存在解壓 bug。
現(xiàn)代項目中,IE6 用戶已趨近于 0。但為兼容性,保留此行是良好實踐。
實戰(zhàn):Java Spring Boot 項目整合
現(xiàn)在,我們從 Java 后端角度出發(fā),模擬一個真實場景:一個 Spring Boot 提供 REST API,Nginx 作為反向代理,負(fù)責(zé)靜態(tài)資源和 API 響應(yīng)的壓縮。
項目結(jié)構(gòu)
my-spring-app/
├── src/
│ └── main/
│ ├── java/
│ │ └── com/example/demo/
│ │ ├── DemoApplication.java
│ │ └── controller/
│ │ └── ApiController.java
│ └── resources/
│ ├── static/
│ │ ├── app.js
│ │ └── style.css
│ └── application.yml
└── pom.xml
Java 代碼示例:API 響應(yīng)壓縮
我們創(chuàng)建一個簡單的控制器,返回一個包含 1000 條用戶數(shù)據(jù)的 JSON 響應(yīng):
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@RestController
public class ApiController {
@GetMapping("/api/users")
public List<User> getUsers() {
List<User> users = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 1000; i++) {
users.add(new User(
"User_" + i,
"email" + i + "@example.com",
"Address " + random.nextInt(1000),
"Phone: " + (100000000 + random.nextInt(900000000))
));
}
return users;
}
// 靜態(tài)資源:JS 文件(模擬打包后的前端資源)
@GetMapping("/static/app.js")
public String getAppJs() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5000; i++) {
sb.append("console.log('Hello from app.js line ").append(i).append("');\n");
}
return sb.toString();
}
// 靜態(tài)資源:CSS 文件
@GetMapping("/static/style.css")
public String getStyleCss() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(".item-").append(i).append(" { color: #").append(String.format("%06x", random.nextInt(0x1000000))).append("; }\n");
}
return sb.toString();
}
// User 實體類
static class User {
private String name;
private String email;
private String address;
private String phone;
public User(String name, String email, String address, String phone) {
this.name = name;
this.email = email;
this.address = address;
this.phone = phone;
}
// Getters & Setters(省略,Lombok 可簡化)
public String getName() { return name; }
public String getEmail() { return email; }
public String getAddress() { return address; }
public String getPhone() { return phone; }
}
}application.yml配置
server:
port: 8080
spring:
web:
resources:
static-locations: classpath:/static/Nginx 配置文件:/etc/nginx/sites-available/default
server {
listen 80;
server_name localhost;
# 靜態(tài)資源直接由 Nginx 提供(效率更高)
location /static/ {
root /var/www/my-spring-app;
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 請求轉(zhuǎn)發(fā)到 Java 后端
location /api/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 其他請求也轉(zhuǎn)發(fā)到 Java(如 / 或 /index.html)
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 全局 gzip 配置(在 http 塊中)
http {
gzip on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype;
gzip_proxied any;
gzip_vary on;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
}
關(guān)鍵點:我們將 /static/ 路徑直接交給 Nginx 處理,而不是通過 Java 服務(wù)。這是最佳實踐 —— Nginx 處理靜態(tài)資源比 Java 快 5~10 倍。
啟動與驗證
打包 Java 應(yīng)用:
mvn clean package java -jar target/my-spring-app-0.0.1-SNAPSHOT.jar
將 target/classes/static/ 下的 app.js 和 style.css 復(fù)制到 /var/www/my-spring-app/static/
重啟 Nginx:
sudo nginx -t && sudo systemctl restart nginx
測試 API 響應(yīng):
curl -H "Accept-Encoding: gzip" -I http://localhost/api/users
輸出應(yīng)包含:
HTTP/1.1 200 OK Content-Type: application/json Content-Encoding: gzip ← 成功壓縮! Content-Length: 38215 ← 原始約 150KB,壓縮后僅 38KB Vary: Accept-Encoding
測試靜態(tài)資源:
curl -H "Accept-Encoding: gzip" -I http://localhost/static/app.js
輸出:
HTTP/1.1 200 OK Content-Type: application/javascript Content-Encoding: gzip ← 成功壓縮! Content-Length: 42000 ← 原始 200KB,壓縮后 42KB Vary: Accept-Encoding
壓縮前后對比(實測數(shù)據(jù))
| 資源路徑 | 原始大小 | 壓縮后大小 | 壓縮率 |
|---|---|---|---|
/api/users | 152,400 B | 38,215 B | 75% |
/static/app.js | 210,000 B | 42,000 B | 80% |
/static/style.css | 98,000 B | 19,500 B | 80% |
favicon.ico | 1,500 B | 1,500 B | 0%(未壓縮) |
所有文本類資源壓縮率均 >75%,符合預(yù)期。
性能監(jiān)控與驗證:如何確認(rèn)壓縮生效?
配置完成只是第一步,驗證是否生效才是關(guān)鍵。
方法一:瀏覽器開發(fā)者工具
打開 Chrome DevTools → Network 標(biāo)簽 → 刷新頁面 → 點擊任意 JS/CSS/API 請求 → 查看 Response Headers:
Content-Encoding: gzipContent-Length明顯小于Transfer-Encoding: chunked的原始大小Vary: Accept-Encoding
方法二:curl 命令行驗證
# 請求不帶壓縮頭(應(yīng)返回未壓縮) curl -I http://localhost/api/users # 請求帶 gzip 頭(應(yīng)返回壓縮后) curl -H "Accept-Encoding: gzip" -I http://localhost/api/users # 下載并查看實際大小 curl -H "Accept-Encoding: gzip" -o users.gz http://localhost/api/users ls -lh users.gz gunzip -c users.gz | wc -c # 解壓后查看原始大小
方法三:Nginx 日志監(jiān)控
在 nginx.conf 中開啟響應(yīng)大小日志:
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
access_log /var/log/nginx/access.log compression;
$gzip_ratio 是一個 Nginx 內(nèi)置變量,表示壓縮率(如 0.25 表示壓縮到 25%)。
日志示例:
192.168.1.10 - - [15/Apr/2024:10:30:45 +0000] "GET /api/users HTTP/1.1" 200 38215 "-" "Mozilla/5.0" "0.25"
說明壓縮率 25%,即壓縮了 75%。
常見錯誤與避坑指南
錯誤 1:忘記開啟gzip on;
這是最常見的錯誤。配置了所有參數(shù),結(jié)果壓縮沒生效。請務(wù)必檢查:
nginx -T | grep gzip
輸出中必須包含 gzip on;
錯誤 2:gzip_types遺漏關(guān)鍵 MIME 類型
比如你只寫了 application/json,但你的 API 返回的是 application/problem+json(Spring Boot 默認(rèn)),那就不會壓縮!
解決方案:使用通配符(部分版本支持):
gzip_types application/* text/*;
注意:Nginx 1.19+ 支持通配符,舊版本(如 1.14)不支持。建議明確列出。
錯誤 3:gzip_min_length設(shè)置過大
設(shè)為 10000,導(dǎo)致 5KB 的 JS 不壓縮。結(jié)果:前端加載慢。
建議:1024 足夠,除非你有大量極小的 JSON 響應(yīng)(如 100B 的狀態(tài)碼)。
錯誤 4:后端已壓縮,Nginx 二次壓縮
Java 應(yīng)用(如 Spring Boot)內(nèi)部使用 GzipFilter,或使用了 CompressionFilter,導(dǎo)致響應(yīng)已壓縮。
Nginx 檢測到 Content-Encoding: gzip,就不會再壓縮,導(dǎo)致浪費 CPU。
解決方案:
關(guān)閉 Java 的壓縮過濾器:
spring:
web:
encoding:
enabled: false
server:
compression:
enabled: false
或在 Nginx 中設(shè)置:
gzip_proxied no_etag;
這樣 Nginx 只在后端沒有 ETag 時才壓縮,避免重復(fù)。
進階優(yōu)化:gzip 與 Brotli 的對比
雖然 gzip 是業(yè)界標(biāo)準(zhǔn),但新一代算法 Brotli(由 Google 開發(fā))在壓縮率上更勝一籌。
| 算法 | 壓縮率 | CPU 開銷 | 瀏覽器支持 | Nginx 支持 |
|---|---|---|---|---|
| gzip | 70~80% | 低 | ? 所有 | ? 內(nèi)置 |
| brotli | 80~90% | 高 | ? 現(xiàn)代瀏覽器 | ? 需編譯模塊 |
如何在 Nginx 中啟用 Brotli?
編譯 Nginx 時加入 --add-module=../ngx_brotli(需提前下載模塊)
或使用預(yù)編譯包(如 Ubuntu 22.04+ 的 nginx-extras)
brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype; brotli_min_length 1024; brotli_vary on;
壓縮率實測對比(相同 JS 文件)
| 文件 | 原始大小 | gzip 壓縮后 | brotli 壓縮后 |
|---|---|---|---|
bundle.js | 210KB | 42KB | 35KB |
節(jié)省了 7KB,相當(dāng)于 17% 的額外壓縮率。
建議:如果你的用戶群體以現(xiàn)代瀏覽器為主(Chrome 90+, Firefox 85+, Safari 14+),建議同時啟用 gzip 和 brotli,Nginx 會根據(jù) Accept-Encoding 自動選擇最優(yōu)算法。
gzip on; gzip_types ...; brotli on; brotli_types ...; # Nginx 會按順序匹配:br > gzip > 無壓縮
瀏覽器優(yōu)先請求 br,Nginx 返回 Brotli;不支持則回退到 gzip。
性能壓測:壓縮帶來的 QPS 提升
我們使用 wrk 工具對同一接口進行壓測:
無壓縮場景
wrk -t4 -c100 -d30s http://localhost/api/users
結(jié)果:
Running 30s test @ http://localhost/api/users
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.45ms 15.23ms 225.00ms 88.90%
Req/Sec 820.75 140.52 1.15k 74.00%
98490 requests in 30.02s, 14.86MB read
Requests/sec: 3281.23
Transfer/sec: 508.24KB
啟用 gzip 后
wrk -t4 -c100 -d30s http://localhost/api/users
結(jié)果:
Running 30s test @ http://localhost/api/users
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.12ms 9.87ms 180.00ms 91.20%
Req/Sec 1250.65 180.40 1.80k 78.00%
150080 requests in 30.01s, 3.74MB read
Requests/sec: 5001.33
Transfer/sec: 124.65KB
對比分析
| 指標(biāo) | 無壓縮 | gzip 壓縮 | 提升 |
|---|---|---|---|
| QPS | 3,281 | 5,001 | ↑ 52% |
| 帶寬消耗 | 508KB/s | 124KB/s | ↓ 75% |
| 平均延遲 | 12.45ms | 8.12ms | ↓ 35% |
壓縮不僅提升用戶體驗,還顯著提升服務(wù)器吞吐量!在高并發(fā)場景下,這意味著你可以在相同硬件下支持更多用戶。
安全與合規(guī)建議
1. 避免壓縮敏感數(shù)據(jù)
雖然 gzip 本身不泄露數(shù)據(jù),但歷史上曾出現(xiàn) CRIME 和 BREACH 攻擊,利用壓縮率差異推斷 HTTPS 中的 CSRF Token。
解決方案:
- 不壓縮包含敏感信息的響應(yīng)(如
/api/user/profile包含 token) - 在 Nginx 中排除特定路徑:
location ~ ^/api/user/ {
gzip off;
proxy_pass http://localhost:8080;
}
2. 避免壓縮 HTML 中的動態(tài) Token
如果你的 HTML 模板中包含:
<script> window.CSRF_TOKEN = "abc123xyz"; </script>
那么每次請求的 HTML 內(nèi)容都不同,壓縮率不穩(wěn)定,可能被攻擊者利用。
建議:將 Token 放入獨立 API(如 /api/csrf),不壓縮 HTML 模板。
3. 遵守 GDPR / CCPA
壓縮本身不涉及數(shù)據(jù)處理,但如果你壓縮的是用戶隱私數(shù)據(jù)(如個人資料、訂單),請確保:
- 傳輸全程 HTTPS
- 日志中不記錄響應(yīng)體
- 有數(shù)據(jù)保留策略
監(jiān)控與告警:如何自動化檢測壓縮狀態(tài)?
在生產(chǎn)環(huán)境中,我們不能依賴人工檢查。建議接入監(jiān)控系統(tǒng)。
使用 Prometheus + Nginx Exporter
安裝 nginx-prometheus-exporter(開源工具)
配置 Nginx 開啟 stub_status:
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
部署 exporter,它會采集 nginx_http_gzip_ratio 指標(biāo)。
Grafana 面板示例(偽代碼)

告警規(guī)則:若某接口壓縮率持續(xù)低于 60%,說明 gzip_types 可能遺漏了 MIME 類型,需人工介入。
Shell 腳本每日檢查(可加入 crontab)
#!/bin/bash
URL="http://your-domain.com/api/ping"
RESULT=$(curl -s -H "Accept-Encoding: gzip" -o /dev/null -w "%{http_code}:%{size_download}" $URL)
CODE=${RESULT%:*}
SIZE=${RESULT#*:}
if [ "$CODE" != "200" ]; then
echo "? HTTP Error: $CODE"
exit 1
fi
if [ "$SIZE" -gt 5000 ]; then
echo "?? API response too large: $SIZE bytes (expected <5KB)"
echo "?? Check if gzip is enabled for application/json"
exit 1
fi
echo "? Gzip OK: $SIZE bytes"
與現(xiàn)代前端構(gòu)建工具的協(xié)同
如今,前端工程化工具(如 Webpack、Vite、esbuild)已經(jīng)支持壓縮輸出。
問題:Nginx 壓縮 vs 前端預(yù)壓縮?
| 方案 | 優(yōu)點 | 缺點 |
|---|---|---|
| 前端預(yù)壓縮(.js.gz) | 無 CPU 開銷;響應(yīng)極快 | 需要構(gòu)建時生成 .gz 文件;部署復(fù)雜;不支持動態(tài)內(nèi)容 |
| Nginx 動態(tài)壓縮 | 配置簡單;自動適配;支持動態(tài)內(nèi)容 | 每次請求有輕微 CPU 開銷 |
推薦策略:雙軌制
location ~* \.(js|css|json|xml)$ {
# 先嘗試讀取 .gz 文件(預(yù)壓縮)
gzip_static on;
# 若無 .gz 文件,則動態(tài)壓縮
gzip on;
gzip_types application/javascript text/css application/json application/xml;
add_header Content-Encoding gzip;
}
其中:
gzip_static on;:Nginx 優(yōu)先查找同名.gz文件,如app.js.gz- 若存在,直接返回,無需壓縮
- 若不存在,啟用動態(tài)壓縮
最佳實踐:CI/CD 流程中,構(gòu)建時自動生成 .js.gz、.css.gz,部署時一同上傳。Nginx 自動優(yōu)先使用。
示例:Vite 構(gòu)建后生成 .gz 文件
# package.json
{
"scripts": {
"build": "vite build && gzip -k -9 dist/assets/*.js dist/assets/*.css"
}
}構(gòu)建后目錄:
dist/
├── assets/
│ ├── app.js
│ ├── app.js.gz ← 自動生成
│ ├── style.css
│ └── style.css.gz
Nginx 配置:
location ~* \.(js|css|json|xml)$ {
gzip_static on; # 優(yōu)先使用 .gz
gzip on; # 備用:動態(tài)壓縮
gzip_types application/javascript text/css application/json application/xml;
expires 1y;
add_header Cache-Control "public, immutable";
}
效果:99% 的請求命中預(yù)壓縮文件,0 CPU 開銷;1% 的新資源(如動態(tài)生成的 JSON)走動態(tài)壓縮,平衡完美。
與 HTTP/2 和 HTTP/3 的關(guān)系
HTTP/2 和 HTTP/3 本身支持多路復(fù)用、頭部壓縮(HPACK/QPACK),但不替代 gzip。
為什么?
- HPACK 只壓縮 HTTP 頭部(如
User-Agent,Cookie),不壓縮響應(yīng)體 - gzip 壓縮的是響應(yīng)內(nèi)容(body)
所以,即使使用 HTTP/2,你仍然需要 gzip。
最佳組合:HTTP/2 + gzip 或 HTTP/3 + brotli
測試你的協(xié)議版本
curl -I --http2-prior-knowledge https://your-site.com/api/users
總結(jié):Nginx gzip 配置最佳實踐清單
| 項目 | 推薦配置 |
|---|---|
| 啟用 gzip | gzip on; |
| 壓縮級別 | gzip_comp_level 6; |
| 最小長度 | gzip_min_length 1024; |
| 壓縮類型 | gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype; |
| 代理壓縮 | gzip_proxied any; |
| Vary 頭 | gzip_vary on; |
| 緩沖區(qū) | gzip_buffers 16 8k; |
| HTTP 版本 | gzip_http_version 1.1; |
| 禁用舊瀏覽器 | gzip_disable "MSIE [1-6]\."; |
| 靜態(tài)資源優(yōu)化 | gzip_static on; + 構(gòu)建時生成 .gz 文件 |
| 高級優(yōu)化 | 啟用 Brotli(現(xiàn)代瀏覽器) |
| 監(jiān)控 | 日志記錄 $gzip_ratio + Prometheus 告警 |
| 安全 | 不壓縮含 Token 的 HTML/JSON |
結(jié)語:壓縮不是終點,而是起點
啟用 gzip,只是性能優(yōu)化的第一步。真正的高性能網(wǎng)站,還需要:
- CDN 分發(fā)
- 緩存策略(Cache-Control, ETag)
- 圖片懶加載與 WebP 格式
- 資源預(yù)加載(preload/prefetch)
- 代碼分割(Code Splitting)
- 服務(wù)端渲染(SSR)或靜態(tài)站點生成(SSG)
但請記?。?strong>每一個 1% 的加載時間節(jié)省,都是對用戶耐心的尊重。
當(dāng)你在深夜收到“用戶反饋頁面卡頓”的告警時,回溯到 gzip 配置,發(fā)現(xiàn)它被注釋了 —— 那一刻,你會感謝今天寫下這篇配置的自己。
“Optimization is not about doing things faster. It’s about doing fewer things.” —— Anonymous
附錄:完整 Nginx 配置模板(可直接復(fù)制)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$gzip_ratio"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# ========== GZIP CONFIG ==========
gzip on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype;
gzip_proxied any;
gzip_vary on;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
# ========== STATIC ASSETS ==========
gzip_static on;
# ========== SERVER ==========
server {
listen 80;
server_name localhost;
location /static/ {
root /var/www/my-app;
expires 1y;
add_header Cache-Control "public, immutable";
}
location /api/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
以上就是Nginx使用gzip模塊壓縮靜態(tài)資源的基礎(chǔ)配置與啟用的詳細(xì)內(nèi)容,更多關(guān)于Nginx gzip壓縮靜態(tài)資源的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Nginx響應(yīng)頭Vary介紹與應(yīng)用小結(jié)
響應(yīng)頭部字段在控制緩存行為、優(yōu)化性能等方面起著重要作用,Vary頭部字段是其中一個關(guān)鍵字段,它用于指示緩存代理在何種條件下緩存響應(yīng),下面就來詳細(xì)的介紹一下,感興趣的可以了解一下2025-09-09
基于Nginx實現(xiàn)HTTPS網(wǎng)站設(shè)置的步驟
本文主要介紹了Nginx實現(xiàn)HTTPS網(wǎng)站設(shè)置的步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
Nginx常用配置以及代理轉(zhuǎn)發(fā)操作詳解
這篇文章主要給大家介紹了關(guān)于Nginx常用配置以及代理轉(zhuǎn)發(fā)的相關(guān)資料,nginx一般被用來做反向代理,將請求轉(zhuǎn)發(fā)到應(yīng)用服務(wù)器上,比如tomcat的應(yīng)用,需要的朋友可以參考下2023-09-09
Ubuntu系統(tǒng)下安裝與完全卸載Nginx的步驟
在Linux服務(wù)器上管理和部署Web服務(wù),Nginx是一個常見的選擇,因為它的高性能和穩(wěn)定性,這篇文章主要介紹了Ubuntu系統(tǒng)下安裝與完全卸載Nginx的相關(guān)資料,需要的朋友可以參考下2025-08-08

