# `Labs.prefetch`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Method of [`Labs`](Labs.md) · labs · since 2.0.0 · called as `session.labs.prefetch`

```ts
prefetch(nodes: readonly (string | DeepReadonly<ConfiguratorNode>)[], options?: SceneModelOptions): Promise<void>;
```

Fetches into the browser cache what a write naming these nodes would load on this device and
quality tier: a ModelNode with its active descendants; a MaterialNode's maps, using the
optimized twin where the runtime would. A string names a node of the current scene model; a
node object is one you are about to write (it need not be in the scene model yet), and its URLs
resolve as the [`setSceneModel`](Writer.setSceneModel.md) that adds it would (`assetBaseUrl` as in [`SceneModelOptions`](SceneModelOptions.md)).
Adds nothing to the scene and records nothing; skips assets already loaded. Resolves when the
files are cached; rejects AbortError on `signal`. For a shopper's intent (hover, focus, touch)
before a pick. Precedents: HTML `<link rel=prefetch>`, PlayCanvas `AssetRegistry.load` of an
asset not yet in the scene.
Its requests go through the automatic preload's scheduler (spec section 5.15): low priority,
at most 2 speculative requests in flight per session for both together, none started before
the first complete frame or while a required model or a picked material's maps load (a
started one finishes). With no scene model yet and none being written, the first frame after
boot is the first complete frame, so a prefetch awaited before the first [`setSceneModel`](Writer.setSceneModel.md)
settles. The sibling choice and its 8-asset cap don't limit the named nodes. A
write that needs a file still queued or downloading takes it over as required work, with no
second download. Aborting drops only this call's interest in its queued files.
A failed file (a network error or a non-success HTTP status) rejects HoloAssetError naming the
first file that failed, once the call's other files settle; it never resolves as cached. The
error's `problem` is the only record (no [`info().problems`](InfoReport.problems.md) entry, no 'problem' event, and the
failure window of spec section 6.4 doesn't start), files already cached stay cached, and a
later prefetch or write fetches the failed file again.

**Default:** options.signal undefined; options.assetBaseUrl the runtime's asset root

## Options

Through [`Session`](Session.md):

| Option | Type | Default | What it does |
| --- | --- | --- | --- |
| `assetBaseUrl` | `string` | the runtime's asset root | Absolute HTTP(S) directory for the model's GLB, try-on rig (`tryOnUrl`, `tryOnCandidateUrl`), texture and HDR URLs; any other value rejects… |
| `signal` | `AbortSignal` | undefined | Cancels this call; the member's JSDoc says what an abort does. |

Through [`Tx`](Tx.md):

| Option | Type | Default | What it does |
| --- | --- | --- | --- |
| `assetBaseUrl` | `string` | the runtime's asset root | Absolute HTTP(S) directory for the model's GLB, try-on rig (`tryOnUrl`, `tryOnCandidateUrl`), texture and HDR URLs; any other value rejects… |
| `signal` | `AbortSignal` | undefined | Cancels this call; the member's JSDoc says what an abort does. |

## Abort (`signal`)

This call is neither a write, a registration, a wait nor a creator (`SignalOption.signal`, [the kinds of call](../read-this-first.md#conventions)).

> Cancels this call; the member's JSDoc says what an abort does.

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/20-Labs.prefetch.ts`):

```ts
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const swatch: HTMLElement;
declare const optionId: string;
// warm an option's files on hover; forget it only when the prefetch rejects, so a file that
// failed is fetched again on the next hover
let warmed = false;
swatch.addEventListener('pointerenter', () => {
  if (warmed) return;
  warmed = true;
  session.labs.prefetch([optionId]).catch(() => (warmed = false));
});
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `prefetch` names no product |
| 2. A precedent | pass: [HTML <link rel="prefetch">](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/prefetch) (row `G56`) |
| 3. Two apps, or labs | labs: it graduates when a second app uses it; apps today: app-04c2774145, app-37356bf09f, app-378d190f1b, app-4762caacdc, app-4f16d2f6da, app-510d750508, app-59c5b5751e, app-b4ae2fce25, app-bcb7ef21da, app-ceb4eccc72, app-ddfb017681, app-f9a32142f1, app-fc07850558 |
| 4. The cheaper fix first | decided per need in Appendix B: rows `G56` at tier labs (a member only where no rule, data, asset or app code serves the need) |
