The Simplest Way to Compress HTML in Django
NOTE: Since writing this post, it has been brought to my attention that as of 2013, there is a new potential attack vector on sites using gzip. Please read this Django security comment for more information after reading this article.
I’ve been working on a lot of website optimization stuff recently for my Django projects, and thought I’d share a cool utility I found for compressing your entire site’s HTML code.
If you’re running any site that could benefit from reduced page load times (who wouldn’t want that?) you may want to consider giving this a go. Essentially, what we’re going to do is take your normal Django template code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
</html>
And compress it so that when the page is rendered for users, it looks like this:
<!doctype html><html lang="en"><head><meta charset="utf-8"/></head></html>
Obviously this is a simple example, but when you have pages with lots of content on them, compressing your pages can lead to a really big page load performance boost, since you’re sending significantly less data to the end user.
The Django app you’ll be using to do this is django-htmlmin. To get started, you really only need to do two things:
pip install django-htmlmin
- Add
htmlmin.middleware.HtmlMinifyMiddleware
to yourMIDDLEWARE_CLASSES
setting.
By default, django-htmlmin
will only compress HTML when your DEBUG
setting
is set to False
(e.g. when your site is running in production)–this way,
while you’re developing and testing your code, you’ll still have your HTML
uncompressed so you can look at it in its original form.
Here’s a quick snippet from my settings.py
which shows my
MIDDLEWARE_CLASSES
(for reference):
MIDDLEWARE_CLASSES = (
'django.middleware.gzip.GZipMiddleware',
'htmlmin.middleware.HtmlMinifyMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
NOTE: If you’re concerned about compressing HTML, you should probably also
enable Django’s GZipMiddleware
(as you can see in my snippet above). GZip
compression will greatly reduce the size of your page’s data for transfer to
the end user, further decreasing page load time.
IMPORTANT: You should always have both GZipMiddleware
and
HtmlMinifyMiddleware
defined before all other middleware classes. The
ordering of the MIDDLEWARE_CLASSES
tuple matters in Django, and since both of
these middleware modify HTML after it’s already been passed through the other
middleware classes, it is necessary to have them executed last by Django (which
means defining them first in MIDDLEWARE_CLASSES
).
PS: If you read this far, you might want to follow me on Bluesky or GitHub and subscribe via RSS or email below (I'll email you new articles when I publish them).