@samitouri / QOS-React-2 / commits / 8e9de898d3

[Flight] Add option to replay console logs or not (#30207)

Defaults to true in browser builds, otherwise defaults to false. The assumption is that the server logs will already contain a log from the original Flight server. We currently always replay console logs but this leads to duplicates on the server by default when you use SSR, because the Flight Client on the server replays the logs. This can be nice since those logs gets badged. It can also be nice if they're running in separate servers but when they're logging to the same stream it's annoying. Which is really the typical set up so we should just make that the default but leave it configurable.

Sebastian Markbåge committed Jul 4, 2024 at 12:15 UTC 8e9de898d3a8a0945fcdc1a02959560bce2bbc30
11 files changed +36 -1
packages/react-client/src/ReactFlightClient.js
+9
@@ -250,6 +250,7 @@ export type Response = {
250 _tempRefs: void | TemporaryReferenceSet, // the set temporary references can be resolved from
251 _debugRootTask?: null | ConsoleTask, // DEV-only
252 _debugFindSourceMapURL?: void | FindSourceMapURLCallback, // DEV-only
253 + _replayConsole: boolean, // DEV-only
254 };
255
256 function readChunk<T>(chunk: SomeChunk<T>): T {
@@ -1278,6 +1279,7 @@ function ResponseInstance(
1279 nonce: void | string,
1280 temporaryReferences: void | TemporaryReferenceSet,
1281 findSourceMapURL: void | FindSourceMapURLCallback,
1282 + replayConsole: boolean,
1283 ) {
1284 const chunks: Map<number, SomeChunk<any>> = new Map();
1285 this._bundlerConfig = bundlerConfig;
@@ -1304,6 +1306,7 @@ function ResponseInstance(
1306 }
1307 if (__DEV__) {
1308 this._debugFindSourceMapURL = findSourceMapURL;
1309 + this._replayConsole = replayConsole;
1310 }
1311 // Don't inline this call because it causes closure to outline the call above.
1312 this._fromJSON = createFromJSONCallback(this);
@@ -1317,6 +1320,7 @@ export function createResponse(
1320 nonce: void | string,
1321 temporaryReferences: void | TemporaryReferenceSet,
1322 findSourceMapURL: void | FindSourceMapURLCallback,
1323 + replayConsole: boolean,
1324 ): Response {
1325 // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
1326 return new ResponseInstance(
@@ -1327,6 +1331,7 @@ export function createResponse(
1331 nonce,
1332 temporaryReferences,
1333 findSourceMapURL,
1334 + replayConsole,
1335 );
1336 }
1337
@@ -2034,6 +2039,10 @@ function resolveConsoleEntry(
2039 );
2040 }
2041
2042 + if (!response._replayConsole) {
2043 + return;
2044 + }
2045 +
2046 const payload: [string, string, null | ReactComponentInfo, string, mixed] =
2047 parseModel(response, value);
2048 const methodName = payload[0];
packages/react-html/src/ReactHTMLServer.js
+1
@@ -179,6 +179,7 @@ export function renderToMarkup(
179 undefined,
180 undefined,
181 undefined,
182 + false,
183 );
184 const resumableState = createResumableState(
185 options ? options.identifierPrefix : undefined,
packages/react-noop-renderer/src/ReactNoopFlightClient.js
+10 -1
@@ -50,7 +50,16 @@ const {createResponse, processBinaryChunk, getRoot, close} = ReactFlightClient({
50 });
51
52 function read<T>(source: Source): Thenable<T> {
53 - const response = createResponse(source, null);
53 + const response = createResponse(
54 + source,
55 + null,
56 + undefined,
57 + undefined,
58 + undefined,
59 + undefined,
60 + undefined,
61 + true,
62 + );
63 for (let i = 0; i < source.length; i++) {
64 processBinaryChunk(response, source[i], 0);
65 }
packages/react-server-dom-esm/src/ReactFlightDOMClientBrowser.js
+2
@@ -42,6 +42,7 @@ export type Options = {
42 callServer?: CallServerCallback,
43 temporaryReferences?: TemporaryReferenceSet,
44 findSourceMapURL?: FindSourceMapURLCallback,
45 + replayConsoleLogs?: boolean,
46 };
47
48 function createResponseFromOptions(options: void | Options) {
@@ -57,6 +58,7 @@ function createResponseFromOptions(options: void | Options) {
58 __DEV__ && options && options.findSourceMapURL
59 ? options.findSourceMapURL
60 : undefined,
61 + __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true
62 );
63 }
64
packages/react-server-dom-esm/src/ReactFlightDOMClientNode.js
+2
@@ -50,6 +50,7 @@ export type Options = {
50 nonce?: string,
51 encodeFormAction?: EncodeFormActionCallback,
52 findSourceMapURL?: FindSourceMapURLCallback,
53 + replayConsoleLogs?: boolean,
54 };
55
56 function createFromNodeStream<T>(
@@ -68,6 +69,7 @@ function createFromNodeStream<T>(
69 __DEV__ && options && options.findSourceMapURL
70 ? options.findSourceMapURL
71 : undefined,
72 + __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
73 );
74 stream.on('data', chunk => {
75 processBinaryChunk(response, chunk);
packages/react-server-dom-turbopack/src/ReactFlightDOMClientBrowser.js
+2
@@ -41,6 +41,7 @@ export type Options = {
41 callServer?: CallServerCallback,
42 temporaryReferences?: TemporaryReferenceSet,
43 findSourceMapURL?: FindSourceMapURLCallback,
44 + replayConsoleLogs?: boolean,
45 };
46
47 function createResponseFromOptions(options: void | Options) {
@@ -56,6 +57,7 @@ function createResponseFromOptions(options: void | Options) {
57 __DEV__ && options && options.findSourceMapURL
58 ? options.findSourceMapURL
59 : undefined,
60 + __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true
61 );
62 }
63
packages/react-server-dom-turbopack/src/ReactFlightDOMClientEdge.js
+2
@@ -71,6 +71,7 @@ export type Options = {
71 encodeFormAction?: EncodeFormActionCallback,
72 temporaryReferences?: TemporaryReferenceSet,
73 findSourceMapURL?: FindSourceMapURLCallback,
74 + replayConsoleLogs?: boolean,
75 };
76
77 function createResponseFromOptions(options: Options) {
@@ -86,6 +87,7 @@ function createResponseFromOptions(options: Options) {
87 __DEV__ && options && options.findSourceMapURL
88 ? options.findSourceMapURL
89 : undefined,
90 + __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
91 );
92 }
93
packages/react-server-dom-turbopack/src/ReactFlightDOMClientNode.js
+2
@@ -60,6 +60,7 @@ export type Options = {
60 nonce?: string,
61 encodeFormAction?: EncodeFormActionCallback,
62 findSourceMapURL?: FindSourceMapURLCallback,
63 + replayConsoleLogs?: boolean,
64 };
65
66 function createFromNodeStream<T>(
@@ -77,6 +78,7 @@ function createFromNodeStream<T>(
78 __DEV__ && options && options.findSourceMapURL
79 ? options.findSourceMapURL
80 : undefined,
81 + __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
82 );
83 stream.on('data', chunk => {
84 processBinaryChunk(response, chunk);
packages/react-server-dom-webpack/src/ReactFlightDOMClientBrowser.js
+2
@@ -41,6 +41,7 @@ export type Options = {
41 callServer?: CallServerCallback,
42 temporaryReferences?: TemporaryReferenceSet,
43 findSourceMapURL?: FindSourceMapURLCallback,
44 + replayConsoleLogs?: boolean,
45 };
46
47 function createResponseFromOptions(options: void | Options) {
@@ -56,6 +57,7 @@ function createResponseFromOptions(options: void | Options) {
57 __DEV__ && options && options.findSourceMapURL
58 ? options.findSourceMapURL
59 : undefined,
60 + __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true
61 );
62 }
63
packages/react-server-dom-webpack/src/ReactFlightDOMClientEdge.js
+2
@@ -71,6 +71,7 @@ export type Options = {
71 encodeFormAction?: EncodeFormActionCallback,
72 temporaryReferences?: TemporaryReferenceSet,
73 findSourceMapURL?: FindSourceMapURLCallback,
74 + replayConsoleLogs?: boolean,
75 };
76
77 function createResponseFromOptions(options: Options) {
@@ -86,6 +87,7 @@ function createResponseFromOptions(options: Options) {
87 __DEV__ && options && options.findSourceMapURL
88 ? options.findSourceMapURL
89 : undefined,
90 + __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
91 );
92 }
93
packages/react-server-dom-webpack/src/ReactFlightDOMClientNode.js
+2
@@ -61,6 +61,7 @@ export type Options = {
61 nonce?: string,
62 encodeFormAction?: EncodeFormActionCallback,
63 findSourceMapURL?: FindSourceMapURLCallback,
64 + replayConsoleLogs?: boolean,
65 };
66
67 function createFromNodeStream<T>(
@@ -78,6 +79,7 @@ function createFromNodeStream<T>(
79 __DEV__ && options && options.findSourceMapURL
80 ? options.findSourceMapURL
81 : undefined,
82 + __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
83 );
84 stream.on('data', chunk => {
85 if (typeof chunk === 'string') {