Module

orchestration.asset

Asset processing orchestration for Bengal SSG.

Handles asset copying, minification, optimization, and fingerprinting. Coordinates parallel asset processing, generates asset manifest for cache-busting, and manages fingerprint cleanup.

Key Concepts:

  • Parallel processing: Concurrent asset processing for performance
  • Asset manifest: JSON manifest mapping logical paths to fingerprinted files
  • Fingerprinting: Hash-based cache-busting via filename suffixes
  • Cleanup: Removal of stale fingerprinted files

Related Modules:

  • bengal.core.asset: Asset representation and processing (package)
  • bengal.assets.manifest: Asset manifest generation
  • bengal.rendering.template_engine: Template access to asset manifest

See Also:

  • bengal/orchestration/asset.py: AssetOrchestrator for orchestration logic
  • plan/active/rfc-asset-fingerprinting.md: Asset fingerprinting design

Classes

AssetOrchestrator
Orchestrates asset processing for static files. Handles asset copying, minification, optimization,…
9

Orchestrates asset processing for static files.

Handles asset copying, minification, optimization, and fingerprinting. Supports parallel processing for performance and maintains CSS entry point cache for efficient incremental builds.

Creation:

Direct instantiation: AssetOrchestrator(site)
  • Created by BuildOrchestrator during build
  • Requires Site instance with assets populated

Attributes

Name Type Description
site

Site instance containing assets and configuration

logger

Logger instance for asset processing events

_cached_css_entry_points

Cached CSS entry points (invalidated on asset changes)

_cached_assets_id

Asset list identity for cache invalidation

_cached_assets_len

Asset list length for cache invalidation

Relationships
  • Uses: Asset class for asset representation and processing - Uses: AssetManifest for cache-busting manifest generation - Used by: BuildOrchestrator for asset processing phase - Uses: ThreadPoolExecutor for parallel asset processing Thread Safety: Thread-safe for parallel asset processing. Uses thread-safe locks for output operations and maintains thread-local state where needed.

Methods 1

process
Process and copy assets to output directory. CSS entry points (style.css) are …
3 None
def process(self, assets: list[Asset], parallel: bool = True, progress_manager: LiveProgressManager | None = None) -> None

Process and copy assets to output directory.

CSS entry points (style.css) are bundled to resolve @imports. CSS modules are skipped (they're bundled into entry points). All other assets are processed normally.

Parameters 3
assets list[Asset]

List of assets to process

parallel bool

Whether to use parallel processing

progress_manager LiveProgressManager | None

Live progress manager (optional)

Internal Methods 8
__init__
Initialize asset orchestrator.
1 None
def __init__(self, site: Site)

Initialize asset orchestrator.

Parameters 1
site Site

Site instance containing assets and configuration

_get_site_css_entries_cached
Return cached list of CSS entry points from the full site asset list. This avo…
0 list[Asset]
def _get_site_css_entries_cached(self) -> list[Asset]

Return cached list of CSS entry points from the full site asset list.

This avoids repeatedly filtering the entire site assets on incremental rebuilds when only CSS modules changed. We use a simple invalidation signal that is robust under dev-server rebuilds whereSite.reset_ephemeral_state()replaces site.assetsentirely:

  • If the identity (id) ofsite.assetschanges, invalidate
  • If the length changes, invalidate If either condition is met or cache is empty, recompute.
Returns

list[Asset]

_process_concurrently
Process CSS and other assets concurrently using a shared thread pool.
7 None
def _process_concurrently(self, css_entries: list[Asset], other_assets: list[Asset], minify: bool, optimize: bool, fingerprint: bool, progress_manager: LiveProgressManager | None, css_modules_count: int) -> None

Process CSS and other assets concurrently using a shared thread pool.

Parameters 7
css_entries list[Asset]
other_assets list[Asset]
minify bool
optimize bool
fingerprint bool
progress_manager LiveProgressManager | None
css_modules_count int
_process_sequentially
Process assets sequentially.
7 None
def _process_sequentially(self, css_entries: list[Asset], other_assets: list[Asset], minify: bool, optimize: bool, fingerprint: bool, progress_manager: LiveProgressManager | None, css_modules_count: int) -> None

Process assets sequentially.

Parameters 7
css_entries list[Asset]
other_assets list[Asset]
minify bool
optimize bool
fingerprint bool
progress_manager LiveProgressManager | None
css_modules_count int
_create_js_bundle
Create a bundled JavaScript file from individual JS modules. Uses pure Python …
2 Asset | None
def _create_js_bundle(self, js_modules: list[Asset], assets_cfg: dict[str, Any]) -> Asset | None

Create a bundled JavaScript file from individual JS modules.

Uses pure Python bundler (no Node.js dependency) to concatenate theme JavaScript files in the correct load order.

Parameters 2
js_modules list[Asset]

List of JS module assets to bundle

assets_cfg dict[str, Any]

Assets configuration dict

Returns

Asset | None

Asset representing the bundle.js file, or None if bundling fails

_process_css_entry
Process a CSS entry point (e.g., style.css) with bundling. Steps: 1. Bundle al…
4 None
def _process_css_entry(self, css_entry: Asset, minify: bool, optimize: bool, fingerprint: bool) -> None

Process a CSS entry point (e.g., style.css) with bundling.

Steps:

  1. Bundle all @import statements into single file
  2. Minify the bundled CSS
  3. Output to public directory
Parameters 4
css_entry Asset

CSS entry point asset

minify bool

Whether to minify

optimize bool

Whether to optimize (unused for CSS)

fingerprint bool

Whether to add hash to filename

_process_single_asset
Process a single asset (called in parallel).
5 None
def _process_single_asset(self, asset: Asset, assets_output: Path, minify: bool, optimize: bool, fingerprint: bool) -> None

Process a single asset (called in parallel).

Parameters 5
asset Asset

Asset to process

assets_output Path

Output directory for assets

minify bool

Whether to minify CSS/JS

optimize bool

Whether to optimize images

fingerprint bool

Whether to add fingerprint to filename

_write_asset_manifest
Persist an asset-manifest.json file mapping logical assets to final outputs.
1 None
def _write_asset_manifest(self, assets: list[Asset]) -> None

Persist an asset-manifest.json file mapping logical assets to final outputs.

Parameters 1
assets list[Asset]