mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[Static][Fizz] Carry forward bootstrap config to resume if postponing in the shell (#27672)
Previously it was possible to postpone in the shell during a prerender and then during a resume the bootstrap scripts would not be emitted leading to no hydration on the client. This change moves the bootstrap configuration to `ResumableState` where it can be serialized after postponing if it wasn't flushed as part of the static shell.
This commit is contained in:
@@ -245,6 +245,13 @@ export type ResumableState = {
|
||||
nextFormID: number,
|
||||
streamingFormat: StreamingFormat,
|
||||
|
||||
// We carry the bootstrap intializers in resumable state in case we postpone in the shell
|
||||
// of a prerender. On resume we will reinitialize the bootstrap scripts if necessary.
|
||||
// If we end up flushing the bootstrap scripts we void these on the resumable state
|
||||
bootstrapScriptContent?: string | void,
|
||||
bootstrapScripts?: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
bootstrapModules?: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
|
||||
// state for script streaming format, unused if using external runtime / data
|
||||
instructions: InstructionState,
|
||||
|
||||
@@ -349,9 +356,6 @@ const DEFAULT_HEADERS_CAPACITY_IN_UTF16_CODE_UNITS = 2000;
|
||||
export function createRenderState(
|
||||
resumableState: ResumableState,
|
||||
nonce: string | void,
|
||||
bootstrapScriptContent: string | void,
|
||||
bootstrapScripts: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
bootstrapModules: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
|
||||
importMap: ImportMap | void,
|
||||
onHeaders: void | ((headers: HeadersDescriptor) => void),
|
||||
@@ -367,6 +371,8 @@ export function createRenderState(
|
||||
|
||||
const bootstrapChunks: Array<Chunk | PrecomputedChunk> = [];
|
||||
let externalRuntimeScript: null | ExternalRuntimeScript = null;
|
||||
const {bootstrapScriptContent, bootstrapScripts, bootstrapModules} =
|
||||
resumableState;
|
||||
if (bootstrapScriptContent !== undefined) {
|
||||
bootstrapChunks.push(
|
||||
inlineScriptWithNonce,
|
||||
@@ -612,9 +618,6 @@ export function resumeRenderState(
|
||||
return createRenderState(
|
||||
resumableState,
|
||||
nonce,
|
||||
// These should have already been flushed in the prerender.
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
@@ -625,6 +628,9 @@ export function resumeRenderState(
|
||||
export function createResumableState(
|
||||
identifierPrefix: string | void,
|
||||
externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
|
||||
bootstrapScriptContent: string | void,
|
||||
bootstrapScripts: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
bootstrapModules: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
): ResumableState {
|
||||
const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix;
|
||||
|
||||
@@ -638,6 +644,9 @@ export function createResumableState(
|
||||
idPrefix: idPrefix,
|
||||
nextFormID: 0,
|
||||
streamingFormat,
|
||||
bootstrapScriptContent,
|
||||
bootstrapScripts,
|
||||
bootstrapModules,
|
||||
instructions: NothingSent,
|
||||
hasBody: false,
|
||||
hasHtml: false,
|
||||
@@ -3714,7 +3723,11 @@ export function pushEndInstance(
|
||||
function writeBootstrap(
|
||||
destination: Destination,
|
||||
renderState: RenderState,
|
||||
resumableState: ResumableState,
|
||||
): boolean {
|
||||
resumableState.bootstrapScriptContent = undefined;
|
||||
resumableState.bootstrapScripts = undefined;
|
||||
resumableState.bootstrapModules = undefined;
|
||||
const bootstrapChunks = renderState.bootstrapChunks;
|
||||
let i = 0;
|
||||
for (; i < bootstrapChunks.length - 1; i++) {
|
||||
@@ -3731,8 +3744,9 @@ function writeBootstrap(
|
||||
export function writeCompletedRoot(
|
||||
destination: Destination,
|
||||
renderState: RenderState,
|
||||
resumableState: ResumableState,
|
||||
): boolean {
|
||||
return writeBootstrap(destination, renderState);
|
||||
return writeBootstrap(destination, renderState, resumableState);
|
||||
}
|
||||
|
||||
// Structural Nodes
|
||||
@@ -4197,7 +4211,7 @@ export function writeCompletedBoundaryInstruction(
|
||||
} else {
|
||||
writeMore = writeChunkAndReturn(destination, completeBoundaryDataEnd);
|
||||
}
|
||||
return writeBootstrap(destination, renderState) && writeMore;
|
||||
return writeBootstrap(destination, renderState, resumableState) && writeMore;
|
||||
}
|
||||
|
||||
const clientRenderScript1Full = stringToPrecomputedChunk(
|
||||
|
||||
@@ -92,8 +92,6 @@ export function createRenderState(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
return {
|
||||
// Keep this in sync with ReactFizzConfigDOM
|
||||
|
||||
@@ -114,6 +114,9 @@ function renderToReadableStream(
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createRequest(
|
||||
children,
|
||||
@@ -121,9 +124,6 @@ function renderToReadableStream(
|
||||
createRenderState(
|
||||
resumableState,
|
||||
options ? options.nonce : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
onHeadersImpl,
|
||||
|
||||
@@ -104,6 +104,9 @@ function renderToReadableStream(
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createRequest(
|
||||
children,
|
||||
@@ -111,9 +114,6 @@ function renderToReadableStream(
|
||||
createRenderState(
|
||||
resumableState,
|
||||
options ? options.nonce : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
onHeadersImpl,
|
||||
|
||||
@@ -114,6 +114,9 @@ function renderToReadableStream(
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createRequest(
|
||||
children,
|
||||
@@ -121,9 +124,6 @@ function renderToReadableStream(
|
||||
createRenderState(
|
||||
resumableState,
|
||||
options ? options.nonce : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
onHeadersImpl,
|
||||
|
||||
@@ -88,6 +88,9 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) {
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
return createRequest(
|
||||
children,
|
||||
@@ -95,9 +98,6 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) {
|
||||
createRenderState(
|
||||
resumableState,
|
||||
options ? options.nonce : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
options ? options.onHeaders : undefined,
|
||||
|
||||
@@ -94,6 +94,9 @@ function prerender(
|
||||
const resources = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createPrerenderRequest(
|
||||
children,
|
||||
@@ -101,9 +104,6 @@ function prerender(
|
||||
createRenderState(
|
||||
resources,
|
||||
undefined, // nonce is not compatible with prerendered bootstrap scripts
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
onHeadersImpl,
|
||||
|
||||
@@ -93,6 +93,9 @@ function prerender(
|
||||
const resources = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createPrerenderRequest(
|
||||
children,
|
||||
@@ -100,9 +103,6 @@ function prerender(
|
||||
createRenderState(
|
||||
resources,
|
||||
undefined, // nonce is not compatible with prerendered bootstrap scripts
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
onHeadersImpl,
|
||||
|
||||
@@ -94,6 +94,9 @@ function prerenderToNodeStream(
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createPrerenderRequest(
|
||||
children,
|
||||
@@ -101,9 +104,6 @@ function prerenderToNodeStream(
|
||||
createRenderState(
|
||||
resumableState,
|
||||
undefined, // nonce is not compatible with prerendered bootstrap scripts
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.importMap : undefined,
|
||||
options ? options.onHeaders : undefined,
|
||||
|
||||
@@ -53,6 +53,9 @@ function renderToStream(children: ReactNodeList, options: Options): Stream {
|
||||
const resumableState = createResumableState(
|
||||
options ? options.identifierPrefix : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
);
|
||||
const request = createRequest(
|
||||
children,
|
||||
@@ -60,9 +63,6 @@ function renderToStream(children: ReactNodeList, options: Options): Stream {
|
||||
createRenderState(
|
||||
resumableState,
|
||||
undefined,
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
),
|
||||
createRootFormatContext(undefined),
|
||||
|
||||
6
packages/react-server/src/ReactFizzServer.js
vendored
6
packages/react-server/src/ReactFizzServer.js
vendored
@@ -3968,7 +3968,11 @@ function flushCompletedQueues(
|
||||
|
||||
flushSegment(request, destination, completedRootSegment);
|
||||
request.completedRootSegment = null;
|
||||
writeCompletedRoot(destination, request.renderState);
|
||||
writeCompletedRoot(
|
||||
destination,
|
||||
request.renderState,
|
||||
request.resumableState,
|
||||
);
|
||||
} else {
|
||||
// We haven't flushed the root yet so we don't need to check any other branches further down
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user