Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Next.js runtime support to ReactFizzServer #22350

Closed
wants to merge 13 commits into from
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from 'react-client/src/ReactFlightClientHostConfigBrowser';
export * from 'react-client/src/ReactFlightClientHostConfigStream';
export * from 'react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig';
86 changes: 86 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzServerNext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import type {ReactNodeList} from 'shared/ReactTypes';
import type {Destination} from 'react-server/src/ReactServerStreamConfigNext';

import ReactVersion from 'shared/ReactVersion';

import {
createRequest,
startWork,
startFlowing,
abort,
} from 'react-server/src/ReactFizzServer';

import {
createResponseState,
createRootFormatContext,
} from './ReactDOMServerFormatConfig';

type NextStreamSource = {
start: (controller: Destination) => void,
pull: (controller: Destination) => void,
cancel: (reason: mixed) => void,
};

type Options = {|
identifierPrefix?: string,
namespaceURI?: string,
nonce?: string,
bootstrapScriptContent?: string,
bootstrapScripts?: Array<string>,
bootstrapModules?: Array<string>,
progressiveChunkSize?: number,
signal?: AbortSignal,
onCompleteShell?: () => void,
onCompleteAll?: () => void,
onError?: (error: mixed) => void,
|};

function renderToNextStream(
children: ReactNodeList,
options?: Options,
): NextStreamSource {
const request = createRequest(
children,
createResponseState(
options ? options.identifierPrefix : undefined,
options ? options.nonce : undefined,
options ? options.bootstrapScriptContent : undefined,
options ? options.bootstrapScripts : undefined,
options ? options.bootstrapModules : undefined,
),
createRootFormatContext(options ? options.namespaceURI : undefined),
options ? options.progressiveChunkSize : undefined,
options ? options.onError : undefined,
options ? options.onCompleteAll : undefined,
options ? options.onCompleteShell : undefined,
);
if (options && options.signal) {
const signal = options.signal;
const listener = () => {
abort(request);
signal.removeEventListener('abort', listener);
};
signal.addEventListener('abort', listener);
}
const stream = {
start(controller) {
startWork(request);
},
pull(controller) {
startFlowing(request, controller);
},
cancel(reason) {},
};
return stream;
}

export {renderToNextStream, ReactVersion as version};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from 'react-dom/src/client/ReactDOMHostConfig';
52 changes: 52 additions & 0 deletions packages/react-server-dom-webpack/src/ReactFlightDOMServerNext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import type {ReactModel} from 'react-server/src/ReactFlightServer';
import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig';
import type {Destination} from 'react-server/src/ReactServerStreamConfigNext';

import {
createRequest,
startWork,
startFlowing,
} from 'react-server/src/ReactFlightServer';

type NextStreamSource = {
start: (controller: Destination) => void,
pull: (controller: Destination) => void,
cancel: (reason: mixed) => void,
};

type Options = {
onError?: (error: mixed) => void,
};

function renderToNextStream(
model: ReactModel,
webpackMap: BundlerConfig,
options?: Options,
): NextStreamSource {
const request = createRequest(
model,
webpackMap,
options ? options.onError : undefined,
);
const stream = {
start(controller) {
startWork(request);
},
pull(controller) {
startFlowing(request, controller);
},
cancel(reason) {},
};
return stream;
}

export {renderToNextStream};
10 changes: 10 additions & 0 deletions packages/react-server-dom-webpack/writer.next.server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from './src/ReactFlightDOMServerNext.js';
63 changes: 63 additions & 0 deletions packages/react-server/src/ReactServerStreamConfigNext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

declare function __next_scheduleReactServerWork(callback: () => void): void;

export type Destination = {
flush: () => void,
buffer: (buffer: boolean) => void,
close: (error: mixed) => void,
write: (chunk: Uint8Array) => void,
desiredSize: number,
};

export type PrecomputedChunk = Uint8Array;
export type Chunk = Uint8Array;

export function scheduleWork(callback: () => void) {
__next_scheduleReactServerWork(callback);
}

export function flushBuffered(destination: Destination) {
destination.flush();
}

export function beginWriting(destination: Destination) {
destination.buffer(true);
}

export function writeChunk(
destination: Destination,
chunk: Chunk | PrecomputedChunk,
): boolean {
destination.write(chunk);
return destination.desiredSize > 0;
}

export function completeWriting(destination: Destination) {
destination.buffer(false);
}

export function close(destination: Destination) {
destination.close();
}

const textEncoder = new TextEncoder();

export function stringToChunk(content: string): Chunk {
return textEncoder.encode(content);
}

export function stringToPrecomputedChunk(content: string): PrecomputedChunk {
return textEncoder.encode(content);
}

export function closeWithError(destination: Destination, error: mixed): void {
destination.close(error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from '../ReactFlightServerConfigStream';
export * from 'react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from 'react-dom/src/server/ReactDOMServerFormatConfig';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export * from '../ReactServerStreamConfigNext';
8 changes: 8 additions & 0 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,14 @@ const bundles = [
wrapWithModuleBoundaries: false,
externals: ['react'],
},
{
bundleTypes: [NODE_DEV, NODE_PROD],
moduleType: RENDERER,
entry: 'react-dom/src/server/ReactDOMFizzServerNext',
name: 'react-dom-server-next',
global: 'ReactDOMServer',
externals: ['react'],
},
{
bundleTypes: __EXPERIMENTAL__ ? [FB_WWW_DEV, FB_WWW_PROD] : [],
moduleType: RENDERER,
Expand Down
16 changes: 16 additions & 0 deletions scripts/shared/inlinedHostConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ module.exports = [
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-next',
entryPoints: [
'react-server-dom-webpack/writer.next.server',
'react-server-dom-webpack',
'react-dom/src/server/ReactDOMFizzServerNext', // react-dom/server
],
paths: [
'react-dom',
'react-server-dom-webpack',
'react-dom/src/server/ReactDOMFizzServerNext.js', // react-dom/server.next
'react-client/src/ReactFlightClientStream.js', // We can only type check this in streaming configurations.
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'art',
entryPoints: ['react-art'],
Expand Down