facebook/reactMITd083ec1Report / request removal

Resource Hoisting & Preloading (Float)

ReactDOM’s resource APIs let application code announce DNS lookups, connections, preloads, and resource initialization without choosing whether the active renderer is the browser client, Fizz, or Flight. The public functions validate inputs, then forward valid requests through ReactDOMSharedInternals.d, the current dispatcher.

The same model handles hoistable DOM resources such as stylesheets and scripts. Client code caches and reuses matching nodes, while Fizz records resources and emits them through headers, head resources, or later stream chunks.

Sources: packages/react-dom/src/shared/ReactDOMFloat.js:49-51, packages/react-dom/src/shared/ReactDOMFloat.js:77-83, packages/react-dom/src/shared/ReactDOMFloat.js:113-147, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5962-5975, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6397-6424, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5724-5774

Core concepts

Resource hints

A resource hint is an early request such as DNS prefetching, preconnect, or preload; the public APIs forward these requests to dispatcher operations D, C, and L.

Sources: packages/react-dom/src/shared/ReactDOMFloat.js:49-51, packages/react-dom/src/shared/ReactDOMFloat.js:77-83, packages/react-dom/src/shared/ReactDOMFloat.js:123-147

Resource initialization

Resource initialization turns a preload-like announcement into an active style or script resource: preinit sends styles through S and scripts through X.

Sources: packages/react-dom/src/shared/ReactDOMFloat.js:230-261

Hoistable resource

A hoistable resource is a DOM-backed resource React can place outside the component’s ordinary position, cache, and reuse; acquisition searches for an existing matching node before creating one.

Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5962-5975

Stylesheet precedence

Stylesheet precedence is the grouping key used by Fizz and the ordering input passed to client stylesheet insertion.

Sources: packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:2999-3023, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6027-6029

Active dispatcher

The active dispatcher is stored in ReactDOMSharedInternals.d, which initially points to DefaultDispatcher.

The following flow shows the renderer boundary used by resource calls.

Resource calls reach the active renderer — How does a resource API call reach client, Fizz, or Flight?

Evidence

Sources: packages/react-dom/src/ReactDOMSharedInternals.js:46-50

How calls select client, Fizz, or Flight

prefetchDNS, preconnect, and preload validate arguments in development builds, forward valid calls through dispatcher slots, and treat the hints as optional rather than fatal operations.

Public operationDispatcher slotRenderer-side behavior
prefetchDNSDSends a DNS-prefetch request.
preconnectCSends a connection hint.
preloadLSends a resource preload with normalized options.
preinitS or XInitializes a style or script.

These operations and dispatcher slots are visible in the shared API implementation.

On the client, preconnect delegates to previousDispatcher.C and then calls preconnectAs. Client preload delegates to previousDispatcher.L, derives a selector or resource key, records properties in preloadPropsMap, and appends a missing link to ownerDocument.head.

Fizz records server-side state. Its preconnect deduplicates by resource key and credential bucket, writes a Link header when capacity permits, or stores a resource for later element emission. Its preload deduplicates image resources and chooses headers or head resources based on resource type, priority, and header capacity.

Flight uses request-local hint state. It constructs a key, skips duplicate hints, trims null options, and emits an L or C hint; when no request is active, it falls back to previousDispatcher.

Sources: packages/react-dom/src/shared/ReactDOMFloat.js:49-55, packages/react-dom/src/shared/ReactDOMFloat.js:77-86, packages/react-dom/src/shared/ReactDOMFloat.js:113-147, packages/react-dom/src/shared/ReactDOMFloat.js:49-51, packages/react-dom/src/shared/ReactDOMFloat.js:77-83, packages/react-dom/src/shared/ReactDOMFloat.js:123-147, packages/react-dom/src/shared/ReactDOMFloat.js:239-260, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5292-5295, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5297-5337, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5352-5376, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6335-6394, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6397-6424, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6426-6483, packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js:59-80, packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js:82-115, packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js:236-255

How client resources are deduplicated and blocked

Client preload identity is selector-based for arbitrary resource types, while styles and scripts use keys derived from their URLs. getStyleKey produces an href key, and stylesheet and script selectors use that key to find existing nodes.

When preinitStyle runs, it defaults missing precedence to default, checks the style cache, hydrates an existing stylesheet when possible, or creates a hoistable link with data-precedence. It records load and error state and inserts the stylesheet using that precedence.

When acquireResource handles a stylesheet, it increments the resource count, reuses a matching node when available, adopts properties from an earlier preload, creates a link otherwise, and inserts it through insertStylesheet.

The client host config exposes resource-specific commit hooks including mayResourceSuspendCommit, preloadResource, suspendResource, waitForCommitToBeReady, and checkIfFullyUnsuspended.

Client preload and acquisition — What happens when a client preload is followed by stylesheet acquisition?

Evidence

Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5869-5873, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5881-5883, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5948-5951, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5953-5955, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5439-5514, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5957-6030, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6564-6569, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6584-6595, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6665-6748, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6777-6846, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6870-6885

How Fizz orders and flushes head resources

A stylesheet with a string precedence and no disabled, onLoad, or onError is eligible for Resource semantics. Fizz groups resources in renderState.styles by precedence and creates a style queue containing precedence, rules, hrefs, and a sheets map. Conflicting properties cause the stylesheet to emit in place instead, although a preload resource may still be created. The validation helper describes the same boundary: these properties prevent React from hoisting or deduplicating the stylesheet.

Fizz’s writeHoistables flushes viewport chunks, preconnects, font preloads, and high-priority image preloads first. It then preloads stylesheet groups, emits scripts, emits bulk preloads, and finally writes ordinary hoistable chunks.

Fizz distinguishes shell flushing from later boundary flushing. During the shell, precedence stylesheets are already emitted in the head and therefore do not alone require suspense outlining; outside the shell, stylesheets or suspensey images can make content suspensey.

Fizz resource flush layers — Which resource groups flush early and which wait for later hoistable output?

Evidence

Sources: packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:2964-3023, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:2968-2997, packages/react-dom-bindings/src/shared/ReactDOMResourceValidation.js:10-40, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5724-5774, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:7132-7144

How it connects

Client resource insertion and suspension are host-config responsibilities, so this page connects to ReactDOM Host Config.

Server request state and streaming behavior belong with Server Rendering (Fizz), while renderer-agnostic Fizz machinery is covered by Fizz Server Internals.

The public resource hint surface connects to Public API Reference.

Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:6777-6846, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6397-6409, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5724-5774

Key takeaways

  • Public resource APIs dispatch through ReactDOMSharedInternals.d.
  • Client preloads are keyed, reused, and appended to ownerDocument.head only when missing.
  • Stylesheets with valid precedence participate in renderer-managed grouping; conflicting loading-control props opt them out.
  • Fizz flushes high-priority hints before stylesheets, scripts, bulk preloads, and ordinary hoistable chunks.
  • Client stylesheet resources carry load state that can participate in commit suspension.

Want this for your repos?

Try Angada AI Wiki