From ab24f643d0809ee09a7499862fef135fb09a0225 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Wed, 21 Aug 2024 07:55:56 -0700 Subject: [PATCH] [Fizz] use microtasks rather than tasks when scheduling work while prerendering (#30770) Similar to https://github.com/facebook/react/pull/30768 we want to schedule work during prerendering in microtasks both for the root task and pings. We continue to schedule flushes as Tasks to allow as much work to be batched up as possible. --- packages/react-server/src/ReactFizzServer.js | 27 +++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index daea492db5..7ccbd65d16 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -38,6 +38,7 @@ import {describeObjectForErrorMessage} from 'shared/ReactSerializationErrors'; import { scheduleWork, + scheduleMicrotask, beginWriting, writeChunk, writeChunkAndReturn, @@ -669,7 +670,11 @@ function pingTask(request: Request, task: Task): void { pingedTasks.push(task); if (request.pingedTasks.length === 1) { request.flushScheduled = request.destination !== null; - scheduleWork(() => performWork(request)); + if (request.trackedPostpones !== null) { + scheduleMicrotask(() => performWork(request)); + } else { + scheduleWork(() => performWork(request)); + } } } @@ -4893,12 +4898,22 @@ function flushCompletedQueues( export function startWork(request: Request): void { request.flushScheduled = request.destination !== null; - if (supportsRequestStorage) { - scheduleWork(() => requestStorage.run(request, performWork, request)); + if (request.trackedPostpones !== null) { + // When prerendering we use microtasks for pinging work + if (supportsRequestStorage) { + scheduleMicrotask(() => + requestStorage.run(request, performWork, request), + ); + } else { + scheduleMicrotask(() => performWork(request)); + } } else { - scheduleWork(() => performWork(request)); - } - if (request.trackedPostpones === null) { + // When rendering/resuming we use regular tasks and we also emit early preloads + if (supportsRequestStorage) { + scheduleWork(() => requestStorage.run(request, performWork, request)); + } else { + scheduleWork(() => performWork(request)); + } // this is either a regular render or a resume. For regular render we want // to call emitEarlyPreloads after the first performWork because we want // are responding to a live request and need to balance sending something early