Asset registry

A feature declares the stylesheets and scripts it ships, and the public shell renders every declared asset, deduplicated and in a fixed order. The page’s CSS and JS are composed from the installed features, with no <link> or <script> tag written into a hook or a template.

Features register assets, the registry orders them, the shell renders them INIT_FEATURE REGISTERS REGISTRY THE SHELL RENDERS Theme base order=0 Each feature order=100 Skin order=200 asset_registry Sorted by order, then endpoint Deduplicated by kind, endpoint, params get_assets('css') a <link> each, in <head> get_assets('js') deferred, before </body>
Install a feature that registers an asset and its tag appears. Remove it and derive again, and the tag is gone.

How it works

  • A feature ships the file under its blueprint’s assets/ folder, which the blueprint’s asset route serves, and registers it from init_feature(app).
  • The registry, splent_framework.assets.asset_registry, keeps every registration of the app and hands the theme the URLs in order.
  • The set of assets follows the set of installed features, so there is no product-level list of stylesheets to keep.

register_asset

The slider ships slider.css and slider.js like this.

from splent_framework.blueprints.base_blueprint import create_blueprint
from splent_framework.services.service_locator import register_service

from splent_io.splent_feature_slider.services import SliderService

slider_bp = create_blueprint(__name__)

def init_feature(app):
    from splent_framework.assets.asset_registry import register_asset

    register_service(app, "SliderService", SliderService)
    register_asset("css", "slider.assets", order=100, subfolder="css", filename="slider.css")
    register_asset("js", "slider.assets", order=100, subfolder="js", filename="slider.js")
Parameter Required Description
kind yes "css" or "js".
endpoint yes The blueprint’s asset route, for instance "slider.assets".
order no Load order, lower first. Defaults to 100. See Order.
shell no Keyword only. The shell that loads it, "public" (the default), "app" or "both". See Assets per shell.
**params no url_for parameters for the asset route, such as subfolder="css" and filename="slider.css".

A registration is idempotent. The registry keys it by (kind, endpoint, params), so registering the same asset twice emits one tag. The first registration keeps its order, and registering the asset again for the other shell makes it serve both.

Two companion functions exist, and you rarely call them yourself.

  • get_assets(kind, shell="public") returns the URLs of one kind registered for that shell and those registered for "both", deduplicated and ordered by (order, endpoint). shell is keyword only and takes "public" or "app", the shell rendering the page. Each carries a ?v=<file mtime> suffix, so an edited stylesheet is fetched again. url_for already adds that suffix to every asset URL, and the registry leaves such a URL as it is. A versioned asset is cached by the browser for a year (see Versioned assets). url_for runs when it is called, so call it from a template, inside a request. An asset whose route cannot be resolved is skipped without an error. It is a Jinja global, and the theme uses it.
  • clear_assets() empties the registry. The framework calls it per app (see Cleared per app).

Order

order decides the cascade.

Layer order Loads
Theme base about 0 first, lowest priority
Features about 100 in the middle
Skins about 200 last, highest priority

A skin registers its stylesheet, skin_<name>.css (for instance skin_arcade.css), with order=200, so it loads after every feature’s CSS and can override it. Features keep the default 100.

In the theme

The public shell, public_base.html in the theme, renders the CSS in the <head>.

{% for href in get_assets('css') %}<link rel="stylesheet" href="{{ href }}">{% endfor %}

The JS goes just before </body>, deferred.

{% for src in get_assets('js') %}<script defer src="{{ src }}"></script>{% endfor %}

Cleared per app

The framework’s FeatureManager calls clear_assets() in register_features(), before it loads a product’s features, as it does for the navigation registry. The registry holds only the assets of this product’s installed features, so a product emits only the CSS and JS it uses.


See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es