Resources

Static assets are usually under the control of a developer and can be managed by Cubane’s resource management system.

For Cubane, a resource is any file (usually part of the website’s code repository) that needs to be processed when deploying a website onto a production system.

See also

In opposite to static assets, media is generally speaking content that was uploaded by an author and is part of the content of the website and not its codebase. Read more about media within the topic for Media.

Requirements

Cubane’s resource system requires Django’s staticfiles app. Please read more about how Django manages static files.

Note

It is important that django.contrib.staticfiles is loaded after cubane, because Cubane changes certain aspects of the runserver management command. Those overwrite would be invalidated by staticfiles, if the order is reversed.

When setting up settings.INSTALLED_APPS, please make sure that django.contrib.staticfiles is listing after cubane and not before.

You can also use Cubane’s Settings environment to setup installed apps, which will take care of this automatically for you.

What the Resource Management System does

Cubane’s resource management system allows you to define a list of static files per Django app. In your project settings, you can then define which app’s resources are combined into a named bucket.

All resource files that are listed for each app within a bucket are then combined into one resource file. Finally, that resource file is minified and combined with a unique version number for each deployment.

In your templates, you can include resources in different ways based on each named bucket. In debug mode, all resources are included as separate files; however, in production mode, there is usually only one file included per bucket and type of resource.

Declaring Resources

All resources for an app are defined by the array RESOURCES within the __init__.py file of your python package that is listed in your settings.INSTALLED_APPS. Let’s assume that we had an app called myApp, which defined the following resources:

RESOURCES = [
    'css/style.css',
    'print|css/print.css',

    'js/main.js',
]

Note

The order in which resource files are listed is important. Generally speaking, Cubane will process, combine and minify resources in the order as specified.

Further, you usually declare all your resources, even if they are of different type. Feel free to list all your CSS and Javascript resources together; Cubane will split resources by type later in the process automatically.

Because of the general layout of static assets managed by staticfiles behind the scenes, we may have organized those assets in the following structure:

myApp/
    static/
        myApp/
            css/
                style.css
                print.css
            js/
                main.js

Each resource within the RESOURCES array is declared relative to the location of the static files of myApp, which is myApp/static/myApp/.... In order for Cubane to process any resources, the app myApp must be installed in settings.INSTALLED_APP:

INSTALLED_APPS = [
    ...
    'myApp',
    ...
]

Declaring Resource Buckets

So far so good. Now, before we can include resources in our template, we first have to declare resource buckets and which app goes into which bucket:

In Cubane, you usually declare multiple resource buckets for different purposes: You may have a bucket for your front-end, then you might define another bucket that is inlined into the template because those resources need higher priority.

You may also have a print style as a separate file if you prefer to organise your print style that way.

Cubane’s backend system requires some style information as well and you certainly, do not want to mix this with your own front-end style.

For each bucket, Cubane will generate a separate file per resource type (for example CSS or Javascript), which can be included in a template differently.

You declare resource buckets in your application settings, for example:

RESOURCES = {
    'frontend': [
        'cubane.lightbox',
        'myApp'
    ],
    'inline': [
        'cubane.medialoader'
    ]
}

The named bucket frontend will include all resources from the apps cubane.lightbox and myApp combined, in that order.

Note

The order in which apps are listed is important. Generally speaking, Cubane will process, combine and minify all resources from all apps in the order as specified.

The bucket inline only contains the resources from only one app, which is cubane.medialoader. The media loader is responsible for lazy-loading images and is therefore given its own bucket in order to inline its code into the website markup directly for better performance. You can read more about Cubane’s media system within the Media section.

Note

The buckets backend and backend-inline are reserved for Cubane’s default backend system. Apart from those, you can declare as many buckets as you need. If those reserved buckets are declared, then their content is being added to the default resources that are loaded by the backend system.

For example, the following settings would load additional resources into the resource bucket that is used by the backend system.

RESOURCES = {
    'backend': [
        'myApp.backend_extensions'
    ]
}

Including Resources

After having declared all resource assets and buckets, we finally would need to refer to those assets. We do this by using Cubane’s resource_tags template library. The template library contains a set of template tags that can be used to embed resource buckets into your template in various ways. The following example should give you a good overview of how this works:

