mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add option to load Fizz runtime from external file (#25499)
* Add feature flag for external Fizz runtime Only enabled for www for now * Add option to load Fizz runtime from external file When unstable_externalRuntimeSrc is provided, React will inject a script tag that points to the provided URL. Then, instead of emitting inline scripts, the Fizz stream will emit HTML nodes with data attributes that encode the instructions. The external runtime will detect these with a mutation observer and translate them into runtime commands. This part isn't implemented in this PR, though — all this does is set up the option to use an external runtime, and inject the script tag. The external runtime is injected at the same time as bootstrap scripts.
This commit is contained in:
committed by
Rick Hanlon
parent
f2d94fdb33
commit
1d2c855e34
@@ -23,6 +23,7 @@ import {
|
||||
enableFilterEmptyStringAttributesDOM,
|
||||
enableCustomElementPropertySupport,
|
||||
enableFloat,
|
||||
enableFizzExternalRuntime,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import type {
|
||||
@@ -157,6 +158,7 @@ export function createResponseState(
|
||||
bootstrapScriptContent: string | void,
|
||||
bootstrapScripts: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
bootstrapModules: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
|
||||
externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
|
||||
): ResponseState {
|
||||
const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix;
|
||||
const inlineScriptWithNonce =
|
||||
@@ -173,6 +175,29 @@ export function createResponseState(
|
||||
endInlineScript,
|
||||
);
|
||||
}
|
||||
if (enableFizzExternalRuntime) {
|
||||
if (externalRuntimeConfig !== undefined) {
|
||||
const src =
|
||||
typeof externalRuntimeConfig === 'string'
|
||||
? externalRuntimeConfig
|
||||
: externalRuntimeConfig.src;
|
||||
const integrity =
|
||||
typeof externalRuntimeConfig === 'string'
|
||||
? undefined
|
||||
: externalRuntimeConfig.integrity;
|
||||
bootstrapChunks.push(
|
||||
startScriptSrc,
|
||||
stringToChunk(escapeTextForBrowser(src)),
|
||||
);
|
||||
if (integrity) {
|
||||
bootstrapChunks.push(
|
||||
scriptIntegirty,
|
||||
stringToChunk(escapeTextForBrowser(integrity)),
|
||||
);
|
||||
}
|
||||
bootstrapChunks.push(endAsyncScript);
|
||||
}
|
||||
}
|
||||
if (bootstrapScripts !== undefined) {
|
||||
for (let i = 0; i < bootstrapScripts.length; i++) {
|
||||
const scriptConfig = bootstrapScripts[i];
|
||||
|
||||
@@ -3546,6 +3546,36 @@ describe('ReactDOMFizzServer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// @gate enableFizzExternalRuntime
|
||||
it('supports option to load runtime as an external script', async () => {
|
||||
await actIntoEmptyDocument(() => {
|
||||
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<div>hello world</div>
|
||||
</body>
|
||||
</html>,
|
||||
{
|
||||
unstable_externalRuntimeSrc: 'src-of-external-runtime',
|
||||
},
|
||||
);
|
||||
pipe(writable);
|
||||
});
|
||||
|
||||
expect(getVisibleChildren(document)).toEqual(
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<div>hello world</div>
|
||||
</body>
|
||||
</html>,
|
||||
);
|
||||
expect(
|
||||
Array.from(document.getElementsByTagName('script')).map(n => n.outerHTML),
|
||||
).toEqual(['<script src="src-of-external-runtime" async=""></script>']);
|
||||
});
|
||||
|
||||
it('#24384: Suspending should halt hydration warnings and not emit any if hydration completes successfully after unsuspending', async () => {
|
||||
const makeApp = () => {
|
||||
let resolve, resolved;
|
||||
|
||||
@@ -34,6 +34,7 @@ type Options = {
|
||||
progressiveChunkSize?: number,
|
||||
signal?: AbortSignal,
|
||||
onError?: (error: mixed) => ?string,
|
||||
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
|
||||
};
|
||||
|
||||
// TODO: Move to sub-classing ReadableStream.
|
||||
@@ -86,6 +87,7 @@ function renderToReadableStream(
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
),
|
||||
createRootFormatContext(options ? options.namespaceURI : undefined),
|
||||
options ? options.progressiveChunkSize : undefined,
|
||||
|
||||
@@ -47,6 +47,7 @@ type Options = {
|
||||
onShellError?: (error: mixed) => void,
|
||||
onAllReady?: () => void,
|
||||
onError?: (error: mixed) => ?string,
|
||||
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
|
||||
};
|
||||
|
||||
type PipeableStream = {
|
||||
@@ -65,6 +66,7 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) {
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
),
|
||||
createRootFormatContext(options ? options.namespaceURI : undefined),
|
||||
options ? options.progressiveChunkSize : undefined,
|
||||
|
||||
@@ -33,6 +33,7 @@ type Options = {
|
||||
progressiveChunkSize?: number,
|
||||
signal?: AbortSignal,
|
||||
onError?: (error: mixed) => ?string,
|
||||
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
|
||||
};
|
||||
|
||||
type StaticResult = {
|
||||
@@ -71,6 +72,7 @@ function prerender(
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
),
|
||||
createRootFormatContext(options ? options.namespaceURI : undefined),
|
||||
options ? options.progressiveChunkSize : undefined,
|
||||
|
||||
@@ -35,6 +35,7 @@ type Options = {
|
||||
progressiveChunkSize?: number,
|
||||
signal?: AbortSignal,
|
||||
onError?: (error: mixed) => ?string,
|
||||
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
|
||||
};
|
||||
|
||||
type StaticResult = {
|
||||
@@ -86,6 +87,7 @@ function prerenderToNodeStreams(
|
||||
options ? options.bootstrapScriptContent : undefined,
|
||||
options ? options.bootstrapScripts : undefined,
|
||||
options ? options.bootstrapModules : undefined,
|
||||
options ? options.unstable_externalRuntimeSrc : undefined,
|
||||
),
|
||||
createRootFormatContext(options ? options.namespaceURI : undefined),
|
||||
options ? options.progressiveChunkSize : undefined,
|
||||
|
||||
@@ -125,6 +125,9 @@ export const enableUseMemoCacheHook = __EXPERIMENTAL__;
|
||||
|
||||
export const enableUseEventHook = __EXPERIMENTAL__;
|
||||
|
||||
// Test in www before enabling in open source.
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Chopping Block
|
||||
//
|
||||
|
||||
@@ -86,6 +86,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -76,6 +76,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -76,6 +76,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -78,6 +78,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -76,6 +76,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -77,6 +77,7 @@ export const enableFloat = false;
|
||||
export const enableHostSingletons = false;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
@@ -113,6 +113,7 @@ export const enableUseMutableSource = true;
|
||||
export const enableCustomElementPropertySupport = __EXPERIMENTAL__;
|
||||
|
||||
export const useModernStrictMode = false;
|
||||
export const enableFizzExternalRuntime = true;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
||||
Reference in New Issue
Block a user