django-critical

https://badge.fury.io/py/django-critical.png https://travis-ci.org/martinblech/django-critical.png?branch=master https://coveralls.io/repos/martinblech/django-critical/badge.png?branch=master

Inlines critical path CSS and defers loading full CSS asynchronously.

Documentation

The full documentation is at https://django-critical.readthedocs.org.

Quickstart

  • Install django-critical:

    pip install django-critical
    
  • Add critical to your INSTALLED_APPS setting:

    INSTALLED_APPS = (
        # other apps
        "critical",
    )
    
  • Add critical.middleware.CriticalCssMiddleware to your MIDDLEWARE_CLASSES setting:

    MIDDLEWARE_CLASSES = (
        # other middlewares
        "critical.middleware.CriticalCssMiddleware",
    )
    
  • Point your CRITICAL_PENTHOUSE_PATH setting to the correct path, e.g.:

    CRITICAL_PENTHOUSE_PATH = os.path.join(
        BASE_DIR, 'node_modules/penthouse/penthouse.js')
    
  • If phantomjs is not in your PATH, you have to set CRITICAL_PHANTOMJS_PATH and point it to your phantomjs binary:

    CRITICAL_PHANTOMJS_PATH = os.path.join(
        BASE_DIR, 'node_modules/phantomjs/bin/phantomjs')
    

How it works

django-critical is activated by adding {% load critical %} to your template.

django-critical then parses the HTML between {% critical %} and {% endcritical %} and searches for CSS.

{% critical %}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<style>
  .jumbotron h1 {
    color: red;
  }
</style>
{% endcritical %}

It downloads and concatenates all that CSS and uses penthouse to extract the critical path CSS rules from it, which end up inlined and minified in place of the original CSS.

<style>html{font-family:sans-serif;-webkit-text-size-adjust:100%…</style>

Later in the HTML, before the closing </body> tag, the {% critical_async %} template tag takes care of loading the rest of the CSS using FilamentGroup’s loadCSS.

Caching

django-critical calculates the critical path CSS for the first request, caches the result and reuses this CSS verbatim for further requests. Most web applications have different critical path CSS for different groups of pages, though. This can be solved using the {% critical_key "<key>" %} template tag, so that different templates can have different caching keys.

Is this stable and ready for production use?

No. django-critical is in a very early stage of development, so you should use it at your own risk. Bug reports and contributions are welcome, though!