{% load resource_tags %}
<!DOCTYPE html>
<html>
    <head>
        ...

        <!-- inline CSS resources -->
        {% inline_resources 'inline' 'css' %}

        <!-- external CSS, you may want to inline above the fold css styles -->
        {% resources 'frontend' 'css' %}

        <!-- print resources -->
        {% resources 'frontend' 'css' 'print' %}
        {% resources 'inline' 'css' 'print' %}
    </head>

    <body>
        ...

        <!-- inline Javascript -->
        {% inline_resources 'inline' 'js' %}

        <!-- external Javascript, async -->
        {% resources 'frontend' 'js' %}
    </body>
</html>

As a typical base template, you would – generally speaking – load CSS resources at the top and Javascript resources at the bottom. For best performance, some CSS code is critical: For example, you would want to embed a good portion of your CSS to render the above the fold content within your template itself, rather than loading an external CSS file. Other resources are less critical and can be loaded from an external file asynchronously.

The following sections will guide you through the different ways of embedding resources.

Inline Resources

The inline_resources template tag will embed all resources from the given bucket and resource type within the template itself. Usually this means that Cubane will generate <style>...</style> markup for CSS and <script>...</script> markup for Javascript code.

An example:

{% inline_resources 'inline' 'css' %}
{% inline_resources 'inline' 'js' %}

The first argument is the name of the bucket. The second argument is the type of resources that should be embedded. This argument is required since there are different ways of how resources are embedded depending on the type of resources.

Tip

For best website performance, you should always split your stylesheet into critical CSS code that must be present to render everything above the fold and any remaining CSS code for styling other – less important – parts of your website.

Critical above the fold CSS code should be inlined if such code is not too heavy in size. Any other CSS code may be loaded from an external file.

In Production mode, all embedded resources will have been combined and minified before being embedded into the template at deployment time.

Note

In Debug mode, Cubane will never actually embed content within the template. When debugging CSS or Javascript code, it is much easier to use the browser’s development tools which can refer to actual files instead of referring to inline HTML code.

External CSS

External CSS code can be included with the resources template tag. Unlike the previous example, we are now instructing the browser to load additional resources from an external file.

An example:

<!-- css (screen only) -->
{% resources 'frontend' 'css' %}

<!-- css (print only) -->
{% resources 'frontend' 'css' 'print' %}

Unlike inline_resources, an additional argument may be provided that declares the CSS media type, such as screen or print. screen is assumed by default if this argument is not given.

Cubane will generate markup like <link href="..." rel="stylesheet" media="screen"> when including CSS resources using the resources template tag.

In Production mode, all resources from the named bucket will have been combined and minified into one file at deployment time. In Debug mode, Cubane will generate individual <link> tags, one for each resource file within the bucket.

You can instruct the browser to load a CSS resource asynchronously by adding the async argument like:

<!-- load css asynchronously -->
{% resources 'frontend' 'css' 'screen' 'async' %}

Loading CSS asynchronously currently relies on Javascript. Cubane will generate a bit of inline Javascript code that will instruct the browser to load the CSS resource without blocking the rendering of the website.

Note

Browsers are beginning to support a standard markup pattern for loading CSS (and other file types) asynchronously via <link rel="preload">.

External Javascript

Like loading external CSS files, you can use the same template tag resources to include external Javascript files as well, like in the following example:

<!-- external javascript, asynchronously -->
{% resources 'frontend' 'js' %}
{% resources 'frontend' 'js' True %}

<!-- external javascript, blocking -->
{% resources 'frontend' 'js' False %}

The first two lines are identical and will both instruct the browser to load an external Javascript file (representing the frontend bucket) asynchronously.

Note

All external Javascript code is loaded asynchronously by default.

The last line is loading the same external Javascript file by blocking the browser.

Declaring CSS Resources

CSS files are declared by simply referring to the path of one or multiple CSS files. Because CSS can target different media types, such as screen or print media, Cubane allows us to specify the type of media alongside each resource file:

RESOURCES = [
    'screen|css/screen1.css',
    'screen|css/screen2.css',
    ...
    'print|css/print1.css',
    'print|css/print2.css',
    ...
]

The media type if prefixed to the resource path by using the pipe character:

[<resource-prefix>] | <resource-path>

The prefix is optional. In the context of CSS files, screen is assumed if omitted. Therefore we could have written the following instead:

RESOURCES = [
    'css/screen1.css',
    'css/screen2.css',
    ...
    'print|css/print1.css',
    'print|css/print2.css',
    ...
]

In both cases, Cubane will combine the first two resource files for the media type screen and the remaining two resources for the media type print.

Note

