Here is how I'm using Apache to compress my site content. Pretty simple but you do have to watch out for missing Content-Length
headers, and incorrect handling of Accept-Encoding
requests due to Vary
header.
Deflate (stylized as DEFLATE) is a lossless data compression that uses a combination of LZ77 and Huffman coding. It was designed by Phil Katz, for version 2 of his PKZIP archiving tool. Deflate was later specified in RFC 1951 (1996).
Mainly using the AddOutputFilterByType directive with mod_deflate.
AddEncoding gzip svgz gz tgz AddCharset utf-8 .js .css SetEnvIfNoCase Request_URI \.(?i:gz|gif|jpe?g|png|webp|wav|mp3|flv|swf|ogg|ico|bmp|avi|mpg|pdf|woff2)$ no-gzip dont-vary AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript AddOutputFilterByType DEFLATE text/css text/html text/plain AddOutputFilterByType DEFLATE text/xml application/xml application/atom+xml application/rss+xml application/json text/x-component application/xhtml+xml AddOutputFilterByType DEFLATE application/vnd.ms-fontobject application/x-font-ttf font/opentype font/ttf image/svg+xml image/x-icon SetOutputFilter DEFLATE Header edit Vary ^Accept-Encoding$ "Accept-Encoding,Cookie" env=!dont-vary
Since mod_deflate re-compresses content each time a request is made, you can pre-compress the files and then have mod_deflate (or just serve normally using mod_headers) send those instead of having to recompress. This may be accomplished using a configuration like the following:
AddEncoding gzip .gz SetEnvIfNoCase Request_URI \.gz$ no-gzip AddType text/css .css.gz AddType text/javascript .js.gz Header set Vary "Accept-Encoding" ForceType text/javascript Header set Vary "Accept-Encoding" ForceType text/css
# Serve gzip compressed CSS and JS files if they exist and the client accepts gzip. RewriteCond "%{HTTP:Accept-encoding}" "gzip" RewriteCond "%{REQUEST_FILENAME}\.gz" -s RewriteRule "^(.*)\.(css|js)" "$1\.$2\.gz" [QSA] # Serve correct content types, and prevent mod_deflate double gzip. RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1] RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1] # Serve correct encoding type. Header append Content-Encoding gzip # Force proxies to cache gzipped & non-gzipped css/js files separately. Header append Vary Accept-Encoding env=!dont-vary
Here is how the Google PageSpeed module uses filters:
There are a couple environment variables you can set with SetEnv or RewriteRule that control a couple aspects of compression.
The mod_deflate module sends a Vary: Accept-Encoding
HTTP response header to alert proxies that a cached response should be sent only to clients that send the appropriate Accept-Encoding
request header. This prevents compressed content from being sent to a client that will not understand it.
If you use some special exclusions dependent on, for example, the User-Agent
header, you must manually configure an addition to the Vary
header to alert proxies of the additional restrictions. For example, in a typical configuration where the addition of the DEFLATE
filter depends on the User-Agent, you should add:
Header append Vary User-Agent
If your decision about compression depends on other information than request headers (e.g. HTTP version), you have to set the Vary header to the value *. This prevents compliant proxies from caching entirely.
Header set Vary *
Header always
for cgi You'll need to change the Header directives to use the always
in order to have them show up in some cases. For example if you are using mod_proxy_fcgi with php-fpm, or some other cgi.
Header always append Cache-Control "no-transform" env=!no-gzip
200 OK
)