├── README.md
└── purgecss_filter.py
/README.md:
--------------------------------------------------------------------------------
1 | # Remove unused CSS classes with the PurgeCSS filter for Django Compressor
2 | PurgeCSS filter for Django Compressor removes unused CSS and makes your CSS files smaller. It automatically discovers all your template files and scans them for CSS classes then removes unused classes from your CSS files. Django Compressor also merges and minimizes your CSS files.
3 |
4 | ## Usage
5 |
6 | 1. Install [Django Compressor](https://django-compressor.readthedocs.io/en/stable/quickstart.html#installation), add `'compressor'` to your `INSTALLED_APPS`.
7 | 2. Add your styles inside Django compressor tags just like this:
8 | ```
9 | {% load compress %}
10 | {% compress css %}
11 |
12 |
13 |
14 |
15 | {% endcompress %}
16 | ```
17 | 3. Install [PurgeCSS](https://purgecss.com/getting-started.html) and make `purgecss` CLI command available globally with this command: `npm i -g purgecss`
18 | 4. Copy `purgecss_filter.py` file to your Django app, for example, to an app folder.
19 | 5. Add the filter to the Django Compressor filter setting in `settings.py`:
20 | ```
21 | COMPRESS_FILTERS = {'css': ['YOUR_APP_NAME.purgecss_filter.PurgeCSSFilter', 'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.cssmin.rCSSMinFilter'], 'js': ['compressor.filters.jsmin.rJSMinFilter']}
22 | ```
23 | Replace YOUR_APP_NAME in the line above with the app name where you placed `purgecss_filter.py`.
24 |
25 | 6. *(optional)* Turn on CSS compression when `DEBUG = True` by adding `COMPRESS_ENABLED = True` to `settings.py`.
26 |
27 | ## If you would like to use it with SCSS files
28 |
29 | Install and configure [django-libsass](https://github.com/torchbox/django-libsass).
30 |
31 | ## If the filter removes some classes that are actually in use
32 |
33 | This may happen when you have some dynamically loaded classes from JS, Python code, or when you use some classes in your content that don't exist in templates. You can fix this by adding an argument to PurgeCSS to whitelist CSS classes that should not be removed:
34 | ```
35 | COMPRESS_PURGECSS_ARGS = "--safelist Class-name1 Class-name2 Class-name3"
36 | ```
37 | By default, the filter doesn't scan third-party installed apps for templates, but you can include these templates as well with this setting:
38 | ```
39 | COMPRESS_PURGECSS_APPS_INCLUDED = [
40 | 'allauth',
41 | 'crispy',
42 | ...
43 | ]
44 | ```
45 |
--------------------------------------------------------------------------------
/purgecss_filter.py:
--------------------------------------------------------------------------------
1 | from compressor.filters import CompilerFilter
2 | from django.conf import settings
3 | from pathlib import Path
4 | from django.template.loaders.app_directories import get_app_template_dirs
5 |
6 |
7 | COMPRESS_PURGECSS_BINARY = "purgecss"
8 | COMPRESS_PURGECSS_ARGS = ""
9 | COMPRESS_PURGECSS_APPS_INCLUDED = []
10 |
11 |
12 | class PurgeCSSFilter(CompilerFilter):
13 | command = '{binary} --css {infile} -o {outfile} {args}'
14 | options = (
15 | ("binary",
16 | getattr(
17 | settings,
18 | "COMPRESS_PURGECSS_BINARY",
19 | COMPRESS_PURGECSS_BINARY)),
20 | ("args",
21 | getattr(
22 | settings,
23 | "COMPRESS_PURGECSS_ARGS",
24 | COMPRESS_PURGECSS_ARGS)),
25 | )
26 |
27 | def __init__(self, *args, **kwargs):
28 | super().__init__(*args, **kwargs)
29 | template_files = " ".join(self.get_all_template_files())
30 | self.command += " --content {}".format(template_files)
31 |
32 | def get_all_template_files(self):
33 | files = []
34 | apps = getattr(settings, "COMPRESS_PURGECSS_APPS_INCLUDED", COMPRESS_PURGECSS_APPS_INCLUDED)
35 | dirs = get_app_template_dirs('templates')
36 | for d in dirs:
37 | if 'site-packages' in str(d):
38 | for app in apps:
39 | if app in str(d):
40 | for f in Path(d).glob('**/*.html'):
41 | files.append(str(f))
42 | else:
43 | for f in Path(d).glob('**/*.html'):
44 | files.append(str(f))
45 | return files
46 |
--------------------------------------------------------------------------------