Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django.

Overview

django-minify-html

https://img.shields.io/github/workflow/status/adamchainz/django-minify-html/CI/main?style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/django-minify-html.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django.

Requirements

Python 3.8 to 3.10 supported.

Django 2.2 to 4.0 supported.


Are your tests slow? Check out my book Speed Up Your Django Tests which covers loads of best practices so you can write faster, more accurate tests.


Installation

  1. Install with pip:

    python -m pip install django-minify-html
  2. Add django-minify-html to your INSTALLED_APPS:

    INSTALLED_APPS = [
        ...,
        "django_minify_html",
        ...,
    ]
  3. Add the middleware:

    MIDDLEWARE = [
        ...,
        "django_minify_html.middleware.MinifyHtmlMiddleware",
        ...,
    ]

    The middleware should be below any other middleware that may encode your responses, such as Django’s GZipMiddleware. It should be above any that may modify your HTML, such as those of django-debug-toolbar or django-browser-reload.

Reference

For information about what minify-html does, refer to its documentation.

django_minify_html.middleware.MinifyHtmlMiddleware

The middleware runs minify_html.minify() on the content of HTML responses. This function minifies HTML, and any inline JavaScript and CSS.

The middleware passes keyword arguments to minify() from its minify_args attribute, a dictionary of names to values. These correspond to the values in the Rust library’s Cfg structure, which have defaults in the Python library as visible in the source. By default the middleware overrides minify_css and minify_js to True. If you need to change an argument, subclass the middleware, replace minify_args, and use your subclass. For example, to preserve comments after minification:

from django_minify_html.middleware import MinifyHtmlMiddleware


class ProjectMinifyHtmlMiddleware:
    minify_args = MinifyHtmlMiddleware.minify_args | {
        "keep_comments": True,
    }

(This example uses Python 3.9’s dictionary merge operator.)

The middleware applies to all non-streaming, non-encoded HTML responses. To restrict this logic, you can subclass, override the should_minify() method, and use your subclass. The should_minify() method accepts the request and response, and returns a bool. For example, to avoid minification of URL’s with the URL prefix /admin/:

from django.http import HttpRequest, HttpResponse

from django_minify_html.middleware import MinifyHtmlMiddleware


class ProjectMinifyHtmlMiddleware:
    def should_minify(self, request: HttpRequest, response: HttpResponse) -> bool:
        return super().should_minify(request, response) and not request.path.startswith(
            "/admin/"
        )

Note that responses are minified even when DEBUG is True. This is recommended because HTML minification can reveal bugs in your templates, so it’s best to always work with your HTML as it will appear in production. Minified HTML is hard to read with “View Source” - it’s best to rely on the inspector in your browser’s developer tools.

Motivation

HTML minification is an underappreciated techinque for web optimization. It can yield significant savings, even on top of other tools like compression with Brotli or Gzip.

There is an existing package for HTML minification in Django, django-htmlmin. But it is much slower, since it does the minification in Python. At time of writing, it is also unmaintained, with no release since March 2019.

There are other minifiers out there, but in benchmarks minify-html surpasses them all. It’s a really well optimized and tested Rust library, and seems to be the best available HTML minifier.

Some CDN’s provide automatic minification, such as CloudFlare. This can be convenient, since it requires no application changes. But it adds some overhead: non-minified HTML has to first be transferred to the CDN, and the CDN has to parse the response, and recombine it. It also means that you don’t get to see the potential side effects of minification until your code is live. Overall it should be faster and more predictable to minify within Django, at the point of HTML generation.

