Gzip压缩是Web优化里性价比很高的一环,文本类资源经过压缩,体积通常能降到原来的三成甚至更低。不过压缩并不是万能药,对于本身就高度压缩的内容,比如JPEG、PNG、GIF这类图片格式,再压一遍几乎没有收益,反而会增加服务器的CPU开销,甚至可能因为双重处理导致响应变慢。所以正确的做法是开启压缩的同时,明确排除掉这些已压缩类型,本文就来详细讲讲Apache下的具体做法。

哪些文件类型适合压缩,哪些必须排除
判断一个文件是否值得压缩,核心依据是压缩后体积能减少多少。纯文本类文件冗余度高,压缩收益显著。比如常见的HTML页面,压缩率一般在60%到80%之间;CSS和JavaScript文件去掉空白与重复字符后,也能减少70%左右的体积;JSON、XML接口返回的数据同样如此,尤其是字段名大量重复的场景。对于这类文件,开启压缩几乎是零成本的选择。
而图片的情况完全不同。JPEG格式在编码阶段就使用了有损压缩,PNG采用Deflate算法存储像素数据,GIF使用LZW压缩,WebP和AVIF更是为Web传输专门设计的压缩格式。这些文件的字节流里已经几乎没有可压缩的冗余空间,强行再过一遍Gzip,往往只能减少1%到3%的体积,得不偿失。
除了图片,还有一些二进制格式同样不建议压缩,例如zip、rar、7z等归档文件,mp4、mp3、flv等音视频文件,以及exe、dll这类可执行文件。综合来看,值得压缩的白名单大致是:text/html、text/css、text/javascript、application/javascript、application/json、application/xml、text/plain、image/svg+xml等。注意SVG虽然属于image类型,但本质是XML文本,压缩效果很好,是需要保留压缩的例外。
Apache下基于mod_deflate的配置方法
Apache 2.x之后推荐使用mod_deflate模块,它取代了早期Apache 1.3时代的mod_gzip。首先确认模块已加载,在httpd.conf中去掉下面这行前的注释符号:
LoadModule deflate_module modules/mod_deflate.so
接下来是压缩规则本身。mod_deflate提供了两种思路:一种是黑名单模式,压缩所有输出但排除部分类型;另一种是白名单模式,只压缩指定类型。对于排除image的需求,两种写法都可以实现,下面分别给出示例。
黑名单写法,压缩所有内容但跳过图片和视频:
<IfModule mod_deflate.c>
# 对所有输出启用压缩
SetOutputFilter DEFLATE
# 排除已压缩的图片类型,避免无效压缩
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico|webp|avif|bmp)$ no-gzip dont-vary
# 排除常见压缩归档和音视频格式
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|rar|7z|mp4|mp3|flv|swf)$ no-gzip dont-vary
</IfModule>白名单写法,只压缩文本类资源,天然把图片排除在外,这种方式更简洁也更安全,是当前比较主流的推荐做法:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript
AddOutputFilterByType DEFLATE application/json application/xml text/xml
AddOutputFilterByType DEFLATE image/svg+xml application/rss+xml
# 部分旧版浏览器不支持压缩,跳过处理
BrowserMatch \bMSIE [1-6]\. no-gzip dont-vary
BrowserMatch \bMSIE [1-6]\.no-gzip dont-vary
</IfModule>这里需要解释两个关键点。第一,SetEnvIfNoCase通过正则匹配请求的URI后缀,匹配成功后设置no-gzip环境变量,mod_deflate检测到该变量就会跳过压缩。第二,dont-vary的作用是告知代理服务器,对于设置了no-gzip的响应不要再依据Accept-Encoding头生成多份缓存副本,避免缓存膨胀。
如果使用的是虚拟主机或者没有权限修改主配置文件,也可以把同样的规则放到网站根目录的.htaccess中,前提是AllowOverride设置允许覆盖配置。htaccess中不需要<IfModule>包裹也可以,但保留它能在模块未加载时避免500错误,建议保留。
mod_deflate与mod_gzip的区别以及参数调优
很多老教程还在讲mod_gzip,这里有必要厘清一下。mod_gzip是Apache 1.3时代的第三方模块,压缩时先把输出写到临时文件再发送,存在磁盘IO开销;mod_deflate是Apache 2.x内置模块,直接在内存中完成压缩流水线处理,效率明显更高。除非维护非常古老的系统,新环境一律应该用mod_deflate。
关于压缩级别,DeflateCompressionLevel指令接受1到9的值,默认是9。级别越高压缩得越小,但CPU消耗越大。实际测试中,级别6和级别9的压缩体积差距通常不到2%,而CPU占用差距明显,因此对高并发站点,建议设置为6这个平衡点:
DeflateCompressionLevel 6
# 记录压缩日志,便于观察实际效果
DeflateFilterNote Input instream
DeflateFilterNote Output outstream
DeflateFilterNote Ratio ratio
LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
CustomLog logs/deflate_log deflate日志里的ratio值能直观反映压缩效果,如果发现某些类型的ratio接近100%,说明压缩几乎没有效果,这类文件就应该加入排除名单。这种基于实际数据调整策略的方式,比凭感觉拍脑袋配置靠谱得多。
如何验证压缩配置生效且排除规则正确
配置完成后,重启Apache使规则生效,然后需要验证两件事:文本资源确实被压缩了,图片资源确实没有被压缩。最方便的工具是curl,观察响应头中的Content-Encoding字段即可。
# 检查HTML是否压缩,期望输出 Content-Encoding: gzip curl -I -H "Accept-Encoding: gzip,deflate" "https://www.ipipp.com/index.html" # 检查图片是否被排除,期望不出现 Content-Encoding 头 curl -I -H "Accept-Encoding: gzip,deflate" "https://www.ipipp.com/logo.png"
如果HTML的响应头里出现了Content-Encoding: gzip,说明压缩生效;如果图片的响应头里没有这个字段,说明排除规则配置成功。反过来,如果发现图片也被压缩了,多半是正则表达式书写有误,比如忘记转义点号,或者把SetEnvIfNoCase写成了区分大小写的SetEnvIf,导致大写后缀如.JPG没被匹配到。
另外提醒一点,如果服务器前端还有Nginx反代或CDN层,要注意压缩职责的划分。通常建议只在最外层做压缩,避免多层重复压缩带来的CPU浪费。CDN场景下,源站输出未压缩内容、由CDN边缘节点压缩,也是一种常见架构。搞清楚整条链路里谁负责压缩,才能真正做到既省流量又不浪费计算资源。
Apache压缩Gzip配置mod_deflate修改时间:2026-09-03 23:57:03