mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
1d25aa5787
* [Fizz] Add Flow/Jest/Rollup build infra Add a new package for react-stream which allows for custom server renderer outputs. I picked the name because it's a reasonable name but also because the npm name is currently owned by a friend of the project. The react-dom build has its own inlined server renderer under the name `react-dom/fizz`. There is also a noop renderer to be used for testing. At some point we might add a public one to test-renderer but for now I don't want to have to think about public API design for the tests. * Add FormatConfig too We need to separate the format (DOM, React Native, etc) from the host running the server (Node, Browser, etc). * Basic wiring between Node, Noop and DOM configs The Node DOM API is pipeToNodeStream which accepts a writable stream. * Merge host and format config in dynamic react-stream entry point Simpler API this way but also avoids having to fork the wrapper config. Fixes noop builds. * Add setImmediate/Buffer globals to lint config Used by the server renderer * Properly include fizz.node.js Also use forwarding to it from fizz.js in builds so that tests covers this. * Make react-stream private since we're not ready to publish or even name it yet * Rename Renderer -> Streamer * Prefix react-dom/fizz with react-dom/unstable-fizz * Add Fizz Browser host config This lets Fizz render to WHATWG streams. E.g. for rendering in a Service Worker. I added react-dom/unstable-fizz.browser as the entry point for this. Since we now have two configurations of DOM. I had to add another inlinedHostConfigs configuration called `dom-browser`. The reconciler treats this configuration the same as `dom`. For stream it checks against the ReactFizzHostConfigBrowser instead of the Node one. * Add Fizz Browser Fixture This is for testing server rendering - on the client. * Lower version number to detach it from react-reconciler version
86 lines
2.0 KiB
JavaScript
86 lines
2.0 KiB
JavaScript
/**
|
|
* 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 {Destination} from './ReactFizzHostConfig';
|
|
import type {ReactNodeList} from 'shared/ReactTypes';
|
|
|
|
import {
|
|
scheduleWork,
|
|
beginWriting,
|
|
writeChunk,
|
|
completeWriting,
|
|
flushBuffered,
|
|
close,
|
|
} from './ReactFizzHostConfig';
|
|
import {formatChunk} from './ReactFizzFormatConfig';
|
|
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
|
|
|
|
type OpaqueRequest = {
|
|
destination: Destination,
|
|
children: ReactNodeList,
|
|
completedChunks: Array<Uint8Array>,
|
|
flowing: boolean,
|
|
};
|
|
|
|
export function createRequest(
|
|
children: ReactNodeList,
|
|
destination: Destination,
|
|
): OpaqueRequest {
|
|
return {destination, children, completedChunks: [], flowing: false};
|
|
}
|
|
|
|
function performWork(request: OpaqueRequest): void {
|
|
let element = (request.children: any);
|
|
request.children = null;
|
|
if (element && element.$$typeof !== REACT_ELEMENT_TYPE) {
|
|
return;
|
|
}
|
|
let type = element.type;
|
|
let props = element.props;
|
|
if (typeof type !== 'string') {
|
|
return;
|
|
}
|
|
request.completedChunks.push(formatChunk(type, props));
|
|
if (request.flowing) {
|
|
flushCompletedChunks(request);
|
|
}
|
|
|
|
flushBuffered(request.destination);
|
|
}
|
|
|
|
function flushCompletedChunks(request: OpaqueRequest) {
|
|
let destination = request.destination;
|
|
let chunks = request.completedChunks;
|
|
request.completedChunks = [];
|
|
|
|
beginWriting(destination);
|
|
try {
|
|
for (let i = 0; i < chunks.length; i++) {
|
|
let chunk = chunks[i];
|
|
writeChunk(destination, chunk);
|
|
}
|
|
} finally {
|
|
completeWriting(destination);
|
|
}
|
|
close(destination);
|
|
}
|
|
|
|
export function startWork(request: OpaqueRequest): void {
|
|
request.flowing = true;
|
|
scheduleWork(() => performWork(request));
|
|
}
|
|
|
|
export function startFlowing(
|
|
request: OpaqueRequest,
|
|
desiredBytes: number,
|
|
): void {
|
|
request.flowing = false;
|
|
flushCompletedChunks(request);
|
|
}
|