@samitouri / QOS-React-2 / commits / d8e49f2af8

Use setTimeout to schedule work on the server in Edge environments (#26348)

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.

Sebastian Markbåge committed Mar 8, 2023 at 15:34 UTC d8e49f2af84c810457eb81ac7fe68fd0fdece859
3 files changed +9 -1
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
+4
@@ -15,6 +15,10 @@ global.ReadableStream =
15 global.TextEncoder = require('util').TextEncoder;
16 global.TextDecoder = require('util').TextDecoder;
17
18 +// Don't wait before processing work on the server.
19 +// TODO: we can replace this with FlightServer.act().
20 +global.setTimeout = cb => cb();
21 +
22 let clientExports;
23 let webpackMap;
24 let webpackModules;
packages/react-server/src/ReactServerStreamConfigEdge.js
+1 -1
@@ -13,7 +13,7 @@ export type PrecomputedChunk = Uint8Array;
13 export opaque type Chunk = Uint8Array;
14
15 export function scheduleWork(callback: () => void) {
16 - callback();
16 + setTimeout(callback, 0);
17 }
18
19 export function flushBuffered(destination: Destination) {
packages/react/src/__tests__/ReactFetchEdge-test.js
+4
@@ -20,6 +20,10 @@ global.Response = require('node-fetch').Response;
20 // Patch for Edge environments for global scope
21 global.AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;
22
23 +// Don't wait before processing work on the server.
24 +// TODO: we can replace this with FlightServer.act().
25 +global.setTimeout = cb => cb();
26 +
27 let fetchCount = 0;
28 async function fetchMock(resource, options) {
29 fetchCount++;