/django-compressor-requirejs

Compress requirejs-modules into bundles.

Primary LanguagePythonMIT LicenseMIT

django-compressor-requirejs

Precompiler for django-compressor to integrate RequireJS-modules into bundles.

This library does not use the r.js compressor, but instead collects the dependencies from your templates and resolves them into bundles, letting django-compressor do the compressing.

Installation

First, install django-compressor into your Django project and configure it. Then install django-compressor-requirejs:

pip install django-compressor-requirejs

and add requirejs.RequireJSCompiler to your COMPRESS_PRECOMPILERS setting:

COMPRESS_PRECOMPILERS = (
    ('text/requirejs', 'requirejs.RequireJSCompiler'),
)

You can now use the content type text/requirejs on your main RequireJS script tag:

{% compress js %}
    <script type="text/requirejs" src="{% static "website/js/libs/require.min.js" %}"></script>
{% endcompress %}

The library will by default generate a single bundle with all modules found in templates and their dependencies. Dynamic dependencies will not be found. It also sets the baseUrl to your STATIC_URL.

If COMPRESS_ENABLED is False, only the config will be added and RequireJS will load modules one by one, without bundles.

Settings

You can control RequireJS with three settings:

  • REQUIREJS_CONFIG is a Python-representation of the RequireJS config object. This will be used as a base for the final configuration generated with the RequireJS-source. Within this dict, the paths, shim and bundles keys will be used to find and process modules in to bundles. Their syntax is the same as in RequireJS.
    • paths will be used to search on disk. Useful to map "jquery" and other modules which should be available on a fixed path.
    • shim will be respected when creating bundles. Shims will not be bundled since RequireJS needs to keep track of them.
    • bundles specifies which bundles will be created. Every module not mentioned in this setting will end up in the main catch-all bundle.
  • REQUIREJS_APP_ALIAS (default None) allows the Javascript directory inside your static root to be addressed by just the app name. Require/define calls to website/some_module will be searched as {{ STATIC_URL }}/website/<alias>/some_module.js if not found in {{ STATIC_URL }}/website/.
  • REQUIREJS_INCLUDE_MAIN_BUNDLE (default False) will make the plugin include the main bundle instead of generating a bundle for it which needs to be fetched.

RequireJS config outside of Django

The REQUIREJS_CONFIG setting is used as the base for your RequireJS configuration and will be written just before the RequireJS JavaScript source. If you want to extend the config in your templates instead of the Django settings, you need to use require.config({..}) after the main tag:

{% compress js %}
    <script type="text/requirejs" src="{% static "website/js/libs/require.min.js" %}"></script>
    <script type="text/javascript">
       require.config({
           // ...
       });
    </script>
{% endcompress %}

Under the hood

django-compressor-requirejs makes use of RequireJS's bundles configuration option, making it possible to bundle modules together and let RequireJS fetch the bundle when it needs one of the modules. The philosophy is that modules bundled together are really often used together, which lowers the amount of requests the browser has to do.

It uses the filter mechanism in django-compressor on the script tag used to load RequireJS itself, injecting a configuration pointing RequireJS to STATIC_URL and -- if compression is enabled -- the compressed bundle(s).

Discovery of modules is done by searching all template directories for calls to RequireJS and parsing their dependencies. This is a plain text search, no real parsing of Javascript or HTML is done (similar to makemessages). All found modules are then similarly scanned for their dependencies.

Since no parsing or evaluation is done, any dynamic loading of dependencies with variables is not supported. If you want to let django-compressor-requirejs pick it up, annotate the require() call with all options (if feasible, of course).

So django-require and compressor_requirejs exist.

Yes, they do; and if you want to use the (otherwise excellent) r.js compressor with django-compressor, please take a look at compressor_requirejs. And if you do not use django-compressor, visit etianen's django-require.