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.
mod_deflate
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
</IfModule>
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 update-compressed-content.sh ~/public_html '*.css'
bash update-compressed-content.sh ~/public_html '*.js'
update-compressed-content.sh:
#!/bin/bash
dir=$1
pattern=$2
test_run=$3
exec_line() {
cmd="$1"
do_not_run="$2"
echo "Executing $cmd";
if [ "X" == "X$do_not_run" ]
then
out= eval $1
echo "Result is $out"
fi
}
if [ -z "$dir" ] || [ -z "$pattern" ]
then
echo "Usage: $0 <directory> <pattern>"
exit 1
fi
echo "find \"$dir\" -name \"$pattern\""
find "$dir" -name "$pattern" | while read fileto
do
echo $fileto
if [ -e "${fileto}gz" ] && [ "${fileto}gz" -nt "$fileto" ]
then
echo "Compressed content for $fileto is up to date"
else
echo "Compressing $fileto"
exec_line "cat '$fileto' | gzip > '${fileto}gz'" $test_run
fi
done
No comments yet
This page was last modified on 2024-09-09 12:51:10