[react-dom] Include all Node.js APIs in Bun entrypoint for `/server` (#34193)
Michael H committed
Oct 28, 2025 at 09:06 UTC
b4455a6ee6450fae830ae0b6e53e77f7a147bc27
7 files changed
+65
-4
packages/react-dom/npm/server.bun.js
+2
@@ -12,6 +12,8 @@ if (process.env.NODE_ENV === 'production') {
12
13
exports.version = b.version;
14
exports.renderToReadableStream = b.renderToReadableStream;
15
+exports.renderToPipeableStream = b.renderToPipeableStream;
16
+exports.resumeToPipeableStream = b.resumeToPipeableStream;
17
exports.resume = b.resume;
18
exports.renderToString = l.renderToString;
19
exports.renderToStaticMarkup = l.renderToStaticMarkup;
packages/react-dom/server.bun.js
+14
@@ -38,3 +38,17 @@ export function resume() {
38
arguments,
39
);
40
}
41
+
42
+export function renderToPipeableStream() {
43
+ return require('./src/server/react-dom-server.bun').renderToPipeableStream.apply(
44
+ this,
45
+ arguments,
46
+ );
47
+}
48
+
49
+export function resumeToPipeableStream() {
50
+ return require('./src/server/react-dom-server.bun').resumeToPipeableStream.apply(
51
+ this,
52
+ arguments,
53
+ );
54
+}
packages/react-dom/src/server/react-dom-server.bun.js
+11
@@ -8,3 +8,14 @@
8
*/
9
10
export * from './ReactDOMFizzServerBun.js';
11
+export {
12
+ renderToPipeableStream,
13
+ resumeToPipeableStream,
14
+ resume,
15
+} from './ReactDOMFizzServerNode.js';
16
+export {
17
+ prerenderToNodeStream,
18
+ prerender,
19
+ resumeAndPrerenderToNodeStream,
20
+ resumeAndPrerender,
21
+} from './ReactDOMFizzStaticNode.js';
packages/react-dom/src/server/react-dom-server.bun.stable.js
+11
@@ -8,3 +8,14 @@
8
*/
9
10
export {renderToReadableStream, version} from './ReactDOMFizzServerBun.js';
11
+export {
12
+ renderToPipeableStream,
13
+ resume,
14
+ resumeToPipeableStream,
15
+} from './ReactDOMFizzServerNode.js';
16
+export {
17
+ prerenderToNodeStream,
18
+ prerender,
19
+ resumeAndPrerenderToNodeStream,
20
+ resumeAndPrerender,
21
+} from './ReactDOMFizzStaticNode.js';
packages/react-server/src/ReactServerStreamConfigBun.js
+24
-3
@@ -9,13 +9,22 @@
9
10
/* global Bun */
11
12
+import type {Writable} from 'stream';
13
+
14
type BunReadableStreamController = ReadableStreamController & {
15
end(): mixed,
16
write(data: Chunk | BinaryChunk): void,
17
error(error: Error): void,
18
flush?: () => void,
19
};
18
-export type Destination = BunReadableStreamController;
20
+
21
+interface MightBeFlushable {
22
+ flush?: () => void;
23
+}
24
+
25
+export type Destination =
26
+ | BunReadableStreamController
27
+ | (Writable & MightBeFlushable);
28
29
export type PrecomputedChunk = string;
30
export opaque type Chunk = string;
@@ -46,6 +55,7 @@ export function writeChunk(
55
return;
56
}
57
58
+ // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun
59
destination.write(chunk);
60
}
61
@@ -53,6 +63,7 @@ export function writeChunkAndReturn(
63
destination: Destination,
64
chunk: PrecomputedChunk | Chunk | BinaryChunk,
65
): boolean {
66
+ // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun
67
return !!destination.write(chunk);
68
}
69
@@ -86,11 +97,21 @@ export function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {
97
}
98
99
export function closeWithError(destination: Destination, error: mixed): void {
100
+ // $FlowFixMe[incompatible-use]
101
// $FlowFixMe[method-unbinding]
102
if (typeof destination.error === 'function') {
103
// $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
104
destination.error(error);
93
- } else {
105
+
106
+ // $FlowFixMe[incompatible-use]
107
+ // $FlowFixMe[method-unbinding]
108
+ } else if (typeof destination.destroy === 'function') {
109
+ // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
110
+ destination.destroy(error);
111
+
112
+ // $FlowFixMe[incompatible-use]
113
+ // $FlowFixMe[method-unbinding]
114
+ } else if (typeof destination.close === 'function') {
115
// Earlier implementations doesn't support this method. In that environment you're
116
// supposed to throw from a promise returned but we don't return a promise in our
117
// approach. We could fork this implementation but this is environment is an edge
@@ -101,7 +122,7 @@ export function closeWithError(destination: Destination, error: mixed): void {
122
}
123
}
124
104
-export function createFastHash(input: string): string | number {
125
+export function createFastHash(input: string): number {
126
return Bun.hash(input);
127
}
128
scripts/rollup/bundles.js
+1
-1
@@ -405,7 +405,7 @@ const bundles = [
405
global: 'ReactDOMServer',
406
minifyWithProdErrorCodes: false,
407
wrapWithModuleBoundaries: false,
408
- externals: ['react', 'react-dom'],
408
+ externals: ['react', 'react-dom', 'crypto', 'stream', 'util'],
409
},
410
411
/******* React DOM Fizz Server External Runtime *******/
scripts/shared/inlinedHostConfigs.js
+2
@@ -250,6 +250,8 @@ module.exports = [
250
'react-dom/server.bun',
251
'react-dom/src/server/react-dom-server.bun',
252
'react-dom/src/server/ReactDOMFizzServerBun.js',
253
+ 'react-dom/src/server/ReactDOMFizzServerNode.js',
254
+ 'react-dom/src/server/ReactDOMFizzStaticNode.js',
255
'react-dom-bindings',
256
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
257
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',