Skip to main content

Enhanced ManifestStaticFilesStorage for Django

Project description

Django ManifestStaticFiles Enhanced

Enhanced ManifestStaticFilesStorage for Django.

AI tools were used for creation of this package

  • Tool(s) used: Claude Code
  • What it was used for: Used for building initial versions of all features and for initial versions of original tests.

Features

This package includes several improvements to Django's ManifestStaticFilesStorage:

  • ticket_27929: keep_original_files option to control whether original files are deleted after hashing
  • ticket_21080: CSS lexer for better URL parsing in CSS files
  • ticket_34322: JsLex for ES module support in JavaScript files
  • ticket_28200: Optimized storage to avoid unnecessary file operations for unchanged files
  • ticket_26329: Ensure production errors are rasied in development too
  • ticket_23517: Collect static files in parallel

Compatibility

  • Django: 4.2, 5.0, 5.1, 5.2
  • Python: 3.9, 3.10, 3.11, 3.12, 3.13

Installation

pip install django-manifeststaticfiles-enhanced

Usage

Basic Usage

Replace Django's default ManifestStaticFilesStorage with the enhanced version using the STORAGES setting:

# settings.py
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
    },
}

Add django_manifeststaticfiles_enhanced to your INSTALLED_APPS before contrib.staticfiles

# settings.py
INSTALLED_APPS = [
    ...
    "django_manifeststaticfiles_enhanced",
    "contrib.staticfiles",
    ...
]

Configuration Options

keep_original_files (ticket_27929)

Control whether original files are kept with the hashed file:

# settings.py - Keep original files (default)
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
        "OPTIONS": {
            "keep_original_files": True,  # Default
        },
    },
}

# Or discard original files to save space
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
        "OPTIONS": {
            "keep_original_files": False,
        },
    },
}

JavaScript Module Support (ticket_34322)

Enable ES module import/export processing:

# settings.py
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
        "OPTIONS": {
            "support_js_module_import_aggregation": True,
        },
    },
}

Easy access to existing options

Disable manifest_strict

# settings.py
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
        "OPTIONS": {
            "manifest_strict": False,
        },
    },
}

Also available:

  • manifest_name: change the name of the staticfiles.json file

--parallel command line option

By default the copying of files to the static folder uses 10 threads, this should be optimal for most projects but you can supply the --parallel option to add more workers if you have lots of files and fast io, or less workers if you have few files and slow io (NAS). Set --parallel to 1 to disable parallel collection.

Feature Details

CSS Processing Improvements (ticket_21080)

CSS URL processing uses a proper lexer instead of regex, providing:

  • Ignores url's in comments
  • More reliable URL extraction
  • Wider @import support

File Operation Optimization (ticket_28200)

Reduces unnecessary file operations during collectstatic:

  • Avoids recreating files that haven't changed
  • Checks file existence before deletion

JavaScript Module Support (ticket_34322)

JS import/export processing uses a proper lexer instead of regex, providing:

  • Covers ES6 import/export statements and dynamic imports
  • Ignores statements in comments and strings
  • Supports assert statements in imports, import sheet from './styles.css' assert { type: 'css' };

Example JavaScript that gets processed:

// Before processing
import { Component } from './component.js';
export { utils } from './utils.js';

// After processing (with hashing)
import { Component } from './component.abc123.js';
export { utils } from './utils.def456.js';

Option to not move the origianl asset to your static folder (ticket_27929)

Control file cleanup behavior:

# Keep original files (default)
keep_original_files = True
# Results in: style.css + style.abc123.css

# Delete original files
keep_original_files = False  
# Results in: style.abc123.css only

Ignoring specific errors

Ignore specific errors during post-processing with the ignore_errors option. This is useful when you have third-party libraries that reference non-existent files or use dynamic path construction that can't be properly parsed.

# settings.py
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
        "OPTIONS": {
            "ignore_errors": [
                # Format: "file_pattern:missing_url_pattern"
                "vendor/bootstrap/*.css:missing-font.woff",  # Ignore missing font in bootstrap CSS
                "vendor/es/*.js:*",  # Ignore all missing missing references in vendors ES version
                "*/*.css:../img/background.png"  # Ignore specific missing image in all CSS files
            ],
        },
    },
}