Comments
  • Enabling MinifyHtmlMiddleware causes infinite loop

    Enabling MinifyHtmlMiddleware causes infinite loop

    Python Version

    3.9.2

    Django Version

    3.2.13

    Package Version

    1.3.0

    Description

    Hi!

    I've added MinifyHtmlMiddleware to my project but rendering a view results in an infinite loop until the browser times out. This only happens on a Debian 11 machine with uWSGI. Running the same project on Windows 11 works and the module works correctly.

    MIDDLEWARE = [
        "corsheaders.middleware.CorsMiddleware",
        "django.middleware.gzip.GZipMiddleware",
        "django_minify_html.middleware.MinifyHtmlMiddleware",
        "debug_toolbar.middleware.DebugToolbarMiddleware",
        "django.middleware.security.SecurityMiddleware",
        "whitenoise.middleware.WhiteNoiseMiddleware",
        "user_sessions.middleware.SessionMiddleware",
        "django.middleware.locale.LocaleMiddleware",
        "django.middleware.common.CommonMiddleware",
        "django.middleware.csrf.CsrfViewMiddleware",
        "corsheaders.middleware.CorsPostCsrfMiddleware",
        "x_forwarded_for.middleware.XForwardedForMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.contrib.messages.middleware.MessageMiddleware",
        "django.middleware.clickjacking.XFrameOptionsMiddleware",
        "django.contrib.sites.middleware.CurrentSiteMiddleware",
    ]
    

    Even with GZipMiddleware and CorsMiddleware disabled, the same issue is present.

    What could be the cause for this? The application does not crash and does not log anything.

    opened by kevin-olbrich 6
  • Some issues I found

    Some issues I found

    Python Version

    3.10.2

    Django Version

    4.0.2

    Package Version

    1.0.0

    Description

    I discover 2 issues

    Break html output

    Using only the installation settings: https://github.com/adamchainz/django-minify-html#installation

    With this enabled

    image

    Without this, the original:

    image

    Break select option with empty value

    https://github.com/django-crispy-forms/crispy-bootstrap5/issues/96

    This issue is already reported: https://github.com/adamchainz/django-minify-html/issues/21

    Reporting this as I have to disabled it because I can't live with these 2 issues. Hope to use this library if I could 😁

    opened by shawnngtq 6
  • minify_html strips empty attributes, which produces an error for django select widgets with blank=True

    minify_html strips empty attributes, which produces an error for django select widgets with blank=True

    Python Version

    3.9

    Django Version

    4.0

    Description

    Hey Adam 👋

    Quick FYI I noticed for you (although this is probably more of an unintended feature rather than a bug).

    When using minify_html on a Django template with a select widget that can accept a blank value, minify_html will strip the blank option, which means an exception is caught in the field clean method. E.g:

    class MyModel(models.Model):
        struct_org_type = models.CharField(
            default="",
            blank=True,
            max_length=255,
            choices=SCHEMA_ORG_CHOICES
        )
    

    Would normally render something like:

    <select id="id_struct_org_type" name="struct_org_type">
        <option value="" selected="">---------</option>
        <option value="example_1">Example 1</option>
        <option value="example_2">Example 2</option>
    </select>
    
    

    However, minify_html will strip the empty value="" attribute in the first option. Without this, django won't recognise the input as valid (being null rather than a blank str) if this is the selected option. It produces:

    Select a valid choice. --------- is not one of the available choices.

    I'm not sure there's any way around this, other than to wrap some conditional logic around should_minify() to prevent its use on views with forms, but thought it worth pointing out.

    opened by rob101 6
  • It seems we created the same middleware

    It seems we created the same middleware

    Hi there again,

    I created this repo some time ago. It also has Downloads and Downloads

    Which also has some traffic :

    python

    It essentially does what you are doing here (+ more). But there are some problems with this approach.

    As discussed here your approach is inefficient. ( Decoding GZIP is useless ). Also your approach doesn't work for special HTML tags like ( X-Init, X-Effect, X-On | Used by AlpineJS which is used in many Django project ).

    My approach here fixes some of the issues. Also to allow the usage in other applications I decided to split the main repo in another project.

    Also 2 projects for essentially one end goal is kinda useless. Because we will essentially rewrite same thing without adding any new features. Is there any chance of merging our repos together or focusing on one repo ( which will essentially allow this module to be used in every python application ) ?

    Currently my repo has an issue, which if fixed will be a feature complete library. I also have an idea of using esbuild with PyO3 ( which minify-html uses and with which i will replace minify-html ) to make the module even faster. I will also add full support for petite-vue in the next year. But for now the development is a bit slow as I am still a beginner in rust.

    opened by baseplate-admin 3
  • ending body & html tag missing

    ending body & html tag missing

    Python Version

    3.10

    Django Version

    4.1.2

    Package Version

    1.3.0

    Description

    ending and </html tags are missing, posting screenshots here... image Please reply...

    opened by amanrawat121 2
  • Enabling minify brokes django-cms toolbar menu

    Enabling minify brokes django-cms toolbar menu

    If I enable MinifyHtmlMiddleware then this menu (page, Language) will make broken Screenshot 2022-09-01 at 08 03 07

    Not sure what data is cutting off with MinifyHtmlMiddleware is going to this result.

    opened by LennyLip 1
  • Issue installing it on Alpine image

    Issue installing it on Alpine image

    Python Version

    3.10.2

    Django Version

    4.0.2

    Package Version

    1.0.0

    Description

    I am creating the docker image of my app (I was developing it with python manage.py run server) and I want to use an alpine image, but I get this error message when I run pip install -r requirements.txt:

    ERROR: Could not find a version that satisfies the requirement minify-html (from django-minify-html) (from versions: none)
    ERROR: No matching distribution found for minify-html
    
    opened by kennylajara 1
  • Do we need the app?

    Do we need the app?

    Python Version

    3.10.2

    Django Version

    4.0.2

    Package Version

    1.0.0

    Description

    I installed the middleware but not the app and it is still working. Is the app necessary? What is the function of the app?

    opened by kennylajara 1
  • onepass variant support

    onepass variant support

    Description

    minify-html-onepass is now on PyPI: https://github.com/wilsonzlin/minify-html/issues/60

    We could adapt this package to support using it for those who want more speed.

    opened by adamchainz 0
