{"id":44405787,"url":"https://github.com/openwisp/django-minify-compress-staticfiles","last_synced_at":"2026-04-25T21:03:57.117Z","repository":{"id":335192781,"uuid":"1144685781","full_name":"openwisp/django-minify-compress-staticfiles","owner":"openwisp","description":"A modern Django package for minifying and compressing static files during collectstatic with minimal configuration.","archived":false,"fork":false,"pushed_at":"2026-01-31T23:33:06.000Z","size":78,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-12T20:33:06.638Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openwisp.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-28T23:50:44.000Z","updated_at":"2026-03-04T18:12:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/openwisp/django-minify-compress-staticfiles","commit_stats":null,"previous_names":["openwisp/django-minify-compress-staticfiles"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/openwisp/django-minify-compress-staticfiles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openwisp%2Fdjango-minify-compress-staticfiles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openwisp%2Fdjango-minify-compress-staticfiles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openwisp%2Fdjango-minify-compress-staticfiles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openwisp%2Fdjango-minify-compress-staticfiles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openwisp","download_url":"https://codeload.github.com/openwisp/django-minify-compress-staticfiles/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openwisp%2Fdjango-minify-compress-staticfiles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32276636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-02-12T06:39:51.030Z","updated_at":"2026-04-25T21:03:57.112Z","avatar_url":"https://github.com/openwisp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Django Minify Compress StaticFiles\n==================================\n\n.. image:: https://github.com/openwisp/django-minify-compress-staticfiles/workflows/CI/badge.svg\n    :target: https://github.com/openwisp/django-minify-compress-staticfiles/actions\n    :alt: CI build status\n\n.. image:: https://coveralls.io/repos/github/openwisp/django-minify-compress-staticfiles/badge.svg?branch=master\n    :target: https://coveralls.io/github/openwisp/django-minify-compress-staticfiles?branch=master\n    :alt: Coverage\n\n.. image:: https://badge.fury.io/py/django-minify-compress-staticfiles.svg\n    :target: https://badge.fury.io/py/django-minify-compress-staticfiles\n    :alt: PyPI Version\n\n.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg\n    :target: https://opensource.org/licenses/BSD-3-Clause\n    :alt: License\n\nA modern Django package for minifying and compressing static files during\n``collectstatic`` with minimal configuration.\n\nFeatures\n--------\n\n- **CSS/JS Minification**: Uses ``rjsmin`` and ``rcssmin`` for fast\n  minification\n- **Dual Compression**: Gzip and Brotli compression support\n- **Django Integration**: Seamless integration with Django's static file\n  system\n- **Selective Processing**: Only processes appropriate file types\n- **Minified Filename Format**: Preserves Django's hash and adds ``.min``\n  before the extension: ``name.{hash}.min.ext``. This allows precompressed\n  files to be properly served as ``name.{hash}.min.ext.gz`` and\n  ``name.{hash}.min.ext.br``.\n- **Configurable**: Fine-grained control over processing options\n\nInstallation\n------------\n\nInstall from PyPI:\n\n.. code-block:: bash\n\n    pip install django-minify-compress-staticfiles\n\nConfiguration\n-------------\n\nFor **Django 4.2+**, update your ``STORAGES`` setting:\n\n.. code-block:: python\n\n    STORAGES = {\n        \"default\": {\n            \"BACKEND\": \"django.core.files.storage.FileSystemStorage\",\n        },\n        \"staticfiles\": {\n            \"BACKEND\": \"django_minify_compress_staticfiles.storage.MinicompressStorage\",\n        },\n    }\n\nFor **Django \u003c 4.2**, use the legacy setting:\n\n.. code-block:: python\n\n    STATICFILES_STORAGE = \"django_minify_compress_staticfiles.storage.MinicompressStorage\"\n\nSettings\n--------\n\nAll settings use the ``MINICOMPRESS_`` prefix:\n\n``MINICOMPRESS_ENABLED``\n    Enable/disable processing (default: ``True``)\n\n``MINICOMPRESS_MINIFY_FILES``\n    Enable CSS/JS minification (default: ``True``)\n\n``MINICOMPRESS_GZIP_COMPRESSION``\n    Enable Gzip compression (default: ``True``)\n\n``MINICOMPRESS_BROTLI_COMPRESSION``\n    Enable Brotli compression (default: ``True``)\n\n``MINICOMPRESS_MIN_FILE_SIZE``\n    Minimum file size for compression in bytes (default: ``200``)\n\n``MINICOMPRESS_MAX_FILE_SIZE``\n    Maximum file size for processing in bytes (default: ``10485760``,\n    i.e., 10MB) Files larger than this are skipped to prevent memory\n    exhaustion. Adjust based on your available memory and security\n    requirements.\n\n``MINICOMPRESS_MAX_FILES_PER_RUN``\n    Maximum number of files to process per ``collectstatic`` run (default:\n    ``1000``) Prevents CPU and memory exhaustion when processing large\n    numbers of files. Increase only if you have verified your system can\n    handle it.\n\n``MINICOMPRESS_COMPRESSION_LEVEL_GZIP``\n    Gzip compression level (default: ``6``, range: 0-9) Level 6 provides a\n    good balance between compression ratio and CPU usage. Higher values\n    (8-9) consume significantly more CPU with diminishing returns. Lower\n    values (0-5) are faster but produce larger compressed files.\n\n``MINICOMPRESS_COMPRESSION_LEVEL_BROTLI``\n    Brotli compression quality (default: ``4``, range: 0-11) Level 4\n    offers excellent compression with reasonable CPU usage. Higher values\n    (8-11) can cause severe CPU spikes during ``collectstatic``. Lower\n    values (0-3) are faster but less effective compression.\n\n``MINICOMPRESS_PRESERVE_COMMENTS``\n    Preserve bang comments in CSS/JS (default: ``True``)\n\n``MINICOMPRESS_SUPPORTED_EXTENSIONS``\n    Dictionary of file extensions to process (default: css, js, txt, xml,\n    json, svg, md, rst, html, htm)\n\n``MINICOMPRESS_EXCLUDE_PATTERNS``\n    List of glob patterns to exclude from processing (default:\n    ``[\"*.min.*\", \"*-min.*\", \"*swagger-ui-*\", \"*.gz\", \"*.br\", \"*.zip\"]``)\n    Pre-compressed files (e.g., ``.gz``, ``.br``, ``.zip``) are excluded\n    by default to prevent double-compression and security issues.\n\nUsage\n-----\n\nRun ``collectstatic`` as usual:\n\n.. code-block:: bash\n\n    python manage.py collectstatic --noinput\n\nThe package will automatically:\n\n- Minify CSS and JavaScript files\n- Create ``.gz`` and ``.br`` compressed versions\n- Update Django's manifest with minified file paths\n- Skip already processed files and patterns\n\nSupported File Types\n--------------------\n\n**Minification**: CSS, JavaScript\n\n**Compression**: CSS, JS, TXT, XML, JSON, SVG, MD, RST, HTML, HTM\n\nSecurity and Performance Considerations\n---------------------------------------\n\nThe package implements the following safeguards to mitigate common attack\nvectors and ensure resource stability.\n\nPath Traversal Protection\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo prevent directory traversal attacks (e.g., ``../etc/passwd``), all file\npaths undergo strict validation. The system enforces a boundary check\nensuring no read or write operations occur outside the defined\n``STATIC_ROOT``. Any attempt to access parent directories via relative\npaths is intercepted and blocked.\n\nMemory Exhaustion Prevention\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo prevent memory exhaustion, the ``MAX_FILE_SIZE`` setting enforces a\nhard cap on file processing. This prevents the application from attempting\nto buffer or process excessively large files that could lead to\nOut-Of-Memory (OOM) errors.\n\nCPU Exhaustion \u0026 Resource Throttling\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCompression is a CPU-intensive task. To balance throughput with system\nstability, the default compression levels are tuned for efficiency:\n\n- **Gzip:** Level 6\n- **Brotli:** Level 4\n\nThese defaults prevent \"CPU pinning\" where a single request monopolizes\nprocessor cycles.\n\nCompression Bomb Protection\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe processor automatically excludes files that are already compressed\n(e.g., ``.gz``, ``.br``, ``.zip``, ``.png``). This prevents recursive\ncompression cycles and \"Zip Bomb\" style attacks that could lead to\nexponential CPU and disk space consumption.\n\nIntegrity \u0026 Cache Validation\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFile fingerprinting uses **MD5** hashing to match Django's\n``ManifestFilesMixin`` algorithm. This ensures consistency between\nDjango's hashed filenames and our minified filenames, allowing the\nmanifest to correctly map original files to their minified versions.\n\nRecommended Settings for Production\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFor production deployments with high security requirements:\n\n.. code-block:: python\n\n    MINICOMPRESS_MAX_FILE_SIZE = 2097152  # 2MB\n    MINICOMPRESS_MAX_FILES_PER_RUN = 500\n    MINICOMPRESS_COMPRESSION_LEVEL_GZIP = 6\n    MINICOMPRESS_COMPRESSION_LEVEL_BROTLI = 4\n\nFor development environments with faster builds:\n\n.. code-block:: python\n\n    MINICOMPRESS_COMPRESSION_LEVEL_GZIP = 1\n    MINICOMPRESS_COMPRESSION_LEVEL_BROTLI = 0\n    MINICOMPRESS_BROTLI_COMPRESSION = False  # Disable for faster builds\n\nDependencies\n------------\n\n**Required**:\n\n- Django \u003e= 4.2\n- Python \u003e= 3.10\n- ``brotli`` \u003e= 1.0.0\n- ``rjsmin`` \u003e= 1.2.0\n- ``rcssmin`` \u003e= 1.1.0\n\nLicense\n-------\n\nBSD 3-Clause License. See ``LICENSE`` file for details.\n\nContributing\n------------\n\nContributions are welcome! Please see the `OpenWISP contributing\nguidelines`_ for more information.\n\n.. _openwisp contributing guidelines: https://openwisp.io/docs/stable/developer/contributing.html\n\nSupport\n-------\n\n- `Issue Tracker`_\n- `OpenWISP Support`_\n\n.. _issue tracker: https://github.com/openwisp/django-minify-compress-staticfiles/issues\n\n.. _openwisp support: https://openwisp.org/support/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenwisp%2Fdjango-minify-compress-staticfiles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenwisp%2Fdjango-minify-compress-staticfiles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenwisp%2Fdjango-minify-compress-staticfiles/lists"}