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.
Evidence
- public-apipackages/react-dom/src/shared/ReactDOMFloat.js:113
- shared-dispatcherpackages/react-dom/src/ReactDOMSharedInternals.js:46
- client-rendererpackages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5297
- fizz-rendererpackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:6397
- flight-rendererpackages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js:82
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 operation | Dispatcher slot | Renderer-side behavior |
|---|---|---|
prefetchDNS | D | Sends a DNS-prefetch request. |
preconnect | C | Sends a connection hint. |
preload | L | Sends a resource preload with normalized options. |
preinit | S or X | Initializes 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.
Evidence
- apipackages/react-dom/src/shared/ReactDOMFloat.js:113
- client-preloadpackages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5297
- preload-cachepackages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5324
- resourcepackages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5957
- headpackages/react-dom-bindings/src/client/ReactFiberConfigDOM.js:5366
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.
Evidence
- render-statepackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5724
- early-hintspackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5742
- stylesheet-groupspackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5751
- scriptspackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5760
- bulk-preloadspackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5765
- hoistable-chunkspackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5769
- head-streampackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5736
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.