Owner
Adam Johnson
🦄 @django technical board member 🇬🇧 @djangolondon co-organizer ✍ AWS/Django/Python Author and Consultant
Adam Johnson
Fully reponsive Chat Application built with django, javascript, materialUi, bootstrap4, html and css.

Chat app (Full Stack Frameworks with Django Project) Fully reponsive Chat Application built with django, javascript, materialUi, bootstrap4, html and

null 1 Jan 19, 2022
This "I P L Team Project" is developed by Prasanta Kumar Mohanty using Python with Django web framework, HTML & CSS.

I-P-L-Team-Project This "I P L Team Project" is developed by Prasanta Kumar Mohanty using Python with Django web framework, HTML & CSS. Screenshots HO

null 1 Dec 15, 2021
Django-Text-to-HTML-converter - The simple Text to HTML Converter using Django framework

Django-Text-to-HTML-converter This is the simple Text to HTML Converter using Dj

Nikit Singh Kanyal 6 Oct 9, 2022
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 2, 2023
Basic Form Web Development using Python, Django and CSS

thebookrain Basic Form Web Development using Python, Django and CSS This is a basic project that contains two forms - borrow and donate. The form data

Ananya Dhulipala 1 Nov 27, 2021
Compresses linked and inline javascript or CSS into a single cached file.

Django Compressor Django Compressor processes, combines and minifies linked and inline Javascript or CSS in a Django template into cacheable static fi

null 2.6k Jan 3, 2023
Packs a bunch of smaller CSS files together from 1 folder.

Packs a bunch of smaller CSS files together from 1 folder.

null 1 Dec 9, 2021
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

lhy 139 Dec 5, 2022
Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project

Django URL Shortener Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project Install this package to your Dja

Rishav Sinha 4 Nov 18, 2021
django-tables2 - An app for creating HTML tables

django-tables2 - An app for creating HTML tables django-tables2 simplifies the task of turning sets of data into HTML tables. It has native support fo

Jan Pieter Waagmeester 1.6k Jan 3, 2023
The best way to have DRY Django forms. The app provides a tag and filter that lets you quickly render forms in a div format while providing an enormous amount of capability to configure and control the rendered HTML.

django-crispy-forms The best way to have Django DRY forms. Build programmatic reusable layouts out of components, having full control of the rendered

null 4.6k Jan 7, 2023
A Powerful HTML white space remover for Django

HTML Whitespace remover for Django Introduction : A powerful tool to optimize Django rendered templates Why use "django_stip_whitespace" ? Adds line b

null 3 Jan 1, 2022
An app that allows you to add recipes from the dashboard made using DJango, JQuery, JScript and HTMl.

An app that allows you to add recipes from the dashboard. Then visitors filter based on different categories also each ingredient has a unique page with their related recipes.

Pablo Sagredo 1 Jan 31, 2022
Fast / fuzzy PostgreSQL counts for Django

Created by Stephen McDonald Introduction Up until PostgreSQL 9.2, COUNT queries generally required scanning every row in a database table. With millio

stephenmcd 85 Oct 25, 2021
Django-fast-export - Utilities for quickly streaming CSV responses to the client

django-fast-export Utilities for quickly streaming CSV responses to the client T

Matthias Kestenholz 4 Aug 24, 2022
Transparently use webpack with django

Looking for maintainers This repository is unmaintained as I don't have any free time to dedicate to this effort. If you or your organisation are heav

Owais Lone 2.4k Jan 6, 2023
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Jan 7, 2023
Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards and optional settings files.

Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards in settings file paths and mark setti

Nikita Sobolev 940 Jan 3, 2023
Full-text multi-table search application for Django. Easy to install and use, with good performance.

django-watson django-watson is a fast multi-model full-text search plugin for Django. It is easy to install and use, and provides high quality search

Dave Hall 1.1k Dec 22, 2022