For CSS, the order in which resource files appear in the list may matter; Cubane will combine and minify all CSS files within the same bucket and media type in the order as specified. If your CSS files need to appear in a specific order, then please make sure that this order is reflected when listing your resources.

When working with CSS, it is quite common to use a CSS reset style to unify the default browser style to a known and precise state, so that your own style can be defined on top it.

Usually, such CSS reset style is listed at the beginning of your resource list, followed by your own style files.

Tip

Alternatively, Cubane provides a default out of the box CSS reset style. Simply include the app cubane.cssreset within your list of installed Django apps like in the following example:

INSTALLED_APPS = [
    ...
    'cubane',
    'cubane.cssreset',
    'myApp',
    ...
]

The final step is to include all resources from cubane.cssreset within your resource bucket of choice, let’s assume that your website is using the frontend bucket:

RESOURCES = {
    'frontend': [
        'cubane.cssreset',
        'myApp',
    ],
    ...
}

Make sure that cubane.cssreset appears before your own app containing your own style, since the order in which CSS style information appears matters, in particular with CSS reset style.

Declaring Javascript Resources

Javascript files are declared by simply referring to the path of one or multiple Javascript files:

RESOURCES = [
    'js/lib/jquery.js',
    'js/main.js',
    ...
]

The order in which Javascript files are declared may be important. For example, if main.js would refer to JQuery, then you should make sure that the source for JQuery appears before main.js.

Declaring Font Resources

Web Fonts play an increasingly important role. Cubane provides an automatic process for including a large number of free web fonts within your websites.

Cubane provides a default font backend which is using the google-webfonts-helper by Mario Ranftl.

You can use any font (listed on the Google WebFonts Helper website) by simply including it as a resource within your app’s list of resources like in the following example:

RESOURCES = [
    'font|Open Sans',
    ...
]

And that’s it. In your CSS style, you can now use the font, for example:

body {
    font-family: 'Open Sans', sans-serif;
}

Cubane will automatically download all required font files to your local system and will also generate all required CSS style for the declaration of the font.

Note

When referring to fonts, make sure that the name of the font is given as listed on the Google WebFonts Helper website, otherwise, Cubane will not be able to locate the exact font.

Cubane’s font system allows for further customisation and extension which would go beyond the scope of this section. Please refer to the Fonts section for further information about Cubane’s font system.

Declaring Resources with Absolute Path

When declaring resources, you would usually use a relative path to refer to individual resource files, as in the following example:

RESOURCES = [
    'css/style.css'
    'js/main.js',
    ...
]

The path is considered to be a relative path because it does not start with a slash (/). Therefore the path is relative to the app that declared the list of resources. Let’s assume that your app is called myApp, then you may use the following directory structure for your static assets (remember that Cubane’s resource system requires Django’s staticfiles):

myApp/
    static/
        myApp/
            css/
                style.css
            js/
                main.js

The relative path css/style.css will be extended to /myApp/css/style.css, which will then refer to the correct file within the myApp app. Under the hood, Cubane will use Django’s staticfiles resolution mechanism to find static files in the described way.

Instead of specifying resource based on a relative path, you can specify resources by using an absolute path instead; starting with a slash (/):

RESOURCES = [
    '/myApp/css/style.css'

    '/myLib/js/jquery.js',
    '/myApp/js/main.js',
    ...
]

In this example, all resources are referred to by using absolute paths. An absolute path will not be prefixed automatically with the name of the app that declared those resources.

Instead, an absolute path is fed into Django’s staticfiles resolution mechanism directly. As long as the path assembles a valid path to a static asset for any installed Django app, this will work.

Note

Please consider to use absolute paths rarely and only if it makes your life so much easier. In most cases, we find that it is a good thing that each Django app is isolated from each other; by using absolute paths, you may create hidden dependencies between your apps.

We would advise to use absolute paths only if you need to and only if you do not intend to share your app with anyone else.

Declaring Media Resources

Usually, resources are assets that are part of the codebase and Django’s staticfiles requires those assets to be located within one specific folder per app, which is usually called static.

On the contrary, there is media, which is usually user-generated content, like images uploaded to the system etc. Such data is usually stored in one folder called media, which is not part of the code repository.

If you require assets that are downloaded from third-party sources and are of temporary nature, you may want to store such data within the media folder and not within the static folder, since the media folder is not part of the code repository.

If you wanted to serve those resources through the pipeline, then you can refer to those assets by referring to the media folder in the following way:

RESOURCES = [
    '/media/imgcache/tiles.css',
    ...
]

