FrançaisPlayground

Loading strategies

resolve says where a component comes from. load: says when its code should be fetched.

They are separate because they vary independently. Where <RevenueChart> lives is the same everywhere and belongs in config; whether this particular usage should wait for the viewport is a property of the usage.

<Summary total={total()} />                    {/* eager — entry chunk */}
<ExportDialog load:interaction />              {/* own chunk, on first interaction */}
<AuditLog load:media="(min-width: 1024px)" />  {/* own chunk, desktop only */}
<RevenueChart load:visible="200px" />          {/* own chunk, just before it scrolls in */}

No import, no lazy(), no wrapper component. The compiler emits the dynamic import and the deferred binding.

The strategies

Directive When the module is fetched
load:eager Immediately, in the parent chunk. The default.
load:idle When the browser goes idle.
load:visible When the element approaches the viewport.
load:interaction On first interaction with the element.
load:media When a media query matches.
load:never Never — no client code at all.

load:visible

Takes an optional margin, passed through as the observer's rootMargin:

<RevenueChart load:visible />          {/* on intersection */}
<RevenueChart load:visible="200px" />  {/* 200px early */}

Prefer the margin. Starting the fetch exactly on intersection means the user watches a blank space while the network works.

load:interaction

Defaults to pointerdown, focusin and keydown — the three that reliably precede a real interaction, keyboard and pointer alike. Name your own to narrow it:

<ExportDialog load:interaction />
<ExportDialog load:interaction="pointerdown" />

load:media

The query is required, since there is no sensible default:

<AuditLog load:media="(min-width: 1024px)" />

load:never

A statement that the component has no place in the client bundle at all — server-rendered output only. Unlike the others this is not about timing, so it is never collapsed away (below), and pairing it with an eager usage of the same module is reported as the contradiction it is.

The strategy has to be static

load: is read at compile time, because it decides how the module is emitted. A runtime value cannot answer that, so a ${…} hole is rejected rather than silently ignored.

Deferring nothing is not free

If a module is already in the parent chunk — because something else uses it eagerly — then deferring it elsewhere buys nothing and costs a wrapper, a promise and a re-render. The compiler notices and demotes those references back to eager.

Collapsing happens per module, not per component name: <Button> eager and <ButtonGroup load:visible> from the same package means the package is already loaded, so deferring the second is pointless.

Verifying it

Rendering passes either way, so an assertion has to be about the build output — which chunk each component landed in. examples/load-strategies in the repository does exactly that: it runs a real build and checks that the three deferred components are in their own chunks and absent from the entry.