[Flight] Bypass caches in Flight fixture if requested (#33445)
Hendrik Liebau committed
Jun 6, 2025 at 06:42 UTC
b1759882c0b8045aff27fa9e41600534d396f69c
3 files changed
+21
-15
fixtures/flight/server/global.js
+3
@@ -101,6 +101,9 @@ async function renderApp(req, res, next) {
101
} else if (req.get('Content-type')) {
102
proxiedHeaders['Content-type'] = req.get('Content-type');
103
}
104
+ if (req.headers['cache-control']) {
105
+ proxiedHeaders['Cache-Control'] = req.get('cache-control');
106
+ }
107
108
const requestsPrerender = req.path === '/prerender';
109
fixtures/flight/server/region.js
+12
-9
@@ -50,7 +50,7 @@ const {readFile} = require('fs').promises;
50
51
const React = require('react');
52
53
-async function renderApp(res, returnValue, formState) {
53
+async function renderApp(res, returnValue, formState, noCache) {
54
const {renderToPipeableStream} = await import(
55
'react-server-dom-webpack/server'
56
);
@@ -97,7 +97,7 @@ async function renderApp(res, returnValue, formState) {
97
key: filename,
98
})
99
),
100
- React.createElement(App)
100
+ React.createElement(App, {noCache})
101
);
102
// For client-invoked server actions we refresh the tree and return a return value.
103
const payload = {root, returnValue, formState};
@@ -105,7 +105,7 @@ async function renderApp(res, returnValue, formState) {
105
pipe(res);
106
}
107
108
-async function prerenderApp(res, returnValue, formState) {
108
+async function prerenderApp(res, returnValue, formState, noCache) {
109
const {unstable_prerenderToNodeStream: prerenderToNodeStream} = await import(
110
'react-server-dom-webpack/static'
111
);
@@ -152,7 +152,7 @@ async function prerenderApp(res, returnValue, formState) {
152
key: filename,
153
})
154
),
155
- React.createElement(App, {prerender: true})
155
+ React.createElement(App, {prerender: true, noCache})
156
);
157
// For client-invoked server actions we refresh the tree and return a return value.
158
const payload = {root, returnValue, formState};
@@ -161,14 +161,17 @@ async function prerenderApp(res, returnValue, formState) {
161
}
162
163
app.get('/', async function (req, res) {
164
+ const noCache = req.get('cache-control') === 'no-cache';
165
+
166
if ('prerender' in req.query) {
165
- await prerenderApp(res, null, null);
167
+ await prerenderApp(res, null, null, noCache);
168
} else {
167
- await renderApp(res, null, null);
169
+ await renderApp(res, null, null, noCache);
170
}
171
});
172
173
app.post('/', bodyParser.text(), async function (req, res) {
174
+ const noCache = req.headers['cache-control'] === 'no-cache';
175
const {decodeReply, decodeReplyFromBusboy, decodeAction, decodeFormState} =
176
await import('react-server-dom-webpack/server');
177
const serverReference = req.get('rsc-action');
@@ -201,7 +204,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
204
// We handle the error on the client
205
}
206
// Refresh the client and return the value
204
- renderApp(res, result, null);
207
+ renderApp(res, result, null, noCache);
208
} else {
209
// This is the progressive enhancement case
210
const UndiciRequest = require('undici').Request;
@@ -217,11 +220,11 @@ app.post('/', bodyParser.text(), async function (req, res) {
220
// Wait for any mutations
221
const result = await action();
222
const formState = decodeFormState(result, formData);
220
- renderApp(res, null, formState);
223
+ renderApp(res, null, formState, noCache);
224
} catch (x) {
225
const {setServerState} = await import('../src/ServerState.js');
226
setServerState('Error: ' + x.message);
224
- renderApp(res, null, null);
227
+ renderApp(res, null, null, noCache);
228
}
229
}
230
});
fixtures/flight/src/App.js
+6
-6
@@ -47,8 +47,8 @@ async function ThirdPartyComponent() {
47
// Using Web streams for tee'ing convenience here.
48
let cachedThirdPartyReadableWeb;
49
50
-function fetchThirdParty(Component) {
51
- if (cachedThirdPartyReadableWeb) {
50
+function fetchThirdParty(noCache) {
51
+ if (cachedThirdPartyReadableWeb && !noCache) {
52
const [readableWeb1, readableWeb2] = cachedThirdPartyReadableWeb.tee();
53
cachedThirdPartyReadableWeb = readableWeb1;
54
@@ -79,16 +79,16 @@ function fetchThirdParty(Component) {
79
return result;
80
}
81
82
-async function ServerComponent() {
82
+async function ServerComponent({noCache}) {
83
await new Promise(resolve => setTimeout(() => resolve('deferred text'), 50));
84
- return await fetchThirdParty();
84
+ return fetchThirdParty(noCache);
85
}
86
87
-export default async function App({prerender}) {
87
+export default async function App({prerender, noCache}) {
88
const res = await fetch('http://localhost:3001/todos');
89
const todos = await res.json();
90
91
- const dedupedChild = <ServerComponent />;
91
+ const dedupedChild = <ServerComponent noCache={noCache} />;
92
const message = getServerState();
93
return (
94
<html lang="en">