How to compress css & javascript: An alternative to mod_deflate or mod_gzip

So, you have used Website Optimization Analyzer or you installed Yslow for Firefox or you discovered somewhere else that compressing your files (html, javascript & css) is a good thing to do. Unfortunately, it’s not always as easy as it looks to do this.

In Apache web hosting environments, there is a module called mod_deflate (for 2.x versions) or mod_gzip (for 1.3) versions. This is generally the easiest way to get content compressed. As in my last post about Magento, you should normally be able to enable this safely with the following lines inside your .htaccess file in your www root of your website:



# Insert filter
SetOutputFilter DEFLATE
# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
# MSIE masquerades as Netscape, but it is fine
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Don't compress images
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary

Then visit your website and in your browser right-click on the web page and choose “View Source”. In the source code, try and find a line that contains your stylesheet, then we go to whatsmyip compression checker and we enter the whole URL to your stylesheet there. To test, enter my css url.

http://www.opensourcetutor.com/wp-content/themes/hemingwayEx/style.css

You should see a big green tick and the site will say the CSS is compressed. Now, if you don’t, you either haven’t applied my above .htaccess settings yet or mod_deflate is not enabled on your server for you to access.

Alternative #1 – requires Apache mod_rewrite

This method is probably the best method I have seen to overcome the mod_deflate issue and we are only concerned about javascript and css files for now. PHP has an easy method to compress php files on the fly. What we need to do is gzip all our javascript & css files.

If you have shell access, you can run this command to take of the job for you. It will find each and every javascript file and css file and create a gzip copy.

find . -regex ".*\(css\|js\)$" -exec bash -c 'echo Compressing "{}" && gzip -c --best "{}" > "{}.gz"' \;

The line above searches the current directory and any subdirectories for files with extensions .js or .css, then prints out that it is being compressed, then compresses with the highest compression in that directory leaving the original file as is.

Now, we need to tell our browser to access the gzip version *IF* it supports gzip encoding. To do this, we use the following in our .htaccess file. Make sure you have removed the above code if it wasn’t successful.



  AddType "text/javascript" .gz
  AddEncoding gzip .gz


  AddType "text/css" .gz
  AddEncoding gzip .gz

RewriteEngine on
#Check to see if browser can accept gzip files.
ReWriteCond %{HTTP:accept-encoding} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
#make sure there's no trailing .gz on the url
ReWriteCond %{REQUEST_FILENAME} !^.+\.gz$
#check to see if a .gz version of the file exists.
RewriteCond %{REQUEST_FILENAME}.gz -f
#All conditions met so add .gz to URL filename (invisibly)
RewriteRule ^(.+) $1.gz [QSA,L] 

The advantage of this Alternative is that our server doesn’t have to gzip / compress the javascript and css each time it is called. This eases the load up on the server as we already do the compression one time and then just call the compressed version from then after. The other advantage is that we don’t need to load up mod_deflate each time. This could be advantages if you are running a VPS with very low memory available.

If you have a static website, you could apply the same technique for all your html files. To do so, you would instead use this line:

find . -regex ".*\(html\|css\|js\)$" -exec bash -c 'echo Compressing "{}" && gzip -c --best "{}" > "{}.gz"' \;

and then add this into your .htaccess also



  AddType "text/html" .gz
  AddEncoding gzip .gz


Technorati Tags: , , , , , ,

Published by salubrium

I am a Systems Administrator based in Sydney, Australia with some hugely varied interests: Topics covered are Virtualization, Web Hosting, Remote Desktop, Security and Backups, PHP, Python, MVC Frameworks, SEO

Join the Conversation

15 Comments

  1. When I first implemented this, Safari didn’t unpack .gz files automatically like other browsers. I am not sure if this is still true. I don’t have or run Safari now so, it’s not easy to test.

  2. I found comments on another blog confirming that several modern browsers don’t support .gz file decompression: Safari, Konqueror and Google Chrome 2.0. With the alternate solution, those users won’t get the benefits of compression.

    Another issue is automating this in your deployment cycle (also mentioned in the post above): I’m often tweaking css on my live sites; using this approach I won’t be seeing any changes until I manually gzip the changed file. Is there any way to automate this?

  3. hello, I am using a simple godaddy economic plan.

    and yes, I have no access to my apache server. and shell :(

    will this still work?

    hope you can guide me on how to implement these one.

    hope you reply SAP

    I am planning to gzip jquery.js and jdgallery.js coz they are 100kb in size

  4. Download copies of your jquery.js and jdgallery.js. Use a utility called 7zip (if you are on windows) to gzip these files and give them a gz extension. Then upload them to the same directory where your original js files live. Add the details to your .htaccess file and test using the http://www.whatsmyip.org/ compression tool or Yslow extension in Firefox.

  5. i’m using this code so if the gzip version of the file dosen’t exist apache does it on the fly.
    ———————————–

    AddType “text/html” .gz
    AddEncoding gzip .gz

    AddType “text/javascript” .gz
    AddEncoding gzip .gz

    AddType “text/css” .gz
    AddEncoding gzip .gz

    RewriteEngine on
    ReWriteCond %{HTTP:accept-encoding} gzip
    RewriteCond %{HTTP_USER_AGENT} !Safari
    ReWriteCond %{REQUEST_FILENAME} !^.+\.gz$
    RewriteCond %{REQUEST_FILENAME}.gz -f
    RewriteRule ^(.+) $1.gz [QSA,L]

    AddOutputFilterByType DEFLATE text/html
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    —————————–

    how can i exclude these:
    Netscape 4.06-4.08
    IE6
    chrome 2.0

    like safari?
    RewriteCond %{HTTP_USER_AGENT} !Safari

  6. I haven’t tested it but something like this should ignore the browsers in question.


    RewriteCond %{HTTP_USER_AGENT} !^.*MSIE\ 6.0
    RewriteCond %{HTTP_USER_AGENT} !^.*Chrome.*
    RewriteCond %{HTTP_USER_AGENT} !^.*Mozilla/4\.0[678].*

  7. I tried to use the above technique and it works perfectly well, but one major problem for my pages. I am using SSIs on each page. When I make .gz file and uplaod it, then the server does not load the SSI. Please suggest me how to include SSI in .gz files.

  8. Helllo Techies,

    How to conditionally disable the mod_deflate based on the query string (EX: has_gender=) and how to check whether it works or not ?

  9. Check out the mod_rewrite Cheat Sheet here

    You will probably use something like (I haven’t tested and my regex’s aren’t that good, so you have to check it out)

    RewriteCond %{REQUEST_URI}% !(^*.has_gender=.*)$

    How to check? Trial and error.. maybe put a 301 redirect to a simple html page if the condition isn’t met until you have finished testing.

  10. Hi I read several blogs and articles and this one actually solved my problem.
    There were actually 40 .js files in my web directory and used 7zip and the htaccess code its working great. I had a doubt while going through the code. It is very clearly explained in the htaccess code that we first check if the browser accepts Gzip file and then we send the Gzip file, in that case why should we specifically exclude browsers. Sorry if this is a stupid/blunt question.

    Raj

  11. You can read the other comments about why we exclude certain browsers. We ignore them because the don’t unpack the gz extension in the normal / expected way like other browsers.

  12. How can I exclude a file on Alternative method 1? My sitemap plugin creates sitemap.xml.gz and I need to exclude it!

Leave a comment

Your email address will not be published.