Django Compressor – Minify/Reduce Requests
The Problem
Nowadays with all the JS frameworks and CSS Frameworks, our web applications end up with a very rich and interactive UI (also called User Experience). With the easy-of-use that this tools bring, many plug-ins and third-party code gets integrated in our apps. Usually this code comes bundled with many CSS and JS files (usually one for each plug-in). They easily pile-up to become a bottleneck of browser rendering performance.
As Yahoo points out in this article, one of the best ways to speed up your website is to drastically reduce the number of requests that the user’s browser has to do.
Another way to improve performance is to minify your CSS and JS. The minify action reduces the number of bytes that go through the wire, thus improving download speed for your users.
At the company I work for we faced a big issue with our pluggable app. After many plug-ins and customizations by clients, our pages were REALLY big with MANY (100+) requests. You can easily guess that this is not a situation you want your website to be in, right?
Django Compressor
Enter Django Compressor, the pluggable app for Django that provides a template tag to compress CSS and JS. It does more than that, though. Django Compressor provides an extensible architecture that allows you to implement your own template parser, your own template filters and your own static CSS and JS Storage. We’ll discuss more of each in the following topics.
I just want to thank beforehand all the effort that has been put in this project and all the involved people. The quality of the project has really surprised (a good surprise) me and I’m really glad to have found it (via Gabriel Falcão).
Basic Usage
As you can read in the readme file (or in github main page), it’s really simple to set Django Compressor up. The steps are:
- Add ‘compressor’ to INSTALLED_APPS in the settings.py file for your Django app (make sure compressor can be imported using ‘import compressor’ in python).
- You don’t *HAVE* to, but I like to specify whether I want compression on or off (the default is the opposite of DEBUG, meaning that in DEBUG mode you don’t compress and with DEBUG off you get compression). If you, like me, want to specify whether to compress or not, just add COMPRESS=True to your settings.py file (anywhere).
- Go to a template where you have many CSS and include the following:
-
{% load compress %} before using any compression. This loads the template tag. -
In your templates, you compress your stylesheets: {% compress css %} <link type="text/css" rel="stylesheet" media="screen" href="/media/my.css" /> <!-- many more css files --> {% endcompress %}
-
That’s all there’s to it. After reloading your view you should see that the my.css link got replaced with <<some_hash>>.css. The hash here is generated based on the contents that got compressed. This means that all the CSS requests that were being done previously will now be done in one go. The same goes for JS, the only difference being that you supply ‘js’ as argument to compress, like this:
{% compress js %}
<script type="text/javascript" src="/media/my.js" />
<!-- many more js files -->
{% endcompress %}
It gets better, though!
Compressor Filters
Django Compressor uses a really simple and easy to understand filter architecture. Basically whatever filters you specify for JS (in the COMPRESS_JS_FILTERS setting) and for CSS (in the COMPRESS_CSS_FILTERS setting) will get called sequentially in order to modify the output.
What this means is that if you want to validate, minify and then concatenate your CSS files, all you have to do is specify the proper filters (or implement your own).
In our current scenario we are using the following settings:
COMPRESS_CSS_FILTERS = [ 'compressor.filters.cssmin.CSSMinFilter' ] COMPRESS_JS_FILTERS = [ 'compressor.filters.jsmin.JSMinFilter' ]
As you can see I’m only using the filters that are already provided with Django Compressor. What this means is that I get for free CSS and JS minification.
If you want to implement your own filters I suggest you take a look at the code for the current filters in Django Compressor (in the filters folder in the source code).
Django Compressor FileStorage
Django Compressor uses Django’s concept of a File Storage. A file storage is an entity responsible for every related file operation that Compressor needs to execute (verifying if a file exists, building file paths, opening and saving files, etc.).
Here at our team we have media distributed in many apps, all of them inside a /media folder. We distribute media like that because our clients plug-in only the apps that they need, so it makes sense that the medias stay where they actually belong. That works pretty well with the way django loads media but deployment is a little harder. We had to work our own deployment scheme (subject for a later post).
By default django compressor only uses the projects media folder (as specified in the MEDIA_PATH setting). We had to change it so we could use it with our apps. It was as easy as implementing our own File Storage class. You can check it at my fork in http://github.com/heynemann/django_compressor. As of the time of this post our code has not been integrated to the Django Compressor project. We are hoping that it does soon.
To use our custom storage all we had to do was specify it in the settings.py file with:
COMPRESS_STORAGE = 'compressor.storage.AppSavvyCompressorFileStorage'
And that’s it! Now the pages that refer to medias in our apps also get compressed.
Conclusion
Django Compressor is a really cool project and very worth contributing to. It already features many filters, parsers and now two storages. If you want to speed-up the loading time of your pages and you are using Django, you definitely should consider it.

Recent Comments