Bundles

A bundle is simply a collection of files that you would like to group together, with some properties attached to tell webassets how to do its job. Such properties include the filters which should be applied, or the location where the output file should be stored.

Note that all filenames and paths considered to be relative to the directory setting of your environment, and generated urls will be relative to the url setting.

Bundle('common/inheritance.js', 'portal/js/common.js',
       'portal/js/plot.js', 'portal/js/ticker.js',
       filters='jsmin',
       output='gen/packed.js')

A bundle takes any number of filenames, as well as the following keyword arguments:

  • filters - One or multiple filters to apply. If no filters are specified, the source files will merely be merged into the output file. Filters are applied in the order in which they are given.

  • merge - If True (the default), All source files will be merged and the result stored at output. Otherwise, each file will be processed separately.

  • output - Name/path of the output file. A %(version)s placeholder is supported here, which will be replaced with the version of the file. See URL Expiry (cache busting). If merge is True, this argument is required and you can also use these placeholders: - %(name)s Just the name of the source file, whithout path or extension (eg: ‘common’) - %(path)s The path and name of the source file (eg: ‘portal/js/common’) - %(ext)s The extension of source file (eg: ‘js’)

  • depends - Additional files that will be watched to determine if the bundle needs to be rebuilt. This is usually necessary if you are using compilers that allow @import instructions. Commonly, one would use a glob instruction here for simplicity:

    Bundle(depends=('**/*.scss'))
    

    Warning

    Currently, using depends disables caching for a bundle.

Nested bundles

Bundles may also contain other bundles:

from webassets import Bundle

all_js = Bundle(
    # jQuery
    Bundle('common/libs/jquery/jquery.js',
        'common/libs/jquery/jquery.ajaxQueue.js',
        'common/libs/jquery/jquery.bgiframe.js',),
    # jQuery Tools
    Bundle('common/libs/jqtools/tools.tabs.js',
        'common/libs/jqtools/tools.tabs.history.js',
        'common/libs/jqtools/tools.tabs.slideshow.js'),
    # Our own stuff
    Bundle('common/inheritance.js', 'portal/js/common.js',
        'portal/js/plot.js', 'portal/js/ticker.js'),
    filters='jsmin',
    output='gen/packed.js')

Here, the use of nested Bundle objects to group the JavaScript files together is purely aesthetical. You could just as well pass all files as a flat list. However, there are some more serious application as well. One of them is the use of CSS compilers. Another would be dealing with pre-compressed files:

If you are using a JavaScript library like jQuery, you might find yourself with a file like jquery.min.js in your media directory, i.e. it is already minified - no reason to do it again.

While I would recommend always using the raw source files, and letting webassets do the compressing, if you do have minified files that you need to merge together with uncompressed ones, you could do it like so:

register('js-all',
    'jquery.min.js',
    Bundle(filters='jsmin', 'uncompressed.js'))

Generally speaking, nested bundles allow you to apply different sets of filters to different groups of files, but still everything together into a single output file.

Some things to consider when nesting bundles:

  • Duplicate filters are only applied once (the leaf filter is applied).
  • If a bundle that is supposed to be processed to a file does not define an output target, it simply serves as a container of its sub-bundles, which in turn will be processed into their respective output files. In this case it must not have any files of its own.
  • A bundle with merge=False cannot contain nested bundles.

Building bundles

Once a bundle is defined, the thing you want to do is build it, and then include a link to the final merged and compressed output file in your site.

There are different approaches.

In Code

For starters, you can simply call the bundle’s urls() method:

>>> env['all_js'].urls()
('/media/gen/packed.js',)

Depending on the value of environment.debug. it will either return a list of all the bundle’s source files, or the merged file pointed to by the bundle’s output option - all relative to the environment.url setting.

urls() will always ensure that the files behind the urls it returns actually exist. That is, it will merge and compress the source files in production mode when first called, and update the compressed assets when it detects changes. This behavior can be customized using various environment configuration values.

Call urls() once per request, and pass the resulting list of urls to your template, and you’re good to go.

In templates

For some template languages, webassets includes extensions which allow you to access the bundles you defined. Further, they usually allow you to define bundles on-the-fly, so you can reference your assets directly from within your templates, rather than predefining them in code.

For example, there is a template tag for Jinja2, which allows you do something like this:

{% assets filters="cssmin,datauri", output="gen/packed.css", "common/jquery.css", "site/base.css", "site/widgets.css" %}
...

Management command

In some cases you might prefer to cause a manual build of your bundles from the command line. See Command Line Interface for more information.