{"id":28745451,"url":"https://github.com/xfenix/django-hmin","last_synced_at":"2025-09-17T23:21:39.608Z","repository":{"id":22138800,"uuid":"25469854","full_name":"xfenix/django-hmin","owner":"xfenix","description":"Django HTML minification middleware (another one,  very much faster than django-htmlmin)","archived":false,"fork":false,"pushed_at":"2024-07-09T18:07:34.000Z","size":934,"stargazers_count":12,"open_issues_count":5,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-13T04:41:28.714Z","etag":null,"topics":["django","html","html5","htmlmin","minification","python","python38"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xfenix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-10-20T14:22:01.000Z","updated_at":"2024-05-19T10:21:18.000Z","dependencies_parsed_at":"2025-04-11T19:01:56.247Z","dependency_job_id":"58fcb576-9b99-4609-9a5f-66f29c99ee97","html_url":"https://github.com/xfenix/django-hmin","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/xfenix/django-hmin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xfenix%2Fdjango-hmin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xfenix%2Fdjango-hmin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xfenix%2Fdjango-hmin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xfenix%2Fdjango-hmin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xfenix","download_url":"https://codeload.github.com/xfenix/django-hmin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xfenix%2Fdjango-hmin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275358989,"owners_count":25450470,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","html","html5","htmlmin","minification","python","python38"],"created_at":"2025-06-16T13:11:29.136Z","updated_at":"2025-09-17T23:21:39.170Z","avatar_url":"https://github.com/xfenix.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# django-hmin\n\n![Build and publish](https://github.com/xfenix/django-hmin/workflows/Build%20and%20publish/badge.svg)\n[![PyPI version](https://badge.fury.io/py/django-hmin.svg)](https://badge.fury.io/py/django-hmin)\n[![codecov](https://codecov.io/gh/xfenix/django-hmin/branch/master/graph/badge.svg)](https://codecov.io/gh/xfenix/django-hmin)\n\u003ca href=\"https://github.com/psf/black\"\u003e\u003cimg alt=\"Code style: black\" src=\"https://img.shields.io/badge/code%20style-black-000000.svg\"\u003e\u003c/a\u003e\n\nDjango (2.0+) oriented HTML minification function and middleware (another one).  \nKey feature — speed. 10x (on large html's it can be 50x, 100x, 200x or even more) time faster, than htmlmin.\n\nCompress html code and removes html comments, but ignores conditional comments (IE) by default.  \nUses cache by default (can be disabled), so minification overhead is greatly reduced.  \nAlso it can be used as solo function.  \nFor best expirience use it with https://github.com/django-compressor/django-compressor.\n\nWritten in modern python 3.7+ with fully typing-covered codebase.\n\nFull support of:\n\n- https://www.python.org/dev/peps/pep-0526/\n- https://www.python.org/dev/peps/pep-0484/\n- https://www.python.org/dev/peps/pep-0008/\n- https://www.python.org/dev/peps/pep-0257/\n- https://www.python.org/dev/peps/pep-0518/\n- https://www.python.org/dev/peps/pep-0585/\n\n# Compatibility\n\n- Python 3.7+\n- Django 2.0+ (not required)\n\n# Install\n\n### Regular way\n\nFor install django-hmin, run on terminal:\n\n```bash\n$ pip install django-hmin\n```\n\n### Advanced\n\nIf there is no release, or you dont want/cant use pypi, then:\n\n- `git clone` this repo\n- `pipenv install` to install requirements or just `pip install flit`\n- `flit install`\n  Yes, we dont use classic `setup.py`, we use flit + `pyproject.toml`. God bless PEP-518 + PEP-621.\n\n# Using with Django as midleware\n\nAll you need to do is add two middlewares to your `MIDDLEWARE_CLASSES`:\n\n```python\nMIDDLEWARE_CLASSES: tuple = (\n    # other middleware classes\n    'hmin.middleware.MinMiddleware',\n    'hmin.middleware.MarkMiddleware',\n)\n```\n\nIf you're using Django's caching middleware, `MarkMiddleware`\nshould go after `FetchFromCacheMiddleware`, and `MinMiddleware`\nshould go after `UpdateCacheMiddleware`:\n\n```python\nMIDDLEWARE_CLASSES: tuple = (\n    'django.middleware.cache.UpdateCacheMiddleware',\n    'hmin.middleware.MinMiddleware',\n    # other middleware classes\n    'django.middleware.cache.FetchFromCacheMiddleware',\n    'hmin.middleware.MarkMiddleware',\n)\n```\n\nYou can optionally specify the `HTML_MINIFY` setting:\n\n```python\nHTML_MINIFY: bool = True\n```\n\nThe default value for the `HTML_MINIFY` setting is `not DEBUG`. You only\nneed to set it to `True` if you want to minify your HTML code when `DEBUG`\nis enabled.\n\n### URL exclude\n\nSpecify setting:\n\n```python\nHMIN_EXCLUDE: tuple = ('^base/', '^admin/')\n```\n\n### Keep HTML comments\n\nSpecify settings:\n\n```python\nHMIN_REMOVE_COMMENTS: bool = False\n```\n\n### Cache\n\nBy default hmin middleware uses cache via django caches framework (very useful for small and middle web sites, and for big you definitely will use ngx_pagespeed or other \"big\" solutions).\nYou can disable it by specify setting:\n\n```python\nHMIN_USE_CACHE: bool = False\n```\n\nAlso you can change time and cache backend (if you want, by default time is 3600, cache backend — \"default\"):\n\n```python\nHMIN_CACHE_TIMEOUT: int = 86400\nHMIN_CACHE_BACKEND: str = 'my_cache'\n```\n\n# More using scenarios\n\n### Decorators\n\nJust import decorator minify_plain: `from hmin.decorators import minify_plain`, than you can minify any function you want:\n\n```python\n@minify_plain()\ndef my_cool_func():\n    \u003c...\u003e\n    return some_plain_html\n```\n\nOr, if you want to keep html comments:\n\n```python\n@minify_plain(False)\ndef my_cool_func():\n    \u003c...\u003e\n    return some_plain_html\n```\n\n### Solo\n\nJust import function minify. Function definition: `def minify(content, remove_comments=True)`. Example:\n\n```python\nfrom hmin import html_minify\n\n\nhtml_minify('\u003cdiv\u003e     hello\u003c/div\u003e') # \u003cdiv\u003ehello\u003c/div\u003e\n```\n\n### CLI\n\n```bash\n$ python -m hmin filename.html \u003e filename.min.html\n```\n\n# Benchmarking (wannabe)\n\n### New data\n\nI try to compress 1.1mb of very dense html on my i7 laptop processor (2020 edition!) and measure raw time with chrome inspector.  \nI got following data (this data comes from field \"Waiting (TTFB)\", not \"Content Download\"):\n\n- htmlmin took about **2.5 seconds**!\n- this package took:\n  - ~**100ms** (verion 0.5.2)\n  - ~**60ms** (version 0.5.3) — i fixed some bug in regexp, now package doesnt strip spaces BEFORE open tag, cause it was incorrect behaviour. So, now speed is like previous version. Yes! :)\n\nAs you can see, hmin 0.5+ are slightly slower than 0.3, but this is comes from updated minifcation logic. In previous version minification was not so accurate, as i think. But, hmin still very much faster.  \nMaybe in the next releases i made some experiments with cython or numba to improve speed.\n\n### Old data (version \u003c 0.5)\n\n#### Stupid speed benchmark (1)\n\nI try to compress 1mb of html (i think, your usual html is slightly thiner) on my i7 laptop processor and measure time with django-debug-toolbar.  \nDjango overhead took about 40ms (all), this is time without minification, just plain html, django, etc.  \nThen i install hmin and htmlmin and just look at the debug toolbar numbers (this is very silly and simple \"benchmark\"):\n\n- with hmin cpu was about **60ms** (min)\n- with htmlmin cpu was about **1200ms** (min)\n  Minus overhead, plain time: hmin — **20ms**, htmlmin — **1160ms**.  \n  Probably, you can get other numbers. But hmin really faster than htmlmin.\n\n#### Stupid speed benchmark (2)\n\nAlso i try to compress 2mb of html on my desktop i3 (sandy bridge).  \nDebug toolbar time:\n\n- with hmin cpu was about **220ms** without cache, and **87ms** with cache\n- with htmlmin cpu was about **125000ms**\n  Django overhead was about **80ms**.  \n  Minus overhead, plain time: hmin — **140ms** (**7ms** with cache), htmlmin — ok.\n\n# Changelog\n\nYou can check https://github.com/xfenix/django-hmin/releases release page.\n\n# Current possible problems\n\n- Doesnt respect CDATA\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxfenix%2Fdjango-hmin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxfenix%2Fdjango-hmin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxfenix%2Fdjango-hmin/lists"}