Skip to content

Commit

Permalink
Add option to load Fizz runtime from external file (#25499)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
acdlite authored and rickhanlonii committed Dec 3, 2022
1 parent f2d94fd commit 1d2c855
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
enableFilterEmptyStringAttributesDOM,
enableCustomElementPropertySupport,
enableFloat,
enableFizzExternalRuntime,
} from 'shared/ReactFeatureFlags';

import type {
Expand Down Expand Up @@ -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 =
Expand All @@ -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];
Expand Down
30 changes: 30 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzServerBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Options = {
progressiveChunkSize?: number,
signal?: AbortSignal,
onError?: (error: mixed) => ?string,
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
};

// TODO: Move to sub-classing ReadableStream.
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzServerNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type Options = {
onShellError?: (error: mixed) => void,
onAllReady?: () => void,
onError?: (error: mixed) => ?string,
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
};

type PipeableStream = {
Expand All @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Options = {
progressiveChunkSize?: number,
signal?: AbortSignal,
onError?: (error: mixed) => ?string,
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
};

type StaticResult = {
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzStaticNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Options = {
progressiveChunkSize?: number,
signal?: AbortSignal,
onError?: (error: mixed) => ?string,
unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,
};

type StaticResult = {
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-oss.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

0 comments on commit 1d2c855

Please sign in to comment.