How to minify HTML output in Django

So, you want to compress the size of the HTML that Django generates? Here is the Django way to do it.

In order to do this, you’ll have to write a middleware for your application.

So, create a file called middleware.py (for this example, but you can name it whatever you want) inside your Django app folder (let’s call the app MyTestApp). Copy the following code inside it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import re
from django.utils.html import strip_spaces_between_tags
from django.conf import settings
 
RE_MULTISPACE = re.compile(r"\s{2,}")
RE_NEWLINE = re.compile(r"\n")
 
class MinifyHTMLMiddleware(object):
    def process_response(self, request, response):
        if 'text/html' in response['Content-Type'] and settings.COMPRESS_HTML:
            response.content = strip_spaces_between_tags(response.content.strip())
            response.content = RE_MULTISPACE.sub(" ", response.content)
            response.content = RE_NEWLINE.sub("", response.content)
        return response

What this does is: first, it removes all the spaces between tags. The problem is that it will remove the space only if between the tags there will be ONLY spaces. But sometimes you have cases like this:

1
<div> .....</div>         Some text    <div> .....</div>

In this case, the space between the two divs will not be compressed because of the “Some text” string, but nevertheless, the spaces will be rendered as only one. To solve this, the
next thing it does is replace multiple appearances of spaces with only one space. Finally, it will remove all the new lines from the html, because they are anyway ignored by the browsers.

After adding the above code to middleware.py, add the following line to MIDDLEWARE_CLASSES in your settings file:

1
'MyTestApp.middleware.MinifyHTMLMiddleware'

Replace MyTestApp with the name of you app and middleware with the name that you gave to the middleware.py file (if you did gave it another name).

Hope this helps!

UPDATE

You also have to add in your settings COMPRESS_HTML and set it to True, if you want to compress the html, or False otherwise.

1
COMPRESS_HTML = True

Comments

10 Responses to “How to minify HTML output in Django”
  1. Greg says:

    You forgot to mention the COMPRESS_HTML setting.

  2. Martin says:

    This is simple and very useful! Thanks!

  3. Ferrix Hovi says:

    I suggest you replace newlines with a space and reverse the multispace and newline regexps. This will eliminate the problem you get with links separated from text with newlines. This should not render as foobar:

    foo
    bar

  4. Ferrix Hovi says:

    I suggest you replace newlines with a space and reverse the multispace and newline regexps. This will eliminate the problem you get with links separated from text with newlines. This should not render as foobar:

    <a>foo</a>
    bar

    Additionally you should use getattr(settings, ‘COMPRESS_HTML’, False) to get the setting so that apps do not start crashing when you introduce this middleware.

  5. Young says:

    It is bad to have a processor to minify html in middleware. It will slow down your site. You need preprocessor to minify html and i’m looking for that solution.

  6. Leszek says:

    Yeah indeed it’s bad idea to do it in middleware.

    Try out my template loader, it does not minify CSS and JS but it really simple for HTML

    https://github.com/iRynek/django-template-minifier

  7. Andrew says:

    Thanks!

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!