Loading Strategies
Streak.js offers three ways to control when a widget's HTML and JS reach the browser. Each strategy trades off initial payload size against time-to-interactive.
Default (No loadingStrategy)
When a widget has no loadingStrategy field in the sitemap, both its HTML and JS are part of the initial page load.
{
"id": "HelloBanner",
"type": "HelloBanner"
} Behavior:
- HTML is rendered at build time and inlined directly into the page.
- Its
Scripttags are inlined too, and execute immediately as the browser parses the page. - The client runtime never has to fetch this widget at all — it's not listed in the page's
w-mregistry.
Best for: above-the-fold content, hero sections, navigation, anything the user sees immediately.
Lazy (loadingStrategy: "lazy")
The widget's HTML and JS are rendered at build time but held out of the initial payload. A small placeholder ships instead, and Streak's client runtime fetches and swaps in the real content right after page load.
{
"id": "HelloMessage",
"type": "HelloMessage",
"loadingStrategy": "lazy"
} Behavior:
- HTML is rendered at build/render time but stored separately, not inlined into the page.
- A placeholder element (
component-type="w") ships in its place, and the widget's id is added to the page'sw-mregistry. - On page load, the client runtime calls
gDom.addWidgetToBody(id)for each lazy widget id inw-m, in order — fetching and injecting one widget's HTML/scripts before moving to the next.
Best for: below-the-fold sections that don't need to be part of the very first paint.
Dynamic Component
Content is removed from the initial HTML entirely. A placeholder element is rendered instead, and the content is injected on demand via gDom.loadDynamicComponent().
import { Dynamic, Script } from "streak-forge/components";
<Dynamic id="nav-submenu">
<ul>
<li>Item A</li>
<li>Item B</li>
</ul>
</Dynamic>
<Script id="nav-submenu-trigger">
{(gDom: any) => {
document.getElementById("nav-btn")
?.addEventListener("click", () => {
gDom.loadDynamicComponent("nav-submenu", () => {
console.info("submenu injected");
});
});
}}
</Script> Behavior:
- At build time, children are stripped from the HTML. A placeholder with
component-type="c"is emitted. - At runtime, calling
gDom.loadDynamicComponent(id, callback)fetches and injects the content into the placeholder. - Nothing loads until your code explicitly triggers it.
Best for: modals, menus, overlays, or any content that should not be in the initial HTML payload.
Comparison Table
| HTML in initial payload | JS loaded | Triggered by | |
|---|---|---|---|
Default (no loadingStrategy) | Yes | Immediately, inline with the page | Automatic |
Lazy (loadingStrategy: "lazy") | No — placeholder only | Fetched and injected after page load | Automatic (w-m registry) |
Dynamic (<Dynamic> component) | No | On demand | gDom.loadDynamicComponent() |
When to Use Which
| Scenario | Strategy |
|---|---|
| Hero banner, primary navigation, LCP content | Default |
| Footer, testimonials section, analytics scripts | Lazy |
| Modal dialogs, dropdown menus, accordion panels | Dynamic |
| Content that must be in the initial HTML for SEO | Default |
| Content that can arrive just after load, or only on interaction | Lazy or Dynamic |
A single page can mix all three strategies. Use default for critical above-the-fold widgets, lazy for visible-but-non-urgent sections, and dynamic for content that only appears on interaction.