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 included in the initial HTML payload.
- JS (Script components) executes immediately when the browser parses the page.
app.jsprocesses this widget first, before any lazy widgets.
Best for: above-the-fold content, hero sections, navigation, anything the user sees immediately.
Lazy (loadingStrategy: "lazy")
The widget's HTML is still in the initial payload, but app.js defers loading its JS assets until after the page is interactive.
{
"id": "HelloMessage",
"type": "HelloMessage",
"loadingStrategy": "lazy"
} Behavior:
- HTML is rendered at build time and present in the initial HTML.
- JS assets are queued and loaded after all default (eager) widgets finish.
- The user sees the widget's HTML immediately, but interactivity arrives later.
Best for: below-the-fold sections that need HTML for SEO or first paint, but whose JS can wait.
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/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="__dynamicWidgetType__"is emitted. - At runtime, calling
gDom.loadDynamicComponent(id, callback)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 on page load | Automatic |
Lazy (loadingStrategy: "lazy") | Yes | After page is interactive | Automatic (deferred) |
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 HTML for SEO | Default or Lazy |
| Content that hurts initial page weight | 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.