Skip to content

Commit

Permalink
Defer to the actual ReactDOM for HTML rendering for now
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sebmarkbage committed Nov 1, 2019
1 parent 97b68e4 commit b36dfdf
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 34 deletions.
1 change: 1 addition & 0 deletions fixtures/flight-browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ <h1>Flight Example</h1>
</div>
<script src="../../build/dist/react.development.js"></script>
<script src="../../build/dist/react-dom.development.js"></script>
<script src="../../build/dist/react-dom-server.browser.development.js"></script>
<script src="../../build/dist/react-dom-unstable-flight-server.browser.development.js"></script>
<script src="../../build/dist/react-dom-unstable-flight-client.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ global.ReadableStream = require('@mattiasbuelens/web-streams-polyfill/ponyfill/e
global.TextEncoder = require('util').TextEncoder;
global.TextDecoder = require('util').TextDecoder;

let Stream;
let React;
let ReactFlightDOMServer;
let ReactFlightDOMClient;

describe('ReactFlightDOMBrowser', () => {
beforeEach(() => {
jest.resetModules();
Stream = require('stream');
React = require('react');
ReactFlightDOMServer = require('react-dom/unstable-flight-server.browser');
ReactFlightDOMClient = require('react-dom/unstable-flight-client');
Expand Down
12 changes: 12 additions & 0 deletions packages/react-dom/src/server/ReactDOMServerFormatConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

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

import ReactDOMServer from 'react-dom/server';

export function formatChunkAsString(type: string, props: Object): string {
let str = '<' + type + '>';
if (typeof props.children === 'string') {
Expand All @@ -21,3 +23,13 @@ export function formatChunkAsString(type: string, props: Object): string {
export function formatChunk(type: string, props: Object): Uint8Array {
return convertStringToBuffer(formatChunkAsString(type, props));
}

export function renderHostChildrenToString(
children: React$Element<any>,
): string {
// TODO: This file is used to actually implement a server renderer
// so we can't actually reference the renderer here. Instead, we
// should replace this method with a reference to Fizz which
// then uses this file to implement the server renderer.
return ReactDOMServer.renderToStaticMarkup(children);
}
3 changes: 3 additions & 0 deletions packages/react-noop-renderer/src/ReactNoopFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const ReactNoopFlightServer = ReactFlightServer({
formatChunk(type: string, props: Object): Uint8Array {
return Buffer.from(JSON.stringify({type, props}), 'utf8');
},
renderHostChildrenToString(children: React$Element<any>): string {
throw new Error('The noop rendered do not support host components');
},
});

function render(model: ReactModel): Destination {
Expand Down
30 changes: 2 additions & 28 deletions packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
close,
convertStringToBuffer,
} from './ReactServerHostConfig';
import {formatChunkAsString} from './ReactServerFormatConfig';
import {renderHostChildrenToString} from './ReactServerFormatConfig';
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';

export type ReactModel =
Expand Down Expand Up @@ -56,32 +56,6 @@ export function createRequest(
return {destination, model, completedChunks: [], flowing: false};
}

function resolveChildToHostFormat(child: ReactJSONValue): string {
if (typeof child === 'string') {
return child;
} else if (typeof child === 'number') {
return '' + child;
} else if (typeof child === 'boolean' || child === null) {
// Booleans are like null when they're React children.
return '';
} else if (Array.isArray(child)) {
return (child: Array<ReactModel>)
.map(c => resolveChildToHostFormat(resolveModelToJSON('', c)))
.join('');
} else {
throw new Error('Object models are not valid as children of host nodes.');
}
}

function resolveElementToHostFormat(type: string, props: Object): string {
let child = resolveModelToJSON('', props.children);
let childString = resolveChildToHostFormat(child);
return formatChunkAsString(
type,
Object.assign({}, props, {children: childString}),
);
}

function resolveModelToJSON(key: string, value: ReactModel): ReactJSONValue {
while (value && value.$$typeof === REACT_ELEMENT_TYPE) {
let element: React$Element<any> = (value: any);
Expand All @@ -93,7 +67,7 @@ function resolveModelToJSON(key: string, value: ReactModel): ReactJSONValue {
continue;
} else if (typeof type === 'string') {
// This is a host element. E.g. HTML.
return resolveElementToHostFormat(type, props);
return renderHostChildrenToString(element);
} else {
throw new Error('Unsupported type.');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ export opaque type Destination = mixed; // eslint-disable-line no-undef

export const formatChunkAsString = $$$hostConfig.formatChunkAsString;
export const formatChunk = $$$hostConfig.formatChunk;
export const renderHostChildrenToString =
$$$hostConfig.renderHostChildrenToString;
8 changes: 4 additions & 4 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ const bundles = [
moduleType: RENDERER,
entry: 'react-dom/unstable-fizz.browser',
global: 'ReactDOMFizzServer',
externals: ['react'],
externals: ['react', 'react-dom/server'],
},
{
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
moduleType: RENDERER,
entry: 'react-dom/unstable-fizz.node',
global: 'ReactDOMFizzServer',
externals: ['react'],
externals: ['react', 'react-dom/server'],
},

/******* React DOM Flight Server *******/
Expand All @@ -176,14 +176,14 @@ const bundles = [
moduleType: RENDERER,
entry: 'react-dom/unstable-flight-server.browser',
global: 'ReactFlightDOMServer',
externals: ['react'],
externals: ['react', 'react-dom/server'],
},
{
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
moduleType: RENDERER,
entry: 'react-dom/unstable-flight-server.node',
global: 'ReactFlightDOMServer',
externals: ['react'],
externals: ['react', 'react-dom/server'],
},

/******* React DOM Flight Client *******/
Expand Down
2 changes: 2 additions & 0 deletions scripts/rollup/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ const importSideEffects = Object.freeze({
'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
scheduler: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'scheduler/tracing': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'react-dom/server': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
});

// Bundles exporting globals that other modules rely on.
const knownGlobals = Object.freeze({
react: 'React',
'react-dom': 'ReactDOM',
'react-dom/server': 'ReactDOMServer',
'react-interactions/events/keyboard': 'ReactEventsKeyboard',
'react-interactions/events/tap': 'ReactEventsTap',
scheduler: 'Scheduler',
Expand Down

0 comments on commit b36dfdf

Please sign in to comment.