mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
We rely heavily on being able to batch rendering after multiple fetches etc. have completed on the server. However, we only do this in the Node.js build. Node.js `setImmediate` has the exact semantics we need. To be after the current cycle of I/O so that we can collect after all those I/O events already in the queue has been processed. This doesn't exist in standard browsers, so we ended up not using it there. We could've used `setTimeout` but that risks being throttled which would severely negatively affect the performance so we just did it synchronously there. We probably could just use the `scheduler` there. Now we have a separate build for Edge where `setTimeout(..., 0)` actually behaves like `setImmediate` which is what we want. So we can just use that in that build. @Jarred-Sumner not sure what you want for Bun.
103 lines
3.0 KiB
JavaScript
103 lines
3.0 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @emails react-core
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
// Polyfills for test environment
|
|
global.ReadableStream =
|
|
require('web-streams-polyfill/ponyfill/es6').ReadableStream;
|
|
global.TextEncoder = require('util').TextEncoder;
|
|
global.TextDecoder = require('util').TextDecoder;
|
|
|
|
// Don't wait before processing work on the server.
|
|
// TODO: we can replace this with FlightServer.act().
|
|
global.setTimeout = cb => cb();
|
|
|
|
let clientExports;
|
|
let webpackMap;
|
|
let webpackModules;
|
|
let React;
|
|
let ReactDOMServer;
|
|
let ReactServerDOMWriter;
|
|
let ReactServerDOMReader;
|
|
let use;
|
|
|
|
describe('ReactFlightDOMEdge', () => {
|
|
beforeEach(() => {
|
|
jest.resetModules();
|
|
const WebpackMock = require('./utils/WebpackMock');
|
|
clientExports = WebpackMock.clientExports;
|
|
webpackMap = WebpackMock.webpackMap;
|
|
webpackModules = WebpackMock.webpackModules;
|
|
React = require('react');
|
|
ReactDOMServer = require('react-dom/server.edge');
|
|
ReactServerDOMWriter = require('react-server-dom-webpack/server.edge');
|
|
ReactServerDOMReader = require('react-server-dom-webpack/client.edge');
|
|
use = React.use;
|
|
});
|
|
|
|
async function readResult(stream) {
|
|
const reader = stream.getReader();
|
|
let result = '';
|
|
while (true) {
|
|
const {done, value} = await reader.read();
|
|
if (done) {
|
|
return result;
|
|
}
|
|
result += Buffer.from(value).toString('utf8');
|
|
}
|
|
}
|
|
|
|
// @gate enableUseHook
|
|
it('should allow an alternative module mapping to be used for SSR', async () => {
|
|
function ClientComponent() {
|
|
return <span>Client Component</span>;
|
|
}
|
|
// The Client build may not have the same IDs as the Server bundles for the same
|
|
// component.
|
|
const ClientComponentOnTheClient = clientExports(ClientComponent);
|
|
const ClientComponentOnTheServer = clientExports(ClientComponent);
|
|
|
|
// In the SSR bundle this module won't exist. We simulate this by deleting it.
|
|
const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;
|
|
delete webpackModules[clientId];
|
|
|
|
// Instead, we have to provide a translation from the client meta data to the SSR
|
|
// meta data.
|
|
const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];
|
|
const translationMap = {
|
|
[clientId]: {
|
|
'*': ssrMetadata,
|
|
},
|
|
};
|
|
|
|
function App() {
|
|
return <ClientComponentOnTheClient />;
|
|
}
|
|
|
|
const stream = ReactServerDOMWriter.renderToReadableStream(
|
|
<App />,
|
|
webpackMap,
|
|
);
|
|
const response = ReactServerDOMReader.createFromReadableStream(stream, {
|
|
moduleMap: translationMap,
|
|
});
|
|
|
|
function ClientRoot() {
|
|
return use(response);
|
|
}
|
|
|
|
const ssrStream = await ReactDOMServer.renderToReadableStream(
|
|
<ClientRoot />,
|
|
);
|
|
const result = await readResult(ssrStream);
|
|
expect(result).toEqual('<span>Client Component</span>');
|
|
});
|
|
});
|