Skip to content

Commit b36dfdf

Browse files
committed
Defer to the actual ReactDOM for HTML rendering for now
This will need to use a variant of Fizz to do inline SSR in Flight. However, I don't want to build the whole impl right now but also don't want to exclude the use case yet. So I outsource it to the existing renderer. Ofc, this doesn't work with Suspense atm.
1 parent 97b68e4 commit b36dfdf

File tree

8 files changed

+26
-34
lines changed

8 files changed

+26
-34
lines changed

fixtures/flight-browser/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ <h1>Flight Example</h1>
1818
</div>
1919
<script src="../../build/dist/react.development.js"></script>
2020
<script src="../../build/dist/react-dom.development.js"></script>
21+
<script src="../../build/dist/react-dom-server.browser.development.js"></script>
2122
<script src="../../build/dist/react-dom-unstable-flight-server.browser.development.js"></script>
2223
<script src="../../build/dist/react-dom-unstable-flight-client.development.js"></script>
2324
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>

packages/react-dom/src/__tests__/ReactFlightDOMBrowser-test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ global.ReadableStream = require('@mattiasbuelens/web-streams-polyfill/ponyfill/e
1515
global.TextEncoder = require('util').TextEncoder;
1616
global.TextDecoder = require('util').TextDecoder;
1717

18-
let Stream;
1918
let React;
2019
let ReactFlightDOMServer;
2120
let ReactFlightDOMClient;
2221

2322
describe('ReactFlightDOMBrowser', () => {
2423
beforeEach(() => {
2524
jest.resetModules();
26-
Stream = require('stream');
2725
React = require('react');
2826
ReactFlightDOMServer = require('react-dom/unstable-flight-server.browser');
2927
ReactFlightDOMClient = require('react-dom/unstable-flight-client');

packages/react-dom/src/server/ReactDOMServerFormatConfig.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
import {convertStringToBuffer} from 'react-server/src/ReactServerHostConfig';
1111

12+
import ReactDOMServer from 'react-dom/server';
13+
1214
export function formatChunkAsString(type: string, props: Object): string {
1315
let str = '<' + type + '>';
1416
if (typeof props.children === 'string') {
@@ -21,3 +23,13 @@ export function formatChunkAsString(type: string, props: Object): string {
2123
export function formatChunk(type: string, props: Object): Uint8Array {
2224
return convertStringToBuffer(formatChunkAsString(type, props));
2325
}
26+
27+
export function renderHostChildrenToString(
28+
children: React$Element<any>,
29+
): string {
30+
// TODO: This file is used to actually implement a server renderer
31+
// so we can't actually reference the renderer here. Instead, we
32+
// should replace this method with a reference to Fizz which
33+
// then uses this file to implement the server renderer.
34+
return ReactDOMServer.renderToStaticMarkup(children);
35+
}

packages/react-noop-renderer/src/ReactNoopFlightServer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ const ReactNoopFlightServer = ReactFlightServer({
4040
formatChunk(type: string, props: Object): Uint8Array {
4141
return Buffer.from(JSON.stringify({type, props}), 'utf8');
4242
},
43+
renderHostChildrenToString(children: React$Element<any>): string {
44+
throw new Error('The noop rendered do not support host components');
45+
},
4346
});
4447

4548
function render(model: ReactModel): Destination {

packages/react-server/src/ReactFlightServer.js

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
close,
1919
convertStringToBuffer,
2020
} from './ReactServerHostConfig';
21-
import {formatChunkAsString} from './ReactServerFormatConfig';
21+
import {renderHostChildrenToString} from './ReactServerFormatConfig';
2222
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
2323

2424
export type ReactModel =
@@ -56,32 +56,6 @@ export function createRequest(
5656
return {destination, model, completedChunks: [], flowing: false};
5757
}
5858

59-
function resolveChildToHostFormat(child: ReactJSONValue): string {
60-
if (typeof child === 'string') {
61-
return child;
62-
} else if (typeof child === 'number') {
63-
return '' + child;
64-
} else if (typeof child === 'boolean' || child === null) {
65-
// Booleans are like null when they're React children.
66-
return '';
67-
} else if (Array.isArray(child)) {
68-
return (child: Array<ReactModel>)
69-
.map(c => resolveChildToHostFormat(resolveModelToJSON('', c)))
70-
.join('');
71-
} else {
72-
throw new Error('Object models are not valid as children of host nodes.');
73-
}
74-
}
75-
76-
function resolveElementToHostFormat(type: string, props: Object): string {
77-
let child = resolveModelToJSON('', props.children);
78-
let childString = resolveChildToHostFormat(child);
79-
return formatChunkAsString(
80-
type,
81-
Object.assign({}, props, {children: childString}),
82-
);
83-
}
84-
8559
function resolveModelToJSON(key: string, value: ReactModel): ReactJSONValue {
8660
while (value && value.$$typeof === REACT_ELEMENT_TYPE) {
8761
let element: React$Element<any> = (value: any);
@@ -93,7 +67,7 @@ function resolveModelToJSON(key: string, value: ReactModel): ReactJSONValue {
9367
continue;
9468
} else if (typeof type === 'string') {
9569
// This is a host element. E.g. HTML.
96-
return resolveElementToHostFormat(type, props);
70+
return renderHostChildrenToString(element);
9771
} else {
9872
throw new Error('Unsupported type.');
9973
}

packages/react-server/src/forks/ReactServerFormatConfig.custom.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ export opaque type Destination = mixed; // eslint-disable-line no-undef
2828

2929
export const formatChunkAsString = $$$hostConfig.formatChunkAsString;
3030
export const formatChunk = $$$hostConfig.formatChunk;
31+
export const renderHostChildrenToString =
32+
$$$hostConfig.renderHostChildrenToString;

scripts/rollup/bundles.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,14 @@ const bundles = [
160160
moduleType: RENDERER,
161161
entry: 'react-dom/unstable-fizz.browser',
162162
global: 'ReactDOMFizzServer',
163-
externals: ['react'],
163+
externals: ['react', 'react-dom/server'],
164164
},
165165
{
166166
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
167167
moduleType: RENDERER,
168168
entry: 'react-dom/unstable-fizz.node',
169169
global: 'ReactDOMFizzServer',
170-
externals: ['react'],
170+
externals: ['react', 'react-dom/server'],
171171
},
172172

173173
/******* React DOM Flight Server *******/
@@ -176,14 +176,14 @@ const bundles = [
176176
moduleType: RENDERER,
177177
entry: 'react-dom/unstable-flight-server.browser',
178178
global: 'ReactFlightDOMServer',
179-
externals: ['react'],
179+
externals: ['react', 'react-dom/server'],
180180
},
181181
{
182182
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
183183
moduleType: RENDERER,
184184
entry: 'react-dom/unstable-flight-server.node',
185185
global: 'ReactFlightDOMServer',
186-
externals: ['react'],
186+
externals: ['react', 'react-dom/server'],
187187
},
188188

189189
/******* React DOM Flight Client *******/

scripts/rollup/modules.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ const importSideEffects = Object.freeze({
1717
'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
1818
scheduler: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
1919
'scheduler/tracing': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
20+
'react-dom/server': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
2021
});
2122

2223
// Bundles exporting globals that other modules rely on.
2324
const knownGlobals = Object.freeze({
2425
react: 'React',
2526
'react-dom': 'ReactDOM',
27+
'react-dom/server': 'ReactDOMServer',
2628
'react-interactions/events/keyboard': 'ReactEventsKeyboard',
2729
'react-interactions/events/tap': 'ReactEventsTap',
2830
scheduler: 'Scheduler',

0 commit comments

Comments
 (0)