Serving pre-compressed js and css when mod_deflate is not available or not desirable.

Serving compressed static contents like javascript and CSS files has become a must-have for every modern website. It helps mitigating the growing size of client side scripts in the modern Web 2.0 pages. By compressing those resources you get a number of benefits - faster page load time, less traffic consumption and hosting price.


Apache httpd provides convenient and easy to use mod_deflate. This module performs on-the-fly compression on selected resources. The setup is fairly easy - you just add a few line to your htaccess file:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE application/javascript text/css

The catch here is that this causes compressing the resources on ERVERY request. This causes significant CPU consumption on the busy websites and is the primary reason this module is not enabled on shared hostings.

The workaround

Not having mod_deflate does not mean that you can't serve compressed resources. Here's the idea: what if you compress all css and js files and than just serve the compressed contents. First let's assume that you have a compressed copy for the files - script.js has compressed script.jsgz and style.css has its style.cssgz. With the following rewrite rules you serve the compressed content to all clients that accept it. Also remember to tune the content type, because the server doesn't know about the content type of .cssgz and .jsgz files.

RewriteEngine on

RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule (.*)\.css$ $1\.cssgz [L]

AddType "text/css;charset=UTF-8" .cssgz
AddEncoding gzip .cssgz

RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule (.*)\.js$ $1\.jsgz [L]

AddType "text/javascript;charset=UTF-8" .jsgz
AddEncoding gzip .jsgz

Automating creation of compressed versions

To automate creation of compressed versions use the following script. Just set it to run every hour or so in the crontab:

bash ~/public_html '*.css'
bash ~/public_html '*.js'



exec_line() {
    echo "Executing $cmd";
    if [ "X" == "X$do_not_run" ]
        out= eval $1
        echo "Result is $out"

if [ -z "$dir" ] || [ -z "$pattern" ]
    echo "Usage: $0 <directory> <pattern>"
    exit 1

echo "find \"$dir\" -name \"$pattern\""
find "$dir" -name "$pattern" | while read fileto
    echo $fileto
    if [ -e "${fileto}gz" ] && [ "${fileto}gz" -nt "$fileto" ]
        echo "Compressed content for $fileto is up to date"
        echo "Compressing $fileto"
        exec_line "cat '$fileto' | gzip > '${fileto}gz'" $test_run



No comments yet

Back to articles list

This page was last modified on 2017-02-22 07:07:04