@samitouri / QOS-React / commits / 93f1668045

[Fizz] Add Node Web Streams bundle for SSR (#33441)

We highly recommend using Node Streams in Node.js because it's much faster and it is less likely to cause issues when chained in things like compression algorithms that need explicit flushing which the Web Streams ecosystem doesn't have a good solution for. However, that said, people want to be able to use the worse option for various reasons. The `.edge` builds aren't technically intended for Node.js. A Node.js environments needs to be patched in various ways to support it. It's also less optimal since it can't use [Node.js exclusive features](https://github.com/facebook/react/pull/33388) and have to use [the lowest common denominator](https://github.com/facebook/react/pull/27399) such as JS implementations instead of native. This adds a Web Streams build of Fizz but exclusively for Node.js so that in it we can rely on Node.js modules. The main difference compared to Edge is that SSR now uses `createHash` from the `"crypto"` module and imports `TextEncoder` from `"util"`. We use `setImmediate` instead of `setTimeout`. The public API is just `react-dom/server` which in Node.js automatically imports `react-dom/server.node` which re-exports the legacy bundle, Node Streams bundle and Node Web Streams bundle. The main downside is if your bundler isn't smart to DCE this barrel file. With Flight the difference is larger but that's a bigger lift.

Sebastian Markbåge committed Jun 5, 2025 at 10:50 UTC 93f1668045b924294f5832d5044fa049cd7af16e
13 files changed +557 -12
packages/react-dom/npm/server.node.js
+7 -1
@@ -1,12 +1,14 @@
1 'use strict';
2
3 -var l, s;
3 +var l, s, w;
4 if (process.env.NODE_ENV === 'production') {
5 l = require('./cjs/react-dom-server-legacy.node.production.js');
6 s = require('./cjs/react-dom-server.node.production.js');
7 + w = require('./cjs/react-dom-server.node-webstreams.production.js');
8 } else {
9 l = require('./cjs/react-dom-server-legacy.node.development.js');
10 s = require('./cjs/react-dom-server.node.development.js');
11 + w = require('./cjs/react-dom-server.node-webstreams.development.js');
12 }
13
14 exports.version = l.version;
@@ -16,3 +18,7 @@ exports.renderToPipeableStream = s.renderToPipeableStream;
18 if (s.resumeToPipeableStream) {
19 exports.resumeToPipeableStream = s.resumeToPipeableStream;
20 }
21 +exports.renderToReadableStream = w.renderToReadableStream;
22 +if (w.resume) {
23 + exports.resume = w.resume;
24 +}
packages/react-dom/npm/static.node.js
+5 -1
@@ -1,12 +1,16 @@
1 'use strict';
2
3 -var s;
3 +var s, w;
4 if (process.env.NODE_ENV === 'production') {
5 s = require('./cjs/react-dom-server.node.production.js');
6 + w = require('./cjs/react-dom-server.node-webstreams.production.js');
7 } else {
8 s = require('./cjs/react-dom-server.node.development.js');
9 + w = require('./cjs/react-dom-server.node-webstreams.development.js');
10 }
11
12 exports.version = s.version;
13 exports.prerenderToNodeStream = s.prerenderToNodeStream;
14 exports.resumeAndPrerenderToNodeStream = s.resumeAndPrerenderToNodeStream;
15 +exports.prerender = w.prerender;
16 +exports.resumeAndPrerender = w.resumeAndPrerender;
packages/react-dom/server.node.js
+14
@@ -37,3 +37,17 @@ export function resumeToPipeableStream() {
37 arguments,
38 );
39 }
40 +
41 +export function renderToReadableStream() {
42 + return require('./src/server/react-dom-server.node-webstreams').renderToReadableStream.apply(
43 + this,
44 + arguments,
45 + );
46 +}
47 +
48 +export function resume() {
49 + return require('./src/server/react-dom-server.node-webstreams').resume.apply(
50 + this,
51 + arguments,
52 + );
53 +}
packages/react-dom/src/__tests__/ReactDOMFizzServerNodeWebStreams-test.js new
+43
@@ -0,0 +1,43 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + * @jest-environment node
9 + */
10 +
11 +'use strict';
12 +
13 +let React;
14 +let ReactDOMFizzServer;
15 +
16 +describe('ReactDOMFizzServerNodeWebStreams', () => {
17 + beforeEach(() => {
18 + jest.resetModules();
19 + jest.useRealTimers();
20 + React = require('react');
21 + ReactDOMFizzServer = require('react-dom/server.node');
22 + });
23 +
24 + async function readResult(stream) {
25 + const reader = stream.getReader();
26 + let result = '';
27 + while (true) {
28 + const {done, value} = await reader.read();
29 + if (done) {
30 + return result;
31 + }
32 + result += Buffer.from(value).toString('utf8');
33 + }
34 + }
35 +
36 + it('should call renderToPipeableStream', async () => {
37 + const stream = await ReactDOMFizzServer.renderToReadableStream(
38 + <div>hello world</div>,
39 + );
40 + const result = await readResult(stream);
41 + expect(result).toMatchInlineSnapshot(`"<div>hello world</div>"`);
42 + });
43 +});
packages/react-dom/src/__tests__/ReactDOMFizzStaticNodeWebStreams-test.js new
+177
@@ -0,0 +1,177 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + * @jest-environment node
9 + */
10 +
11 +'use strict';
12 +
13 +import {
14 + getVisibleChildren,
15 + insertNodesAndExecuteScripts,
16 +} from '../test-utils/FizzTestUtils';
17 +
18 +let JSDOM;
19 +let React;
20 +let ReactDOMFizzServer;
21 +let ReactDOMFizzStatic;
22 +let Suspense;
23 +let container;
24 +let serverAct;
25 +
26 +describe('ReactDOMFizzStaticNodeWebStreams', () => {
27 + beforeEach(() => {
28 + jest.resetModules();
29 + serverAct = require('internal-test-utils').serverAct;
30 +
31 + JSDOM = require('jsdom').JSDOM;
32 +
33 + React = require('react');
34 + ReactDOMFizzServer = require('react-dom/server.node');
35 + ReactDOMFizzStatic = require('react-dom/static.node');
36 + Suspense = React.Suspense;
37 +
38 + const jsdom = new JSDOM(
39 + // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.
40 + '<script>window.requestAnimationFrame = setTimeout;</script>',
41 + {
42 + runScripts: 'dangerously',
43 + },
44 + );
45 + global.window = jsdom.window;
46 + global.document = jsdom.window.document;
47 + container = document.createElement('div');
48 + document.body.appendChild(container);
49 + });
50 +
51 + afterEach(() => {
52 + document.body.removeChild(container);
53 + });
54 +
55 + async function readContent(stream) {
56 + const reader = stream.getReader();
57 + let content = '';
58 + while (true) {
59 + const {done, value} = await reader.read();
60 + if (done) {
61 + return content;
62 + }
63 + content += Buffer.from(value).toString('utf8');
64 + }
65 + }
66 +
67 + async function readIntoContainer(stream) {
68 + const reader = stream.getReader();
69 + let result = '';
70 + while (true) {
71 + const {done, value} = await reader.read();
72 + if (done) {
73 + break;
74 + }
75 + result += Buffer.from(value).toString('utf8');
76 + }
77 + const temp = document.createElement('div');
78 + temp.innerHTML = result;
79 + await insertNodesAndExecuteScripts(temp, container, null);
80 + jest.runAllTimers();
81 + }
82 +
83 + it('should call prerender', async () => {
84 + const result = await serverAct(() =>
85 + ReactDOMFizzStatic.prerender(<div>hello world</div>),
86 + );
87 + const prelude = await readContent(result.prelude);
88 + expect(prelude).toMatchInlineSnapshot(`"<div>hello world</div>"`);
89 + });
90 +
91 + // @gate enableHalt
92 + it('can resume render of a prerender', async () => {
93 + const errors = [];
94 +
95 + let resolveA;
96 + const promiseA = new Promise(r => (resolveA = r));
97 + let resolveB;
98 + const promiseB = new Promise(r => (resolveB = r));
99 +
100 + async function ComponentA() {
101 + await promiseA;
102 + return (
103 + <Suspense fallback="Loading B">
104 + <ComponentB />
105 + </Suspense>
106 + );
107 + }
108 +
109 + async function ComponentB() {
110 + await promiseB;
111 + return 'Hello';
112 + }
113 +
114 + function App() {
115 + return (
116 + <div>
117 + <Suspense fallback="Loading A">
118 + <ComponentA />
119 + </Suspense>
120 + </div>
121 + );
122 + }
123 +
124 + const controller = new AbortController();
125 + let pendingResult;
126 + await serverAct(async () => {
127 + pendingResult = ReactDOMFizzStatic.prerender(<App />, {
128 + signal: controller.signal,
129 + onError(x) {
130 + errors.push(x.message);
131 + },
132 + });
133 + });
134 +
135 + controller.abort();
136 + const prerendered = await pendingResult;
137 + const postponedState = JSON.stringify(prerendered.postponed);
138 +
139 + await readIntoContainer(prerendered.prelude);
140 + expect(getVisibleChildren(container)).toEqual(<div>Loading A</div>);
141 +
142 + await resolveA();
143 +
144 + expect(prerendered.postponed).not.toBe(null);
145 +
146 + const controller2 = new AbortController();
147 + await serverAct(async () => {
148 + pendingResult = ReactDOMFizzStatic.resumeAndPrerender(
149 + <App />,
150 + JSON.parse(postponedState),
151 + {
152 + signal: controller2.signal,
153 + onError(x) {
154 + errors.push(x.message);
155 + },
156 + },
157 + );
158 + });
159 +
160 + controller2.abort();
161 +
162 + const prerendered2 = await pendingResult;
163 + const postponedState2 = JSON.stringify(prerendered2.postponed);
164 +
165 + await readIntoContainer(prerendered2.prelude);
166 + expect(getVisibleChildren(container)).toEqual(<div>Loading B</div>);
167 +
168 + await resolveB();
169 +
170 + const dynamic = await serverAct(() =>
171 + ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState2)),
172 + );
173 +
174 + await readIntoContainer(dynamic);
175 + expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);
176 + });
177 +});
packages/react-dom/src/server/react-dom-server.node-webstreams.js new
+11
@@ -0,0 +1,11 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export * from './ReactDOMFizzServerEdge.js';
11 +export {prerender, resumeAndPrerender} from './ReactDOMFizzStaticEdge.js';
packages/react-dom/src/server/react-dom-server.node-webstreams.stable.js new
+11
@@ -0,0 +1,11 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export {renderToReadableStream, version} from './ReactDOMFizzServerEdge.js';
11 +export {prerender} from './ReactDOMFizzStaticEdge.js';
packages/react-dom/static.node.js
+46 -7
@@ -3,12 +3,51 @@
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
6 */
7
10 -export {
11 - prerenderToNodeStream,
12 - resumeAndPrerenderToNodeStream,
13 - version,
14 -} from './src/server/react-dom-server.node';
8 +// This file is only used for tests.
9 +// It lazily loads the implementation so that we get the correct set of host configs.
10 +
11 +import ReactVersion from 'shared/ReactVersion';
12 +export {ReactVersion as version};
13 +
14 +export function renderToString() {
15 + return require('./src/server/ReactDOMLegacyServerNode').renderToString.apply(
16 + this,
17 + arguments,
18 + );
19 +}
20 +export function renderToStaticMarkup() {
21 + return require('./src/server/ReactDOMLegacyServerNode').renderToStaticMarkup.apply(
22 + this,
23 + arguments,
24 + );
25 +}
26 +
27 +export function prerenderToNodeStream() {
28 + return require('./src/server/react-dom-server.node').prerenderToNodeStream.apply(
29 + this,
30 + arguments,
31 + );
32 +}
33 +
34 +export function resumeAndPrerenderToNodeStream() {
35 + return require('./src/server/react-dom-server.node').resumeAndPrerenderToNodeStream.apply(
36 + this,
37 + arguments,
38 + );
39 +}
40 +
41 +export function prerender() {
42 + return require('./src/server/react-dom-server.node-webstreams').prerender.apply(
43 + this,
44 + arguments,
45 + );
46 +}
47 +
48 +export function resumeAndPrerender() {
49 + return require('./src/server/react-dom-server.node-webstreams').resumeAndPrerender.apply(
50 + this,
51 + arguments,
52 + );
53 +}
packages/react-server/src/ReactServerStreamConfigNodeWebStreams.js new
+186
@@ -0,0 +1,186 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +import {TextEncoder} from 'util';
11 +import {createHash} from 'crypto';
12 +
13 +export type Destination = ReadableStreamController;
14 +
15 +export type PrecomputedChunk = Uint8Array;
16 +export opaque type Chunk = Uint8Array;
17 +export type BinaryChunk = Uint8Array;
18 +
19 +export function scheduleWork(callback: () => void) {
20 + setImmediate(callback);
21 +}
22 +
23 +export const scheduleMicrotask = queueMicrotask;
24 +
25 +export function flushBuffered(destination: Destination) {
26 + // WHATWG Streams do not yet have a way to flush the underlying
27 + // transform streams. https://github.com/whatwg/streams/issues/960
28 +}
29 +
30 +const VIEW_SIZE = 2048;
31 +let currentView = null;
32 +let writtenBytes = 0;
33 +
34 +export function beginWriting(destination: Destination) {
35 + currentView = new Uint8Array(VIEW_SIZE);
36 + writtenBytes = 0;
37 +}
38 +
39 +export function writeChunk(
40 + destination: Destination,
41 + chunk: PrecomputedChunk | Chunk | BinaryChunk,
42 +): void {
43 + if (chunk.byteLength === 0) {
44 + return;
45 + }
46 +
47 + if (chunk.byteLength > VIEW_SIZE) {
48 + // this chunk may overflow a single view which implies it was not
49 + // one that is cached by the streaming renderer. We will enqueu
50 + // it directly and expect it is not re-used
51 + if (writtenBytes > 0) {
52 + destination.enqueue(
53 + new Uint8Array(
54 + ((currentView: any): Uint8Array).buffer,
55 + 0,
56 + writtenBytes,
57 + ),
58 + );
59 + currentView = new Uint8Array(VIEW_SIZE);
60 + writtenBytes = 0;
61 + }
62 + destination.enqueue(chunk);
63 + return;
64 + }
65 +
66 + let bytesToWrite = chunk;
67 + const allowableBytes = ((currentView: any): Uint8Array).length - writtenBytes;
68 + if (allowableBytes < bytesToWrite.byteLength) {
69 + // this chunk would overflow the current view. We enqueue a full view
70 + // and start a new view with the remaining chunk
71 + if (allowableBytes === 0) {
72 + // the current view is already full, send it
73 + destination.enqueue(currentView);
74 + } else {
75 + // fill up the current view and apply the remaining chunk bytes
76 + // to a new view.
77 + ((currentView: any): Uint8Array).set(
78 + bytesToWrite.subarray(0, allowableBytes),
79 + writtenBytes,
80 + );
81 + // writtenBytes += allowableBytes; // this can be skipped because we are going to immediately reset the view
82 + destination.enqueue(currentView);
83 + bytesToWrite = bytesToWrite.subarray(allowableBytes);
84 + }
85 + currentView = new Uint8Array(VIEW_SIZE);
86 + writtenBytes = 0;
87 + }
88 + ((currentView: any): Uint8Array).set(bytesToWrite, writtenBytes);
89 + writtenBytes += bytesToWrite.byteLength;
90 +}
91 +
92 +export function writeChunkAndReturn(
93 + destination: Destination,
94 + chunk: PrecomputedChunk | Chunk | BinaryChunk,
95 +): boolean {
96 + writeChunk(destination, chunk);
97 + // in web streams there is no backpressure so we can alwas write more
98 + return true;
99 +}
100 +
101 +export function completeWriting(destination: Destination) {
102 + if (currentView && writtenBytes > 0) {
103 + destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
104 + currentView = null;
105 + writtenBytes = 0;
106 + }
107 +}
108 +
109 +export function close(destination: Destination) {
110 + destination.close();
111 +}
112 +
113 +const textEncoder = new TextEncoder();
114 +
115 +export function stringToChunk(content: string): Chunk {
116 + return textEncoder.encode(content);
117 +}
118 +
119 +export function stringToPrecomputedChunk(content: string): PrecomputedChunk {
120 + const precomputedChunk = textEncoder.encode(content);
121 +
122 + if (__DEV__) {
123 + if (precomputedChunk.byteLength > VIEW_SIZE) {
124 + console.error(
125 + 'precomputed chunks must be smaller than the view size configured for this host. This is a bug in React.',
126 + );
127 + }
128 + }
129 +
130 + return precomputedChunk;
131 +}
132 +
133 +export function typedArrayToBinaryChunk(
134 + content: $ArrayBufferView,
135 +): BinaryChunk {
136 + // Convert any non-Uint8Array array to Uint8Array. We could avoid this for Uint8Arrays.
137 + // If we passed through this straight to enqueue we wouldn't have to convert it but since
138 + // we need to copy the buffer in that case, we need to convert it to copy it.
139 + // When we copy it into another array using set() it needs to be a Uint8Array.
140 + const buffer = new Uint8Array(
141 + content.buffer,
142 + content.byteOffset,
143 + content.byteLength,
144 + );
145 + // We clone large chunks so that we can transfer them when we write them.
146 + // Others get copied into the target buffer.
147 + return content.byteLength > VIEW_SIZE ? buffer.slice() : buffer;
148 +}
149 +
150 +export function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {
151 + return chunk.byteLength;
152 +}
153 +
154 +export function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {
155 + return chunk.byteLength;
156 +}
157 +
158 +export function closeWithError(destination: Destination, error: mixed): void {
159 + // $FlowFixMe[method-unbinding]
160 + if (typeof destination.error === 'function') {
161 + // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
162 + destination.error(error);
163 + } else {
164 + // Earlier implementations doesn't support this method. In that environment you're
165 + // supposed to throw from a promise returned but we don't return a promise in our
166 + // approach. We could fork this implementation but this is environment is an edge
167 + // case to begin with. It's even less common to run this in an older environment.
168 + // Even then, this is not where errors are supposed to happen and they get reported
169 + // to a global callback in addition to this anyway. So it's fine just to close this.
170 + destination.close();
171 + }
172 +}
173 +
174 +export function createFastHash(input: string): string | number {
175 + const hash = createHash('md5');
176 + hash.update(input);
177 + return hash.digest('hex');
178 +}
179 +
180 +export function readAsDataURL(blob: Blob): Promise<string> {
181 + return blob.arrayBuffer().then(arrayBuffer => {
182 + const encoded = Buffer.from(arrayBuffer).toString('base64');
183 + const mimeType = blob.type || 'application/octet-stream';
184 + return 'data:' + mimeType + ';base64,' + encoded;
185 + });
186 +}
packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webstreams.js new
+10
@@ -0,0 +1,10 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export * from '../ReactServerStreamConfigNodeWebStreams';
packages/react/src/__tests__/ReactMismatchedVersions-test.js
+1
@@ -109,6 +109,7 @@ describe('ReactMismatchedVersions-test', () => {
109 );
110 });
111
112 + // @gate !source
113 it('importing "react-dom/static.node" throws if version does not match React version', async () => {
114 expect(() => require('react-dom/static.node')).toThrow(
115 'Incompatible React versions: The "react" and "react-dom" packages ' +
scripts/rollup/bundles.js
+10
@@ -365,6 +365,16 @@ const bundles = [
365 wrapWithModuleBoundaries: false,
366 externals: ['react', 'util', 'crypto', 'async_hooks', 'react-dom'],
367 },
368 + {
369 + bundleTypes: [NODE_DEV, NODE_PROD],
370 + moduleType: RENDERER,
371 + entry: 'react-dom/src/server/react-dom-server.node-webstreams.js',
372 + name: 'react-dom-server.node-webstreams',
373 + global: 'ReactDOMServer',
374 + minifyWithProdErrorCodes: false,
375 + wrapWithModuleBoundaries: false,
376 + externals: ['react', 'util', 'crypto', 'async_hooks', 'react-dom'],
377 + },
378 {
379 bundleTypes: __EXPERIMENTAL__ ? [FB_WWW_DEV, FB_WWW_PROD] : [],
380 moduleType: RENDERER,
scripts/shared/inlinedHostConfigs.js
+36 -3
@@ -60,7 +60,6 @@ module.exports = [
60 entryPoints: [
61 'react-dom/src/ReactDOMReactServer.js',
62 'react-dom/src/server/react-dom-server.node.js',
63 - 'react-dom/static.node',
63 'react-dom/test-utils',
64 'react-dom/unstable_server-external-runtime',
65 'react-server-dom-webpack/client.node.unbundled',
@@ -103,6 +102,42 @@ module.exports = [
102 isFlowTyped: true,
103 isServerSupported: true,
104 },
105 + {
106 + shortName: 'dom-node-webstreams',
107 + entryPoints: ['react-dom/src/server/react-dom-server.node-webstreams.js'],
108 + paths: [
109 + 'react-dom',
110 + 'react-dom/src/ReactDOMReactServer.js',
111 + 'react-dom-bindings',
112 + 'react-dom/client',
113 + 'react-dom/profiling',
114 + 'react-dom/server',
115 + 'react-dom/server.node',
116 + 'react-dom/static',
117 + 'react-dom/static.node',
118 + 'react-dom/test-utils',
119 + 'react-dom/src/server/react-dom-server.node-webstreams',
120 + 'react-dom/src/server/ReactDOMFizzServerEdge.js',
121 + 'react-dom/src/server/ReactDOMFizzStaticEdge.js',
122 + 'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
123 + 'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
124 + 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
125 + 'react-server-dom-webpack',
126 + 'react-server-dom-webpack/client.node.unbundled',
127 + 'react-server-dom-webpack/server',
128 + 'react-server-dom-webpack/server.node.unbundled',
129 + 'react-server-dom-webpack/static',
130 + 'react-server-dom-webpack/static.node.unbundled',
131 + 'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.node
132 + 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerNode.js',
133 + 'react-server-dom-webpack/src/server/react-flight-dom-server.node.unbundled',
134 + 'react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-webpack/src/server/react-flight-dom-server.node
135 + 'shared/ReactDOMSharedInternals',
136 + 'react-server/src/ReactFlightServerConfigDebugNode.js',
137 + ],
138 + isFlowTyped: true,
139 + isServerSupported: true,
140 + },
141 {
142 shortName: 'dom-node-webpack',
143 entryPoints: [
@@ -221,8 +256,6 @@ module.exports = [
256 'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
257 'react-server-dom-parcel/src/server/react-flight-dom-server.node',
258 'react-server-dom-parcel/src/server/ReactFlightDOMServerNode.js', // react-server-dom-parcel/src/server/react-flight-dom-server.node
224 - 'react-server-dom-parcel/node-register',
225 - 'react-server-dom-parcel/src/ReactFlightParcelNodeRegister.js',
259 'react-devtools',
260 'react-devtools-core',
261 'react-devtools-shell',