Patterns support wildcard matching with * to match any number of characters.

Catching common errors between development and production

The {% static %} tag does not use the manifest file in development, when DEBUG=True, instead it defaults to StaticFilesStorage. This can lead to errors that only show up in staging/production enviornments, because some static paths will work for StaticFilesStorage but not be valid paths in the manifest file and cause errors when DEBUG=False. This class adds extra validation when DEBUG=True so that the errors can be caught earlier. This package also includes a special storage class, TestingManifestStaticFilesStorage, for testing that uses StaticFilesStorage with the validation checks.

# settings.py for testing
STORAGES = {
    "staticfiles": {
        "BACKEND": "django_manifeststaticfiles_enhanced.storage.TestingManifestStaticFilesStorage",
    },
}

The TestingManifestStaticFilesStorage includes the DebugValidationMixin which performs the following validations:

  1. Rejects paths that start with / (e.g., /static/file.css)
  2. Rejects paths that use backslashes (e.g., path\to\file.css)
  3. Checks if the file actually exists in your static files
  4. Detects case sensitivity issues that might work in development but fail in production

Collect static files in parallel

  • Uses threadpool workers to speed up copying files from finders

Running Tests

# Install development dependencies
pip install -e .[dev]

# Run tests
python tests/runtests.py

# Or run specific test modules
python tests/runtests.py staticfiles_tests.test_storage

Migration from Django's ManifestStaticFilesStorage

This package is designed as a drop-in replacement:

  1. Install the package
  2. Update your STORAGES setting
  3. Add django_manifeststaticfiles_enhanced to INSTALLED_APPS above contrib.staticfiles
  4. Run python manage.py collectstatic as usual

All existing functionality remains the same, with additional features available through configuration options.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the BSD 3-Clause License - the same license as Django.

Changelog

0.7.0

  • Add collectstatic command with parallelization, which can be customized with --parallel option

0.6.0

  • Surface exceptions with {% static %} tag when DEBUG=True
  • Added TestingManifestStaticFilesStorage for use in tests to Surface exceptions when DEBUG=False

0.5.0

  • Made support of js import/export statements opt in

0.4.0

  • Added handling of circular dependencies in js/css files.

0.3.0

  • Added ignore_errors option to allow ignoring specific file reference errors during post-processing
  • Improved error handling to continue processing when errors are explicitly ignored

0.2.0

  • Performence improvements
  • Improved exception messages
  • Fixed issue with js dynamic imports that include template literals
  • Improved handling of soucerMapURLs

0.1.0 (Initial Release)

  • Includes keep_original_files option (ticket_27929)
  • Includes CSS lexer improvements (ticket_21080)
  • Includes file operation optimizations (ticket_28200)
  • Includes JavaScript module support (ticket_34322)
  • Added comprehensive test suite
  • Support for Django 4.2+

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_manifeststaticfiles_enhanced-0.7.4.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file django_manifeststaticfiles_enhanced-0.7.4.tar.gz.

File metadata

File hashes

Hashes for django_manifeststaticfiles_enhanced-0.7.4.tar.gz
Algorithm Hash digest
SHA256 414114a14edd9bf5eb843096e5f3f1221ff03a50fdedd10c105b5e2be8b12e7b
MD5 b19edd2735f26c83e8a96b19f5b2dab5
BLAKE2b-256 9a017231cc84768586408a5ec42c1a3b4cf761450670734f56f09fcb5d6b1cc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_manifeststaticfiles_enhanced-0.7.4.tar.gz:

Publisher: pypi-release.yml on blighj/django-manifeststaticfiles-enhanced

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_manifeststaticfiles_enhanced-0.7.4-py3-none-any.whl.

File metadata

File hashes

Hashes for django_manifeststaticfiles_enhanced-0.7.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ae5e0ec137166c69db33478d1bdfa5126e0fbccaeb3ca06672dee0e58c3995f9
MD5 c41dd94c00429f4b330c1e081ff05a7f
BLAKE2b-256 5917efc266ede6bf9882f306acedad5eb510e31e6ecb74a2543d20d85484bfb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_manifeststaticfiles_enhanced-0.7.4-py3-none-any.whl:

Publisher: pypi-release.yml on blighj/django-manifeststaticfiles-enhanced

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page