A modern Django package for minifying and compressing static files during
collectstatic with minimal configuration.
- CSS/JS Minification: Uses
rjsminandrcssminfor fast minification - Dual Compression: Gzip and Brotli compression support
- Django Integration: Seamless integration with Django's static file system
- Selective Processing: Only processes appropriate file types
- Minified Filename Format: Preserves Django's hash and adds
.minbefore the extension:name.{hash}.min.ext. This allows precompressed files to be properly served asname.{hash}.min.ext.gzandname.{hash}.min.ext.br. - Configurable: Fine-grained control over processing options
Install from PyPI:
pip install django-minify-compress-staticfilesFor Django 4.2+, update your STORAGES setting:
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django_minify_compress_staticfiles.storage.MinicompressStorage",
},
}For Django < 4.2, use the legacy setting:
STATICFILES_STORAGE = "django_minify_compress_staticfiles.storage.MinicompressStorage"All settings use the MINICOMPRESS_ prefix:
MINICOMPRESS_ENABLED- Enable/disable processing (default:
True) MINICOMPRESS_MINIFY_FILES- Enable CSS/JS minification (default:
True) MINICOMPRESS_GZIP_COMPRESSION- Enable Gzip compression (default:
True) MINICOMPRESS_BROTLI_COMPRESSION- Enable Brotli compression (default:
True) MINICOMPRESS_MIN_FILE_SIZE- Minimum file size for compression in bytes (default:
200) MINICOMPRESS_MAX_FILE_SIZE- Maximum file size for processing in bytes (default:
10485760, i.e., 10MB) Files larger than this are skipped to prevent memory exhaustion. Adjust based on your available memory and security requirements. MINICOMPRESS_MAX_FILES_PER_RUN- Maximum number of files to process per
collectstaticrun (default:1000) Prevents CPU and memory exhaustion when processing large numbers of files. Increase only if you have verified your system can handle it. MINICOMPRESS_COMPRESSION_LEVEL_GZIP- Gzip compression level (default:
6, range: 0-9) Level 6 provides a good balance between compression ratio and CPU usage. Higher values (8-9) consume significantly more CPU with diminishing returns. Lower values (0-5) are faster but produce larger compressed files. MINICOMPRESS_COMPRESSION_LEVEL_BROTLI- Brotli compression quality (default:
4, range: 0-11) Level 4 offers excellent compression with reasonable CPU usage. Higher values (8-11) can cause severe CPU spikes duringcollectstatic. Lower values (0-3) are faster but less effective compression. MINICOMPRESS_PRESERVE_COMMENTS- Preserve bang comments in CSS/JS (default:
True) MINICOMPRESS_SUPPORTED_EXTENSIONS- Dictionary of file extensions to process (default: css, js, txt, xml, json, svg, md, rst, html, htm)
MINICOMPRESS_EXCLUDE_PATTERNS- List of glob patterns to exclude from processing (default:
["*.min.*", "*-min.*", "*.gz", "*.br", "*.zip"]) Pre-compressed files (e.g.,.gz,.br,.zip) are excluded by default to prevent double-compression and security issues.
Run collectstatic as usual:
python manage.py collectstatic --noinputThe package will automatically:
- Minify CSS and JavaScript files
- Create
.gzand.brcompressed versions - Update Django's manifest with minified file paths
- Skip already processed files and patterns
Minification: CSS, JavaScript
Compression: CSS, JS, TXT, XML, JSON, SVG, MD, RST, HTML, HTM
Files matching *.min.* or *-min.* patterns are excluded from
processing.
The package implements the following safeguards to mitigate common attack vectors and ensure resource stability.
To prevent directory traversal attacks (e.g., ../etc/passwd), all file
paths undergo strict validation. The system enforces a boundary check
ensuring no read or write operations occur outside the defined
STATIC_ROOT. Any attempt to access parent directories via relative
paths is intercepted and blocked.
To prevent memory exhaustion, the MAX_FILE_SIZE setting enforces a
hard cap on file processing. This prevents the application from attempting
to buffer or process excessively large files that could lead to
Out-Of-Memory (OOM) errors.
Compression is a CPU-intensive task. To balance throughput with system stability, the default compression levels are tuned for efficiency:
- Gzip: Level 6
- Brotli: Level 4
These defaults prevent "CPU pinning" where a single request monopolizes processor cycles.
The processor automatically excludes files that are already compressed
(e.g., .gz, .br, .zip, .png). This prevents recursive
compression cycles and "Zip Bomb" style attacks that could lead to
exponential CPU and disk space consumption.
File fingerprinting uses MD5 hashing to match Django's
ManifestFilesMixin algorithm. This ensures consistency between
Django's hashed filenames and our minified filenames, allowing the
manifest to correctly map original files to their minified versions.
For production deployments with high security requirements:
MINICOMPRESS_MAX_FILE_SIZE = 2097152 # 2MB
MINICOMPRESS_MAX_FILES_PER_RUN = 500
MINICOMPRESS_COMPRESSION_LEVEL_GZIP = 6
MINICOMPRESS_COMPRESSION_LEVEL_BROTLI = 4For development environments with faster builds:
MINICOMPRESS_COMPRESSION_LEVEL_GZIP = 1
MINICOMPRESS_COMPRESSION_LEVEL_BROTLI = 0
MINICOMPRESS_BROTLI_COMPRESSION = False # Disable for faster buildsRequired:
- Django >= 4.2
- Python >= 3.10
brotli>= 1.0.0rjsmin>= 1.2.0rcssmin>= 1.1.0
BSD 3-Clause License. See LICENSE file for details.
Contributions are welcome! Please see the OpenWISP contributing guidelines for more information.