Esc

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 Script tags 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-m registry.

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's w-m registry.
  • On page load, the client runtime calls gDom.addWidgetToBody(id) for each lazy widget id in w-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 payloadJS loadedTriggered by
Default (no loadingStrategy)YesImmediately, inline with the pageAutomatic
Lazy (loadingStrategy: "lazy")No — placeholder onlyFetched and injected after page loadAutomatic (w-m registry)
Dynamic (<Dynamic> component)NoOn demandgDom.loadDynamicComponent()

When to Use Which

ScenarioStrategy
Hero banner, primary navigation, LCP contentDefault
Footer, testimonials section, analytics scriptsLazy
Modal dialogs, dropdown menus, accordion panelsDynamic
Content that must be in the initial HTML for SEODefault
Content that can arrive just after load, or only on interactionLazy 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.