In this example, we assume that you have some process for caching CSS style information that is generated by a third party. Such data is stored in the media folder for reasons outlined above.

In order to include this resource in the build process, you can simply refer to the file via an absolute path to the media folder.

Declaring External Resources

Usually, resources would become part of your code base and you would always refer to local files; however, sometimes you would want to include resources from external web servers.

For this reason, resources can be declared by simply specifying an absolute URL, for example

RESOURCES = [
    'https://example.com/files/js/calendar.js',
    ...
]

In this example, the pipeline would automatically download the file /files/js/calendar.js from example.com at deployment time. The downloaded file would then become part of the resource bucket which is ultimately minified together with other javascript resources.

Pattern Expansion

Resources can be declared by using UNIX-style pathname pattern expansion. For example, instead of listing all CSS style files individually you could simply refer to all files with the extension .css instead:

RESOURCES = [
    # listing all resources individually:
    'css/components/header.css',
    'css/components/button.css',
    'css/components/carousel.css',
    'css/components/footer.css',

    # using pattern expansion instead:
    'css/components/*.css',
    ...
]

The first block is (almost) equivalent to the second block: While the first block refers to all style files individually, the second block simply refers to all CSS style files within a specific folder.

Cubane will automatically expand the pattern css/components/*.css into a list of individual file paths based on the expansion of the pattern. Each CSS file within the css/components folder will be listed in alphabetical order.

Note

When using pattern expansions, the resulting list of individual file paths is sorted alphabetically by default. If the order in which your resource files appear matters than it may not be appropriate to use pattern expansion.

However, there are a lot of cases where the order does not matter. For CSS style files for example, if you separated your style based on independent style components then the precise order in which they appear may not matter at all.

We would advise declaring individual files where the order matters and to use pattern expansion where the order of things does not matter.

Pattern expansion is particularly useful for SVG-based icons. You can read more about SVG-based icon sets within the SVG Icons section.

Resource Templates

In some cases, it can be useful to embed generated data or content into resource files. Cubane is using this concept in a number of places where this is required, for example, the media loader or the font system.

Basically, you can instruct Cubane to process any resource file through Django’s template system before serving the file. This would allow you to generate parts of the resource file dynamically based on data generated by your application.

We would not advise using this technique for implementing CSS themes or performing computation for CSS style in general for your website’s theme; there are far better solutions for pre-processing CSS style information.

However, for generating short bits of CSS style or generating constants based on your settings within your Javascript files, the template system might be exactly what you need.

First, you have to rename your asset file to include the reserved extension template, for example, main.js would become main.template.js.

RESOURCES = [
    # referring to a template instead of a static file will invoke
    # Django's template system...
    'js/main.template.js',
    ...
]

This is actually enough to invoke Django’s template system. In most cases, you would want to construct an additional template context for your template that contains some data required to render the template.

In your app’s __init__.py file, define a method called get_deploy_context() that returns a dictionary that is used as the template context for rendering any asset (of your app) via Django’s template system:

def get_deploy_context():
    return {
        'greetings': 'Hello World'
    }

Finally, in your main.template.js file, you can use Django’s template system to generate Javascript code dynamically.

var greetings = '{{ greetings }}';
...

In Debug mode, the runserver command will process templates as they are requested. For example, when the browser downloads the file /static/myApp/js/main.template.js, then the Django template system is invoked and the following result is returned to the browser:

var greetings = 'Hello World';
...

In Production mode, the template system is invoked only once, when the website is deployed. All static assets are generated at deployment time and the file main.template.js file actually contains the final result after the website has been deployed.

Using RequireJS

RequireJS is a Javascript file and module loader. If your Javascript code base is using RequireJS, Cubane can help you to automatically compile and minify your Javascript code as part of the site’s deployment.

For every RequireJS main javascript source file, you need to declare the following entry in your application’s settings file:

REQUIRE_JS = [
    {
        'filename': 'myProject/js/require_js_main.js',
        'baseurl': 'myProject/js',
        'module': 'require_js_main'
    }
]

The REQUIRE_JS settings variable declares a list of Javascript sources that are using RequireJS as a module loader.

filename

Required. For each source, the filename argument is required in order to provide the path to the main entry file for your RequireJS source.

baseurl

Optional. Root directory for every module search.

module

Optional. Name of the module as declared in your main javascript file.

See also

Please refer to the RequireJS Documentation <http://requirejs.org/docs/start.html> for more information on RequireJS.