Static pipeline#
This page covers how the static subsystem discovers assets, collects them per request, deduplicates them, and emits the final HTML through the configured backend.
Overview#
The static pipeline runs entirely per request.
AssetDiscovery walks the page and component trees on each render, builds StaticAsset records, and feeds them to the request StaticCollector.
Discovery and injection#
flowchart LR
subgraph Request["Request"]
Walk["Filesystem walk"] --> StemMatch["Match stem and extension"]
StemMatch --> Discovery["AssetDiscovery"]
Discovery --> Collector["StaticCollector"]
end
Collector --> Dedup["Dedup strategy"]
Dedup --> Backend["StaticFilesBackend"]
Backend --> Tags["Render link or script tags"]
Tags --> HTML["Final HTML"]
Collector slots#
The collector keeps assets in named slots, one per registered slot, each backed by a placeholder token in templates.
Each slot matches the collector slot term in Glossary.
flowchart TB
Trigger["Layout, page, or component renders"] --> Route["Route to slot named by KindRegistry.slot(kind)"]
Route --> Slot["Slot, for example styles or scripts"]
Slot --> Finalize["collector_finalized"]
Finalize --> Emit["collect tag for each slot"]
Emit --> Injected["html_injected"]
Runtime script injection#
Under the AUTO script injection policy the static manager wraps the rendered page with the next.min.js runtime through NextScriptBuilder.
flowchart LR
JsContext["JS context values"] --> Builder["NextScriptBuilder"]
Builder --> Preload["Preload hint before </head>"]
Builder --> Runtime["next.min.js script tag"]
Builder --> Init["Inline Next._init payload"]
Preload --> Wrapped["Wrapped HTML"]
Runtime --> Wrapped
Init --> Wrapped
See JavaScript context for the ScriptInjectionPolicy values, the three injected fragments, and the NEXT_JS_OPTIONS keys.
Modules#
next.static.discovery.AssetDiscoverywalks the filesystem and producesStaticAssetrecords. HostsStemRegistryplus thedefault_stemsinstance and reads thedefault_kindsregistry fromnext.static.assets.default_stemsis not re-exported from thenext.staticpackage surface, so code that registers a stem imports it fromnext.static.discoverydirectly.next.static.assets.The
StaticAssetfrozen dataclass andKindRegistryplus thedefault_kindsinstance.next.static.collector.StaticCollectorplus the dedup strategiesUrlDedup,HashContentDedup,IdentityDedupand the JS context policies. Also holdsPlaceholderSlot,PlaceholderRegistry, and thedefault_placeholdersinstance.next.static.backends.StaticBackendabstract base class plus the bundledStaticFilesBackend. Instances come fromload_backends, the shared loader every backend family uses.next.static.manager.StaticManagerorchestrates discovery and the per request collector lifecycle.next.static.scripts.NextScriptBuilderandScriptInjectionPolicyfor theNextruntime script.next.static.serializers.JsContextSerializerprotocol plusJsonJsContextSerializerandPydanticJsContextSerializer.next.static.finders.NextStaticFilesFinderexposes co-located page and component assets to Django staticfiles, socollectstaticcopies them intoSTATIC_ROOT. Static assets overview covers the finder from the user side.next.static.defaults.register_defaultsregisters the built incss,js, andmodulekinds and thestylesandscriptsslots.
Asset kinds#
Each kind maps an extension to a placeholder slot and a backend renderer method.
The renderer name is a plain string the manager looks up with getattr on the active static backend per asset, so a backend supplies a renderer by exposing a method of that name.
Asset kinds lists the bundled kinds and their renderer methods.
Dedup#
The collector holds one dedup strategy for the request.
The strategy is selected by the dotted path under the DEDUP_STRATEGY key of the first static backend OPTIONS, instantiated once per request, defaulting to UrlDedup when the key is absent.
Deduplication covers the bundled strategies and the custom-strategy protocol.
Signals#
The pipeline fires four signals.
asset_registeredfires once per co-located file registered through a backend. Module-levelstylesandscriptslists and inline{% #use_script %}and{% #use_style %}blocks callcollector.adddirectly and do not emit it.collector_finalizedonce per request after the collector closes its set.html_injectedonce per request after the manager replaces the placeholder slots.backend_loadedonce per backend instance when the manager builds it, including the staticfiles backend it seeds when no entry survives.
A standalone zone render runs the same discovery but ships the collected assets in the patch envelope, so collector_finalized and html_injected fire only on full-page renders.
Extension points#
Subclass
StaticFilesBackendto change the rendered output.Implement the
DedupStrategyprotocol and pointDEDUP_STRATEGYat it.Call
default_kinds.registerinAppConfig.readyto recognise a new extension.Call
default_stems.registerinAppConfig.readyto recognise a new filename.Subscribe to
collector_finalizedto inspect the collected set.
See also#
See also
Static assets for the topic subtree. Request lifecycle for where the pipeline runs.