@samitouri / QOS-React-1 / commits / c5b9375767

[Fizz] Only compute component stacks in DEV and prerenders (#27850)

If you have a lot of intentional throws (or postpones) from client-only rendering then computing the stack is too much.

Sebastian Markbåge committed Dec 19, 2023 at 18:04 UTC c5b9375767e2c4102d7e5559d383523736f1c902
1 file changed +20 -11
packages/react-server/src/ReactFizzServer.js
+20 -11
@@ -769,8 +769,17 @@ export type PostponeInfo = ThrownInfo;
769 // during prerender in Prod. The reason for this is that the stack is useful for prerender where the timeliness
770 // of the request is less critical than the observability of the execution. For renders and resumes however we
771 // prioritize speed of the request.
772 -function getThrownInfo(node: null | ComponentStackNode): ThrownInfo {
773 - if (node) {
772 +function getThrownInfo(
773 + request: Request,
774 + node: null | ComponentStackNode,
775 +): ThrownInfo {
776 + if (
777 + node &&
778 + // Always produce a stack in dev
779 + (__DEV__ ||
780 + // Produce a stack in prod if we're in a prerender
781 + request.trackedPostpones !== null)
782 + ) {
783 return {
784 componentStack: getStackFromNode(node),
785 };
@@ -968,7 +977,7 @@ function renderSuspenseBoundary(
977 } catch (error: mixed) {
978 contentRootSegment.status = ERRORED;
979 newBoundary.status = CLIENT_RENDERED;
971 - const thrownInfo = getThrownInfo(task.componentStack);
980 + const thrownInfo = getThrownInfo(request, task.componentStack);
981 let errorDigest;
982 if (
983 enablePostpone &&
@@ -1117,7 +1126,7 @@ function replaySuspenseBoundary(
1126 }
1127 } catch (error: mixed) {
1128 resumedBoundary.status = CLIENT_RENDERED;
1120 - const thrownInfo = getThrownInfo(task.componentStack);
1129 + const thrownInfo = getThrownInfo(request, task.componentStack);
1130 let errorDigest;
1131 if (
1132 enablePostpone &&
@@ -2088,7 +2097,7 @@ function replayElement(
2097 // in the original prerender. What's unable to complete is the child
2098 // replay nodes which might be Suspense boundaries which are able to
2099 // absorb the error and we can still continue with siblings.
2091 - const thrownInfo = getThrownInfo(task.componentStack);
2100 + const thrownInfo = getThrownInfo(request, task.componentStack);
2101 erroredReplay(
2102 request,
2103 task.blockedBoundary,
@@ -2424,7 +2433,7 @@ function replayFragment(
2433 // replay nodes which might be Suspense boundaries which are able to
2434 // absorb the error and we can still continue with siblings.
2435 // This is an error, stash the component stack if it is null.
2427 - const thrownInfo = getThrownInfo(task.componentStack);
2436 + const thrownInfo = getThrownInfo(request, task.componentStack);
2437 erroredReplay(
2438 request,
2439 task.blockedBoundary,
@@ -2888,7 +2897,7 @@ function renderNode(
2897 const trackedPostpones = request.trackedPostpones;
2898
2899 const postponeInstance: Postpone = (x: any);
2891 - const thrownInfo = getThrownInfo(task.componentStack);
2900 + const thrownInfo = getThrownInfo(request, task.componentStack);
2901 const postponedSegment = injectPostponedHole(
2902 request,
2903 ((task: any): RenderTask), // We don't use ReplayTasks in prerenders.
@@ -3168,7 +3177,7 @@ function abortTask(task: Task, request: Request, error: mixed): void {
3177 boundary.status = CLIENT_RENDERED;
3178 // We construct an errorInfo from the boundary's componentStack so the error in dev will indicate which
3179 // boundary the message is referring to
3171 - const errorInfo = getThrownInfo(task.componentStack);
3180 + const errorInfo = getThrownInfo(request, task.componentStack);
3181 const errorDigest = logRecoverableError(request, error, errorInfo);
3182 let errorMessage = error;
3183 if (__DEV__) {
@@ -3470,7 +3479,7 @@ function retryRenderTask(
3479 task.abortSet.delete(task);
3480 const postponeInstance: Postpone = (x: any);
3481
3473 - const postponeInfo = getThrownInfo(task.componentStack);
3482 + const postponeInfo = getThrownInfo(request, task.componentStack);
3483 logPostpone(request, postponeInstance.message, postponeInfo);
3484 trackPostpone(request, trackedPostpones, task, segment);
3485 finishedTask(request, task.blockedBoundary, segment);
@@ -3478,7 +3487,7 @@ function retryRenderTask(
3487 }
3488 }
3489
3481 - const errorInfo = getThrownInfo(task.componentStack);
3490 + const errorInfo = getThrownInfo(request, task.componentStack);
3491 task.abortSet.delete(task);
3492 segment.status = ERRORED;
3493 erroredTask(request, task.blockedBoundary, x, errorInfo);
@@ -3562,7 +3571,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void {
3571 }
3572 task.replay.pendingTasks--;
3573 task.abortSet.delete(task);
3565 - const errorInfo = getThrownInfo(task.componentStack);
3574 + const errorInfo = getThrownInfo(request, task.componentStack);
3575 erroredReplay(
3576 request,
3577 task.blockedBoundary,