vite-plugin-react-server 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +10 -5
- package/dist/plugin/config/defaults.d.ts +1 -1
- package/dist/plugin/config/defaults.js +1 -1
- package/dist/plugin/config/defaults.js.map +1 -1
- package/dist/plugin/config/resolveAutoDiscover.d.ts +2 -0
- package/dist/plugin/config/resolveAutoDiscover.d.ts.map +1 -1
- package/dist/plugin/config/resolveAutoDiscover.js +15 -18
- package/dist/plugin/config/resolveAutoDiscover.js.map +1 -1
- package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
- package/dist/plugin/config/resolveOptions.js +4 -1
- package/dist/plugin/config/resolveOptions.js.map +1 -1
- package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
- package/dist/plugin/config/resolveUserConfig.js +56 -29
- package/dist/plugin/config/resolveUserConfig.js.map +1 -1
- package/dist/plugin/helpers/collectBundleManifestCss.d.ts +0 -6
- package/dist/plugin/helpers/collectBundleManifestCss.d.ts.map +1 -1
- package/dist/plugin/helpers/collectBundleManifestCss.js +2 -110
- package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts +2 -1
- package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts.map +1 -1
- package/dist/plugin/helpers/collectViteModuleGraphCss.js +19 -18
- package/dist/plugin/helpers/collectViteModuleGraphCss.js.map +1 -1
- package/dist/plugin/helpers/createCssProps.d.ts +3 -2
- package/dist/plugin/helpers/createCssProps.d.ts.map +1 -1
- package/dist/plugin/helpers/createCssProps.js +10 -6
- package/dist/plugin/helpers/createCssProps.js.map +1 -1
- package/dist/plugin/helpers/createRscStream.d.ts.map +1 -1
- package/dist/plugin/helpers/createRscStream.js +37 -43
- package/dist/plugin/helpers/createRscStream.js.map +1 -1
- package/dist/plugin/helpers/formatMetrics.d.ts +4 -0
- package/dist/plugin/helpers/formatMetrics.d.ts.map +1 -0
- package/dist/plugin/helpers/formatMetrics.js +24 -0
- package/dist/plugin/helpers/tryManifest.d.ts.map +1 -1
- package/dist/plugin/helpers/tryManifest.js +0 -8
- package/dist/plugin/helpers/tryManifest.js.map +1 -1
- package/dist/plugin/html.js +1 -1
- package/dist/plugin/html.js.map +1 -1
- package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
- package/dist/plugin/loader/createBuildLoader.js +2 -0
- package/dist/plugin/loader/createBuildLoader.js.map +1 -1
- package/dist/plugin/metrics/formatMetrics.d.ts +4 -0
- package/dist/plugin/metrics/formatMetrics.d.ts.map +1 -0
- package/dist/plugin/metrics/formatMetrics.js +39 -0
- package/dist/plugin/metrics/formatMetrics.js.map +1 -0
- package/dist/plugin/metrics/index.d.ts +3 -0
- package/dist/plugin/metrics/index.d.ts.map +1 -0
- package/dist/plugin/metrics/index.js +1 -0
- package/dist/plugin/metrics.js +7 -0
- package/dist/plugin/metrics.js.map +1 -0
- package/dist/plugin/react-client/createWorkerStream.d.ts +16 -0
- package/dist/plugin/react-client/createWorkerStream.d.ts.map +1 -0
- package/dist/plugin/react-client/createWorkerStream.js +88 -0
- package/dist/plugin/react-client/createWorkerStream.js.map +1 -0
- package/dist/plugin/react-client/plugin.d.ts.map +1 -1
- package/dist/plugin/react-client/plugin.js +4 -1
- package/dist/plugin/react-client/plugin.js.map +1 -1
- package/dist/plugin/react-client/restartWorker.d.ts +6 -0
- package/dist/plugin/react-client/restartWorker.d.ts.map +1 -0
- package/dist/plugin/react-client/restartWorker.js +53 -0
- package/dist/plugin/react-client/restartWorker.js.map +1 -0
- package/dist/plugin/react-client/server.d.ts +5 -4
- package/dist/plugin/react-client/server.d.ts.map +1 -1
- package/dist/plugin/react-client/server.js +79 -110
- package/dist/plugin/react-client/server.js.map +1 -1
- package/dist/plugin/react-server/server.d.ts.map +1 -1
- package/dist/plugin/react-server/server.js +23 -28
- package/dist/plugin/react-server/server.js.map +1 -1
- package/dist/plugin/react-static/collectHtmlWorkerContent.js +1 -1
- package/dist/plugin/react-static/collectHtmlWorkerContent.js.map +1 -1
- package/dist/plugin/react-static/collectRscContent.js +1 -1
- package/dist/plugin/react-static/collectRscContent.js.map +1 -1
- package/dist/plugin/react-static/configurePreviewServer.d.ts.map +1 -1
- package/dist/plugin/react-static/configurePreviewServer.js +23 -4
- package/dist/plugin/react-static/configurePreviewServer.js.map +1 -1
- package/dist/plugin/react-static/fileWriter.d.ts.map +1 -1
- package/dist/plugin/react-static/fileWriter.js +5 -1
- package/dist/plugin/react-static/fileWriter.js.map +1 -1
- package/dist/plugin/react-static/plugin.d.ts.map +1 -1
- package/dist/plugin/react-static/plugin.js +50 -33
- package/dist/plugin/react-static/plugin.js.map +1 -1
- package/dist/plugin/types.d.ts +6 -7
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/utils/callServer.d.ts +2 -0
- package/dist/plugin/utils/callServer.d.ts.map +1 -0
- package/dist/plugin/utils/callServer.js +26 -0
- package/dist/plugin/utils/callServer.js.map +1 -0
- package/dist/plugin/utils/createReactFetcher.d.ts +7 -0
- package/dist/plugin/utils/createReactFetcher.d.ts.map +1 -0
- package/dist/plugin/utils/createReactFetcher.js +33 -0
- package/dist/plugin/utils/createReactFetcher.js.map +1 -0
- package/dist/plugin/utils/index.d.ts +4 -0
- package/dist/plugin/utils/index.d.ts.map +1 -0
- package/dist/plugin/utils/index.js +3 -0
- package/dist/plugin/utils/pageURL.d.ts +2 -0
- package/dist/plugin/utils/pageURL.d.ts.map +1 -0
- package/dist/plugin/utils/pageURL.js +21 -0
- package/dist/plugin/utils/pageURL.js.map +1 -0
- package/dist/plugin/utils.js +9 -0
- package/dist/plugin/utils.js.map +1 -0
- package/dist/plugin/worker/rsc/handleRender.d.ts +6 -2
- package/dist/plugin/worker/rsc/handleRender.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/handleRender.js +26 -55
- package/dist/plugin/worker/rsc/handleRender.js.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.d.ts +1 -2
- package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.js +45 -2
- package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
- package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/state.js +1 -5
- package/dist/plugin/worker/rsc/state.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -5
- package/plugin/config/defaults.tsx +1 -1
- package/plugin/config/resolveAutoDiscover.ts +17 -22
- package/plugin/config/resolveOptions.ts +5 -1
- package/plugin/config/resolveUserConfig.ts +64 -36
- package/plugin/helpers/collectBundleManifestCss.ts +1 -160
- package/plugin/helpers/collectViteModuleGraphCss.ts +31 -29
- package/plugin/helpers/createCssProps.tsx +22 -11
- package/plugin/helpers/createRscStream.tsx +42 -46
- package/plugin/helpers/formatMetrics.ts +37 -0
- package/plugin/helpers/tryManifest.ts +0 -9
- package/plugin/html.tsx +1 -1
- package/plugin/loader/createBuildLoader.ts +2 -0
- package/plugin/metrics/formatMetrics.ts +37 -0
- package/plugin/metrics/index.ts +2 -0
- package/plugin/react-client/createWorkerStream.ts +107 -0
- package/plugin/react-client/plugin.ts +3 -0
- package/plugin/react-client/restartWorker.ts +65 -0
- package/plugin/react-client/server.ts +97 -146
- package/plugin/react-server/server.ts +24 -29
- package/plugin/react-static/collectHtmlWorkerContent.ts +1 -1
- package/plugin/react-static/collectRscContent.ts +2 -2
- package/plugin/react-static/configurePreviewServer.ts +29 -6
- package/plugin/react-static/fileWriter.ts +5 -1
- package/plugin/react-static/plugin.ts +58 -38
- package/plugin/types.ts +11 -11
- package/plugin/utils/callServer.ts +25 -0
- package/plugin/utils/createReactFetcher.ts +31 -0
- package/plugin/utils/index.ts +3 -0
- package/plugin/utils/pageURL.ts +28 -0
- package/plugin/worker/rsc/handleRender.ts +33 -71
- package/plugin/worker/rsc/messageHandler.tsx +48 -6
- package/plugin/worker/rsc/state.ts +1 -5
|
@@ -4,101 +4,39 @@
|
|
|
4
4
|
* MIT License
|
|
5
5
|
*/
|
|
6
6
|
import 'node:worker_threads';
|
|
7
|
-
import { serializedOptions
|
|
8
|
-
import { createWorker } from '../worker/createWorker.js';
|
|
7
|
+
import { serializedOptions } from '../helpers/serializeUserOptions.js';
|
|
9
8
|
import { getRouteFiles } from '../helpers/getRouteFiles.js';
|
|
10
9
|
import { requestToRoute } from '../helpers/requestToRoute.js';
|
|
10
|
+
import { performance } from 'node:perf_hooks';
|
|
11
|
+
import { createWorkerStream } from './createWorkerStream.js';
|
|
12
|
+
import { restartWorker } from './restartWorker.js';
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
let isRestarting = false;
|
|
14
|
-
async function restartWorker(server, autoDiscoveredFiles, userOptions, hmrChannel) {
|
|
15
|
-
if (isRestarting) return;
|
|
16
|
-
isRestarting = true;
|
|
17
|
-
try {
|
|
18
|
-
if (currentWorker) {
|
|
19
|
-
currentWorker.terminate();
|
|
20
|
-
currentWorker = null;
|
|
21
|
-
}
|
|
22
|
-
const workerResult = await createWorker({
|
|
23
|
-
projectRoot: server.config.root,
|
|
24
|
-
workerPath: userOptions.rscWorkerPath,
|
|
25
|
-
reverseCondition: "react-server",
|
|
26
|
-
currentCondition: "react-client",
|
|
27
|
-
workerData: {
|
|
28
|
-
hmrPort: hmrChannel.port2,
|
|
29
|
-
resolvedConfig: serializedDevServerConfig(server.config),
|
|
30
|
-
userOptions: serializedOptions(userOptions, autoDiscoveredFiles)
|
|
31
|
-
},
|
|
32
|
-
transferList: [hmrChannel.port2]
|
|
33
|
-
});
|
|
34
|
-
if (workerResult.type === "success") {
|
|
35
|
-
currentWorker = workerResult.worker;
|
|
36
|
-
} else if (workerResult.type === "error") {
|
|
37
|
-
server.config.logger.error("Failed to start rsc-worker", {
|
|
38
|
-
error: workerResult.error
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
} finally {
|
|
42
|
-
isRestarting = false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
async function* createWorkerStream(worker, message) {
|
|
46
|
-
let messageHandler;
|
|
47
|
-
let cleanup = () => {
|
|
48
|
-
};
|
|
49
|
-
yield await new Promise((resolve) => {
|
|
50
|
-
messageHandler = (message2) => {
|
|
51
|
-
if (message2.type === "RSC_CHUNK") {
|
|
52
|
-
resolve(message2.chunk);
|
|
53
|
-
}
|
|
54
|
-
if (message2.type === "ERROR") {
|
|
55
|
-
resolve(new Uint8Array());
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
cleanup = () => {
|
|
59
|
-
worker.off("message", messageHandler);
|
|
60
|
-
};
|
|
61
|
-
worker.on("message", messageHandler);
|
|
62
|
-
worker.postMessage({
|
|
63
|
-
type: "RSC_RENDER",
|
|
64
|
-
id: message.route,
|
|
65
|
-
...message
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
while (true) {
|
|
69
|
-
const chunk = await new Promise((resolve) => {
|
|
70
|
-
messageHandler = (message2) => {
|
|
71
|
-
if (message2.type === "RSC_END") {
|
|
72
|
-
cleanup();
|
|
73
|
-
resolve(new Uint8Array());
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
if (message2.type === "RSC_CHUNK") {
|
|
77
|
-
resolve(message2.chunk);
|
|
78
|
-
}
|
|
79
|
-
if (message2.type === "ERROR") {
|
|
80
|
-
cleanup();
|
|
81
|
-
resolve(new Uint8Array());
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
worker.once("message", messageHandler);
|
|
86
|
-
});
|
|
87
|
-
if (chunk.length === 0) {
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
yield chunk;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function handleWorkerRscStream(worker, message) {
|
|
14
|
+
function handleWorkerRscStream(worker, message, logger, onMetrics) {
|
|
94
15
|
return new ReadableStream({
|
|
95
16
|
async start(controller) {
|
|
96
17
|
try {
|
|
97
|
-
for await (const chunk of createWorkerStream(
|
|
18
|
+
for await (const chunk of createWorkerStream(
|
|
19
|
+
worker,
|
|
20
|
+
message,
|
|
21
|
+
logger,
|
|
22
|
+
onMetrics
|
|
23
|
+
)) {
|
|
98
24
|
controller.enqueue(chunk);
|
|
99
25
|
}
|
|
100
26
|
} catch (error) {
|
|
101
|
-
|
|
27
|
+
const err = error instanceof Error ? error : typeof error === "string" ? new Error(error) : typeof error === "object" && error != null ? {
|
|
28
|
+
message: "message" in error ? String(error.message) : "Unknown error",
|
|
29
|
+
stack: "stack" in error ? String(error.stack) : "",
|
|
30
|
+
name: "name" in error ? String(error.name) : "Error"
|
|
31
|
+
} : {
|
|
32
|
+
message: "Unknown error",
|
|
33
|
+
stack: "",
|
|
34
|
+
name: "Error"
|
|
35
|
+
};
|
|
36
|
+
logger.error(err.message, {
|
|
37
|
+
error: err
|
|
38
|
+
});
|
|
39
|
+
controller.error(err);
|
|
102
40
|
} finally {
|
|
103
41
|
controller.close();
|
|
104
42
|
}
|
|
@@ -109,20 +47,22 @@ async function configureWorkerRequestHandler({
|
|
|
109
47
|
server,
|
|
110
48
|
autoDiscoveredFiles,
|
|
111
49
|
userOptions: _userOptions,
|
|
112
|
-
hmrChannel
|
|
50
|
+
hmrChannel,
|
|
51
|
+
onMetrics
|
|
113
52
|
}) {
|
|
114
53
|
let {
|
|
115
54
|
// remove these
|
|
116
|
-
moduleBaseURL: _moduleBaseURL,
|
|
117
55
|
projectRoot: _projectRoot,
|
|
56
|
+
moduleBaseURL: _moduleBaseURL,
|
|
57
|
+
moduleBasePath: _moduleBasePath,
|
|
118
58
|
...handlerUserOptions
|
|
119
59
|
} = _userOptions;
|
|
120
60
|
const handlerOptions = Object.assign({}, handlerUserOptions, {
|
|
121
|
-
moduleBaseURL: typeof server.config.server.host === "string" ? `${server.config.server.https ? "https" : "http"}://${server.config.server.host}:${server.config.server.port}` :
|
|
61
|
+
moduleBaseURL: typeof server.config.server.host === "string" ? `${server.config.server.https ? "https" : "http"}://${server.config.server.host}:${server.config.server.port}` : _moduleBaseURL,
|
|
122
62
|
moduleBasePath: server.config.base === "/" ? "" : server.config.base.endsWith("/") ? server.config.base.slice(0, -1) : server.config.base,
|
|
123
63
|
projectRoot: server.config.root
|
|
124
64
|
});
|
|
125
|
-
await restartWorker(server, autoDiscoveredFiles, handlerOptions, hmrChannel);
|
|
65
|
+
const currentWorker = await restartWorker(server, autoDiscoveredFiles, handlerOptions, hmrChannel);
|
|
126
66
|
const handler = async (req, res, next) => {
|
|
127
67
|
if (!req.url || req.headers.accept !== "text/x-component") return next();
|
|
128
68
|
try {
|
|
@@ -143,10 +83,14 @@ async function configureWorkerRequestHandler({
|
|
|
143
83
|
handlerOptions
|
|
144
84
|
);
|
|
145
85
|
if (routeFiles.type === "error") {
|
|
146
|
-
server.config.logger.error(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
86
|
+
server.config.logger.error(
|
|
87
|
+
`[react-client] Error fetching route files for ${route}`,
|
|
88
|
+
{
|
|
89
|
+
error: routeFiles.error,
|
|
90
|
+
timestamp: true,
|
|
91
|
+
environment: "server"
|
|
92
|
+
}
|
|
93
|
+
);
|
|
150
94
|
return next();
|
|
151
95
|
}
|
|
152
96
|
const { page, props } = routeFiles;
|
|
@@ -157,19 +101,43 @@ async function configureWorkerRequestHandler({
|
|
|
157
101
|
handlerOptions,
|
|
158
102
|
autoDiscoveredFiles
|
|
159
103
|
);
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
104
|
+
const startTime = performance.now();
|
|
105
|
+
const stream = handleWorkerRscStream(
|
|
106
|
+
currentWorker,
|
|
107
|
+
{
|
|
108
|
+
...serializedUserOptions,
|
|
109
|
+
// we make the worker stream aware of the route, pagePath, propsPath
|
|
110
|
+
route,
|
|
111
|
+
pagePath: page,
|
|
112
|
+
propsPath: props,
|
|
113
|
+
// override these at all times to ensure the settings will work for the dev server
|
|
114
|
+
projectRoot: server.config.root,
|
|
115
|
+
build: serializedUserOptions.build,
|
|
116
|
+
manifest: autoDiscoveredFiles.staticManifest,
|
|
117
|
+
cssFiles: /* @__PURE__ */ new Map(),
|
|
118
|
+
globalCss: /* @__PURE__ */ new Map()
|
|
119
|
+
},
|
|
120
|
+
server.config.logger,
|
|
121
|
+
typeof onMetrics === "function" ? (metrics) => {
|
|
122
|
+
const elapsedTime = performance.now() - startTime;
|
|
123
|
+
const formattedMetrics = {
|
|
124
|
+
route,
|
|
125
|
+
htmlSize: 0,
|
|
126
|
+
rscSize: metrics.bytes,
|
|
127
|
+
processingTime: elapsedTime,
|
|
128
|
+
chunks: metrics.chunks,
|
|
129
|
+
chunkRate: metrics.chunks / (elapsedTime / 1e3),
|
|
130
|
+
memoryUsage: process.memoryUsage(),
|
|
131
|
+
streamMetrics: {
|
|
132
|
+
...metrics,
|
|
133
|
+
duration: elapsedTime
|
|
134
|
+
},
|
|
135
|
+
htmlSizes: /* @__PURE__ */ new Map(),
|
|
136
|
+
rscSizes: /* @__PURE__ */ new Map([[route, metrics.bytes]])
|
|
137
|
+
};
|
|
138
|
+
onMetrics(formattedMetrics);
|
|
139
|
+
} : void 0
|
|
140
|
+
);
|
|
173
141
|
const writeStream = new WritableStream({
|
|
174
142
|
write(chunk) {
|
|
175
143
|
res.write(chunk);
|
|
@@ -189,11 +157,12 @@ async function configureWorkerRequestHandler({
|
|
|
189
157
|
res.end();
|
|
190
158
|
}
|
|
191
159
|
});
|
|
192
|
-
let timeout
|
|
193
|
-
|
|
160
|
+
let timeout;
|
|
161
|
+
stream.pipeTo(writeStream);
|
|
162
|
+
timeout = setTimeout(() => {
|
|
163
|
+
server.config.logger.error("RSC render timeout");
|
|
194
164
|
res.end();
|
|
195
165
|
}, 5e3);
|
|
196
|
-
stream.pipeTo(writeStream);
|
|
197
166
|
} catch (error) {
|
|
198
167
|
if (error instanceof Error) {
|
|
199
168
|
server.config.logger.error(error.message, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../../../plugin/react-client/server.ts"],"sourcesContent":["import type { ViteDevServer } from \"vite\";\nimport type {\n AutoDiscoveredFiles,\n RequestHandler,\n ResolvedUserOptions,\n} from \"../types.js\";\nimport type {\n RscWorkerOutputMessage,\n RscRenderMessage,\n} from \"../worker/types.js\";\nimport type { Worker as NodeWorker } from \"node:worker_threads\";\nimport { MessageChannel } from \"node:worker_threads\";\nimport {\n serializedDevServerConfig,\n serializedOptions,\n} from \"../helpers/serializeUserOptions.js\";\nimport { createWorker } from \"../worker/createWorker.js\";\nimport { getRouteFiles } from \"../helpers/getRouteFiles.js\";\nimport { requestToRoute } from \"../helpers/requestToRoute.js\";\n\nlet currentWorker: NodeWorker | null = null;\nlet isRestarting = false;\n\nasync function restartWorker(\n server: ViteDevServer,\n autoDiscoveredFiles: AutoDiscoveredFiles,\n userOptions: ResolvedUserOptions,\n hmrChannel: MessageChannel\n) {\n if (isRestarting) return;\n isRestarting = true;\n\n try {\n // Terminate the current worker if it exists\n if (currentWorker) {\n currentWorker.terminate();\n currentWorker = null;\n }\n\n const workerResult = await createWorker({\n projectRoot: server.config.root,\n workerPath: userOptions.rscWorkerPath,\n reverseCondition: \"react-server\",\n currentCondition: \"react-client\",\n workerData: {\n hmrPort: hmrChannel.port2,\n resolvedConfig: serializedDevServerConfig(server.config),\n userOptions: serializedOptions(userOptions, autoDiscoveredFiles),\n },\n transferList: [hmrChannel.port2],\n });\n\n if (workerResult.type === \"success\") {\n currentWorker = workerResult.worker;\n } else if (workerResult.type === \"error\") {\n server.config.logger.error(\"Failed to start rsc-worker\", {\n error: workerResult.error,\n });\n }\n } finally {\n isRestarting = false;\n }\n}\n\n/**\n * Creates an async generator that yields RSC chunks from the worker.\n * Handles both module requests and RSC streaming.\n *\n * @param worker - The worker thread\n * @param server - The Vite dev server\n * @param message - The RSC render message\n * @param rscWorkerLoaderPort - Optional loader port for module loading\n * @returns An async generator that yields RSC chunks\n */\nasync function* createWorkerStream(\n worker: NodeWorker,\n message: Omit<RscRenderMessage, \"type\" | \"id\">\n): AsyncGenerator<Uint8Array, void, unknown> {\n let messageHandler: (message: RscWorkerOutputMessage) => void;\n let cleanup: () => void = () => {};\n\n // First yield: wait for initial message and handle module requests\n yield await new Promise<Uint8Array>((resolve) => {\n messageHandler = (message: RscWorkerOutputMessage) => {\n if (message.type === \"RSC_CHUNK\") {\n resolve(message.chunk);\n }\n if (message.type === \"ERROR\") {\n resolve(new Uint8Array());\n }\n };\n\n cleanup = () => {\n worker.off(\"message\", messageHandler);\n };\n\n worker.on(\"message\", messageHandler);\n\n // Send the render message to start the RSC stream\n worker.postMessage({\n type: \"RSC_RENDER\",\n id: message.route,\n ...message,\n });\n });\n\n // Subsequent yields: handle RSC chunks until stream ends\n while (true) {\n const chunk = await new Promise<Uint8Array>((resolve) => {\n messageHandler = (message: RscWorkerOutputMessage) => {\n if (message.type === \"RSC_END\") {\n cleanup();\n resolve(new Uint8Array());\n return;\n }\n if (message.type === \"RSC_CHUNK\") {\n resolve(message.chunk);\n }\n if (message.type === \"ERROR\") {\n cleanup();\n resolve(new Uint8Array());\n return;\n }\n };\n worker.once(\"message\", messageHandler);\n });\n\n if (chunk.length === 0) {\n break;\n }\n yield chunk;\n }\n}\n\n/**\n * Handles the RSC stream from the worker.\n * Creates a ReadableStream that pipes RSC chunks to the response.\n *\n * @param worker - The worker thread\n * @param message - The RSC render message\n * @returns A ReadableStream that yields RSC chunks\n */\nexport function handleWorkerRscStream(\n worker: NodeWorker,\n message: Omit<RscRenderMessage, \"type\" | \"id\">\n): ReadableStream<Uint8Array> {\n // Create a ReadableStream from the async generator\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of createWorkerStream(worker, message)) {\n controller.enqueue(chunk);\n }\n } catch (error) {\n controller.error(error);\n } finally {\n controller.close();\n }\n },\n });\n}\n\n/**\n * Configures the worker request handler.\n * @param server - The Vite dev server\n * @param autoDiscoveredFiles - The auto discovered files\n * @param userOptions - The user options\n */\nexport async function configureWorkerRequestHandler({\n server,\n autoDiscoveredFiles,\n userOptions: _userOptions,\n hmrChannel,\n}: {\n server: ViteDevServer;\n autoDiscoveredFiles: AutoDiscoveredFiles;\n userOptions: ResolvedUserOptions;\n hmrChannel: MessageChannel;\n}) {\n let {\n // remove these\n moduleBaseURL: _moduleBaseURL,\n projectRoot: _projectRoot,\n ...handlerUserOptions\n } = _userOptions;\n const handlerOptions = Object.assign({}, handlerUserOptions, {\n moduleBaseURL:\n typeof server.config.server.host === \"string\"\n ? `${server.config.server.https ? \"https\" : \"http\"}://${\n server.config.server.host\n }:${server.config.server.port}`\n : \"\",\n moduleBasePath:\n server.config.base === \"/\"\n ? \"\"\n : server.config.base.endsWith(\"/\")\n ? server.config.base.slice(0, -1)\n : server.config.base,\n projectRoot: server.config.root,\n });\n\n // Start the worker\n await restartWorker(server, autoDiscoveredFiles, handlerOptions, hmrChannel);\n\n // Create the request handler\n const handler: RequestHandler = async (req, res, next) => {\n if (!req.url || req.headers.accept !== \"text/x-component\") return next();\n try {\n if (!currentWorker) {\n server.config.logger.error(\"[react-client] No worker available\");\n return next();\n }\n\n // Get the route from the request\n let route = requestToRoute(req, {\n moduleBasePath: handlerOptions.moduleBasePath,\n build: handlerOptions.build\n });\n if (!route) {\n return next();\n }\n // in the case of the no build.pages and a async Page and or props userOption, we need to await those\n // if they are already autoDiscovered then the promise will resolve immediately\n const routeFiles = await getRouteFiles(\n route,\n autoDiscoveredFiles,\n handlerOptions\n );\n if (routeFiles.type === \"error\") {\n server.config.logger.error(routeFiles.error.message, {\n error: routeFiles.error,\n timestamp: true,\n });\n return next();\n }\n const { page, props } = routeFiles;\n\n // Set up response headers for streaming\n res.setHeader(\"Content-Type\", \"text/x-component; charset=utf-8\");\n res.setHeader(\"Transfer-Encoding\", \"chunked\");\n res.setHeader(\"Connection\", \"keep-alive\");\n const serializedUserOptions = serializedOptions(\n handlerOptions,\n autoDiscoveredFiles\n );\n const stream = handleWorkerRscStream(currentWorker, {\n ...serializedUserOptions,\n // we make the worker stream aware of the route, pagePath, propsPath\n route,\n pagePath: page,\n propsPath: props,\n // override these at all times to ensure the settings will work for the dev server\n projectRoot: server.config.root,\n build: serializedUserOptions.build,\n manifest: autoDiscoveredFiles.staticManifest,\n cssFiles: new Map(),\n globalCss: new Map(),\n });\n const writeStream = new WritableStream({\n write(chunk) {\n res.write(chunk);\n },\n\n close() {\n clearTimeout(timeout);\n res.end();\n },\n abort() {\n clearTimeout(timeout);\n // Restart worker on error\n restartWorker(\n server,\n autoDiscoveredFiles,\n handlerOptions,\n hmrChannel\n );\n res.end();\n },\n })\n let timeout = setTimeout(() => {\n server.config.logger.error(\"[react-client] RSC render timeout\");\n res.end();\n }, 5000);\n\n // Pipe the stream to the response\n stream.pipeTo(writeStream);\n } catch (error) {\n if (error instanceof Error) {\n server.config.logger.error(error.message, {\n error,\n });\n }\n }\n };\n // attach handler to the server\n server.middlewares.use(handler);\n // done\n}\n"],"names":["message"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../../../plugin/react-client/server.ts"],"sourcesContent":["import type { Logger, ViteDevServer } from \"vite\";\nimport type {\n AutoDiscoveredFiles,\n RenderMetrics,\n RequestHandler,\n ResolvedUserOptions,\n StreamMetrics,\n} from \"../types.js\";\nimport type {\n RscRenderMessage,\n} from \"../worker/types.js\";\nimport type { Worker as NodeWorker } from \"node:worker_threads\";\nimport { MessageChannel } from \"node:worker_threads\";\nimport {\n serializedOptions,\n} from \"../helpers/serializeUserOptions.js\";\nimport { getRouteFiles } from \"../helpers/getRouteFiles.js\";\nimport { requestToRoute } from \"../helpers/requestToRoute.js\";\nimport { performance } from \"node:perf_hooks\";\nimport { createWorkerStream } from \"./createWorkerStream.js\";\nimport { restartWorker } from \"./restartWorker.js\";\n\n\n/**\n * Handles the RSC stream from the worker.\n * Creates a ReadableStream that pipes RSC chunks to the response.\n *\n * @param worker - The worker thread\n * @param message - The RSC render message\n * @returns A ReadableStream that yields RSC chunks\n */\nexport function handleWorkerRscStream(\n worker: NodeWorker,\n message: Omit<RscRenderMessage, \"type\" | \"id\">,\n logger: Logger,\n onMetrics?: (metrics: StreamMetrics) => void\n): ReadableStream<Uint8Array> {\n // Create a ReadableStream from the async generator\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of createWorkerStream(\n worker,\n message,\n logger,\n onMetrics\n )) {\n controller.enqueue(chunk);\n }\n } catch (error) {\n const err =\n error instanceof Error\n ? error\n : typeof error === \"string\"\n ? new Error(error)\n : typeof error === \"object\" && error != null\n ? {\n message:\n \"message\" in error ? String(error.message) : \"Unknown error\",\n stack: \"stack\" in error ? String(error.stack) : \"\",\n name: \"name\" in error ? String(error.name) : \"Error\",\n }\n : {\n message: \"Unknown error\",\n stack: \"\",\n name: \"Error\",\n };\n logger.error(err.message, {\n error: err,\n });\n controller.error(err);\n } finally {\n controller.close();\n }\n },\n });\n}\n\n/**\n * Configures the worker request handler.\n * @param server - The Vite dev server\n * @param autoDiscoveredFiles - The auto discovered files\n * @param userOptions - The user options\n */\nexport async function configureWorkerRequestHandler({\n server,\n autoDiscoveredFiles,\n userOptions: _userOptions,\n hmrChannel,\n onMetrics,\n}: {\n server: ViteDevServer;\n autoDiscoveredFiles: AutoDiscoveredFiles;\n userOptions: ResolvedUserOptions;\n hmrChannel: MessageChannel;\n onMetrics?: (metrics: RenderMetrics) => void;\n}) {\n let {\n // remove these\n projectRoot: _projectRoot,\n moduleBaseURL: _moduleBaseURL,\n moduleBasePath: _moduleBasePath,\n ...handlerUserOptions\n } = _userOptions;\n const handlerOptions = Object.assign({}, handlerUserOptions, {\n moduleBaseURL:\n typeof server.config.server.host === \"string\"\n ? `${server.config.server.https ? \"https\" : \"http\"}://${\n server.config.server.host\n }:${server.config.server.port}`\n : _moduleBaseURL,\n moduleBasePath:\n server.config.base === \"/\"\n ? \"\"\n : server.config.base.endsWith(\"/\")\n ? server.config.base.slice(0, -1)\n : server.config.base,\n projectRoot: server.config.root,\n });\n\n // Start the worker\n const currentWorker = await restartWorker(server, autoDiscoveredFiles, handlerOptions, hmrChannel);\n\n // Create the request handler\n const handler: RequestHandler = async (req, res, next) => {\n if (!req.url || req.headers.accept !== \"text/x-component\") return next();\n try {\n if (!currentWorker) {\n server.config.logger.error(\"[react-client] No worker available\");\n return next();\n }\n\n // Get the route from the request\n let route = requestToRoute(req, {\n moduleBasePath: handlerOptions.moduleBasePath,\n build: handlerOptions.build,\n });\n if (!route) {\n return next();\n }\n // in the case of the no build.pages and a async Page and or props userOption, we need to await those\n // if they are already autoDiscovered then the promise will resolve immediately\n const routeFiles = await getRouteFiles(\n route,\n autoDiscoveredFiles,\n handlerOptions\n );\n if (routeFiles.type === \"error\") {\n server.config.logger.error(\n `[react-client] Error fetching route files for ${route}`,\n {\n error: routeFiles.error,\n timestamp: true,\n environment: \"server\",\n }\n );\n return next();\n }\n const { page, props } = routeFiles;\n\n // Set up response headers for streaming\n res.setHeader(\"Content-Type\", \"text/x-component; charset=utf-8\");\n res.setHeader(\"Transfer-Encoding\", \"chunked\");\n res.setHeader(\"Connection\", \"keep-alive\");\n const serializedUserOptions = serializedOptions(\n handlerOptions,\n autoDiscoveredFiles\n );\n const startTime = performance.now();\n const stream = handleWorkerRscStream(\n currentWorker,\n {\n ...serializedUserOptions,\n // we make the worker stream aware of the route, pagePath, propsPath\n route,\n pagePath: page,\n propsPath: props,\n // override these at all times to ensure the settings will work for the dev server\n projectRoot: server.config.root,\n build: serializedUserOptions.build,\n manifest: autoDiscoveredFiles.staticManifest,\n cssFiles: new Map(),\n globalCss: new Map(),\n },\n server.config.logger,\n typeof onMetrics === \"function\"\n ? (metrics) => {\n const elapsedTime = performance.now() - startTime;\n const formattedMetrics = {\n route,\n htmlSize: 0,\n rscSize: metrics.bytes,\n processingTime: elapsedTime,\n chunks: metrics.chunks,\n chunkRate: metrics.chunks / (elapsedTime / 1000),\n memoryUsage: process.memoryUsage(),\n streamMetrics: {\n ...metrics,\n duration: elapsedTime\n },\n htmlSizes: new Map(),\n rscSizes: new Map([[route, metrics.bytes]]),\n } satisfies RenderMetrics;\n onMetrics(formattedMetrics);\n }\n : undefined\n );\n const writeStream = new WritableStream({\n write(chunk) {\n res.write(chunk);\n },\n\n close() {\n clearTimeout(timeout);\n res.end();\n },\n abort() {\n clearTimeout(timeout);\n // Restart worker on error\n restartWorker(\n server,\n autoDiscoveredFiles,\n handlerOptions,\n hmrChannel\n );\n res.end();\n },\n });\n let timeout: NodeJS.Timeout;\n\n // Pipe the stream to the response\n stream.pipeTo(writeStream);\n // wait for timeout\n timeout = setTimeout(() => {\n server.config.logger.error(\"RSC render timeout\");\n res.end();\n }, 5000);\n } catch (error) {\n if (error instanceof Error) {\n server.config.logger.error(error.message, {\n error,\n });\n }\n }\n };\n // attach handler to the server\n server.middlewares.use(handler);\n // done\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../plugin/react-server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAO5E,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,mBAAmB,EACnB,WAAW,EAAE,YAAY,EACzB,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,mBAAmB,CAAC;IACjC,cAAc,EAAE,QAAQ,CAAC;CAC1B,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../plugin/react-server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAO5E,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,mBAAmB,EACnB,WAAW,EAAE,YAAY,EACzB,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,mBAAmB,CAAC;IACjC,cAAc,EAAE,QAAQ,CAAC;CAC1B,iBAkIA"}
|
|
@@ -26,12 +26,12 @@ async function configureReactServer({
|
|
|
26
26
|
...handlerUserOptions
|
|
27
27
|
} = _userOptions;
|
|
28
28
|
const handlerOptions = Object.assign({}, handlerUserOptions, {
|
|
29
|
-
moduleBaseURL: typeof server.config.server.host === "string" ? `${server.config.server.https ? "https" : "http"}://${server.config.server.host}:${server.config.server.port}` :
|
|
29
|
+
moduleBaseURL: typeof server.config.server.host === "string" ? `${server.config.server.https ? "https" : "http"}://${server.config.server.host}:${server.config.server.port}` : _moduleBaseURL,
|
|
30
30
|
moduleBasePath: server.config.base === "/" ? "" : server.config.base.endsWith("/") ? server.config.base.slice(0, -1) : server.config.base,
|
|
31
31
|
projectRoot: server.config.root
|
|
32
32
|
});
|
|
33
33
|
server.ws.on("restart", (path) => {
|
|
34
|
-
|
|
34
|
+
server.config.logger.info(
|
|
35
35
|
"[vite-plugin-react-server] 🔧 Plugin changed, preparing for restart:",
|
|
36
36
|
path
|
|
37
37
|
);
|
|
@@ -40,7 +40,7 @@ async function configureReactServer({
|
|
|
40
40
|
"Content-Type": "text/x-component",
|
|
41
41
|
"Retry-After": "1"
|
|
42
42
|
});
|
|
43
|
-
res.end(
|
|
43
|
+
res.end(`0:E{"digest":"","name":"Error","message":"Server restarting...","stack":"","env":"Server"}`);
|
|
44
44
|
}
|
|
45
45
|
activeStreams.clear();
|
|
46
46
|
});
|
|
@@ -48,14 +48,11 @@ async function configureReactServer({
|
|
|
48
48
|
try {
|
|
49
49
|
if (req.headers.accept !== "text/x-component") return next();
|
|
50
50
|
let route = req.url?.replace("/" + handlerOptions.build.rscOutputPath, "");
|
|
51
|
-
if (!route?.startsWith(handlerOptions.moduleBasePath)) {
|
|
51
|
+
if (handlerOptions.moduleBasePath !== "" && !route?.startsWith(handlerOptions.moduleBasePath)) {
|
|
52
52
|
next();
|
|
53
|
-
} else {
|
|
53
|
+
} else if (route && handlerOptions.moduleBasePath.length) {
|
|
54
54
|
route = route.slice(handlerOptions.moduleBasePath.length);
|
|
55
55
|
}
|
|
56
|
-
if (typeof route !== "string") {
|
|
57
|
-
throw new Error("req.url is not a string");
|
|
58
|
-
}
|
|
59
56
|
if (!route || route === "") {
|
|
60
57
|
route = "/";
|
|
61
58
|
}
|
|
@@ -68,26 +65,6 @@ async function configureReactServer({
|
|
|
68
65
|
const routeFiles = autoDiscoveredFiles.urlMap.get(route);
|
|
69
66
|
const pagePath = routeFiles.page;
|
|
70
67
|
const propsPath = routeFiles.props;
|
|
71
|
-
await server.warmupRequest(pagePath);
|
|
72
|
-
const eventHandler = createEventHandler(onEvent);
|
|
73
|
-
const cssFilesResult = await collectViteModuleGraphCss({
|
|
74
|
-
moduleGraph: server.moduleGraph,
|
|
75
|
-
pagePath,
|
|
76
|
-
loader: (i) => server.ssrLoadModule(i, { fixStacktrace: true }),
|
|
77
|
-
// explicitly set for development server
|
|
78
|
-
moduleBaseURL: handlerOptions.moduleBaseURL,
|
|
79
|
-
moduleBasePath: handlerOptions.moduleBasePath,
|
|
80
|
-
moduleRootPath: handlerOptions.moduleRootPath,
|
|
81
|
-
projectRoot: handlerOptions.projectRoot,
|
|
82
|
-
css: handlerOptions.css,
|
|
83
|
-
parentUrl: pagePath
|
|
84
|
-
});
|
|
85
|
-
if (cssFilesResult.type === "skip") {
|
|
86
|
-
return next();
|
|
87
|
-
}
|
|
88
|
-
if (cssFilesResult.type === "error") {
|
|
89
|
-
throw cssFilesResult.error;
|
|
90
|
-
}
|
|
91
68
|
const pageAndPropsResult = await resolvePageAndProps({
|
|
92
69
|
pagePath,
|
|
93
70
|
propsPath,
|
|
@@ -102,6 +79,24 @@ async function configureReactServer({
|
|
|
102
79
|
if (pageAndPropsResult.type === "skip") {
|
|
103
80
|
return next();
|
|
104
81
|
}
|
|
82
|
+
const eventHandler = createEventHandler(onEvent);
|
|
83
|
+
const cssFilesResult = await collectViteModuleGraphCss({
|
|
84
|
+
moduleGraph: server.moduleGraph,
|
|
85
|
+
// by having loaded the page and props, we can get them from the module graph
|
|
86
|
+
parentUrl: pagePath,
|
|
87
|
+
handlerOptions: {
|
|
88
|
+
pagePath,
|
|
89
|
+
loader: server.ssrLoadModule,
|
|
90
|
+
// explicitly set for development server
|
|
91
|
+
...handlerOptions
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
if (cssFilesResult.type === "skip") {
|
|
95
|
+
return next();
|
|
96
|
+
}
|
|
97
|
+
if (cssFilesResult.type === "error") {
|
|
98
|
+
throw cssFilesResult.error;
|
|
99
|
+
}
|
|
105
100
|
const { PageComponent, pageProps } = pageAndPropsResult;
|
|
106
101
|
const rscResult = await createHandler({
|
|
107
102
|
...handlerOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../../../plugin/react-server/server.ts"],"sourcesContent":["import type { Manifest, ViteDevServer } from \"vite\";\nimport type { ServerResponse } from \"http\";\nimport type { AutoDiscoveredFiles, ResolvedUserOptions } from \"../types.js\";\nimport { createEventHandler } from \"../helpers/createEventHandler.js\";\nimport { collectViteModuleGraphCss } from \"../helpers/collectViteModuleGraphCss.js\";\nimport { resolvePageAndProps } from \"../helpers/resolvePageAndProps.js\";\nimport { createHandler } from \"../helpers/createHandler.js\";\nimport React from \"react\";\n\nexport async function configureReactServer({\n server,\n autoDiscoveredFiles,\n userOptions: _userOptions,\n serverManifest,\n}: {\n server: ViteDevServer;\n autoDiscoveredFiles: AutoDiscoveredFiles;\n userOptions: ResolvedUserOptions;\n serverManifest: Manifest;\n}) {\n const activeStreams = new Set<ServerResponse>();\n\n const {\n Html: _UserHtmlComponent,\n onEvent,\n // remove these\n moduleBaseURL: _moduleBaseURL,\n moduleBasePath: _moduleBasePath,\n projectRoot: _projectRoot,\n ...handlerUserOptions\n } = _userOptions;\n\n const handlerOptions = Object.assign({}, handlerUserOptions, {\n moduleBaseURL:\n typeof server.config.server.host === \"string\"\n ? `${server.config.server.https ? \"https\" : \"http\"}://${\n server.config.server.host\n }:${server.config.server.port}`\n :
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../../../plugin/react-server/server.ts"],"sourcesContent":["import type { Manifest, ViteDevServer } from \"vite\";\nimport type { ServerResponse } from \"http\";\nimport type { AutoDiscoveredFiles, ResolvedUserOptions } from \"../types.js\";\nimport { createEventHandler } from \"../helpers/createEventHandler.js\";\nimport { collectViteModuleGraphCss } from \"../helpers/collectViteModuleGraphCss.js\";\nimport { resolvePageAndProps } from \"../helpers/resolvePageAndProps.js\";\nimport { createHandler } from \"../helpers/createHandler.js\";\nimport React from \"react\";\n\nexport async function configureReactServer({\n server,\n autoDiscoveredFiles,\n userOptions: _userOptions,\n serverManifest,\n}: {\n server: ViteDevServer;\n autoDiscoveredFiles: AutoDiscoveredFiles;\n userOptions: ResolvedUserOptions;\n serverManifest: Manifest;\n}) {\n const activeStreams = new Set<ServerResponse>();\n\n const {\n Html: _UserHtmlComponent,\n onEvent,\n // remove these\n moduleBaseURL: _moduleBaseURL,\n moduleBasePath: _moduleBasePath,\n projectRoot: _projectRoot,\n ...handlerUserOptions\n } = _userOptions;\n\n const handlerOptions = Object.assign({}, handlerUserOptions, {\n moduleBaseURL:\n typeof server.config.server.host === \"string\"\n ? `${server.config.server.https ? \"https\" : \"http\"}://${\n server.config.server.host\n }:${server.config.server.port}`\n : _moduleBaseURL,\n moduleBasePath:\n server.config.base === \"/\"\n ? \"\"\n : server.config.base.endsWith(\"/\")\n ? server.config.base.slice(0, -1)\n : server.config.base,\n projectRoot: server.config.root,\n });\n // Handle Vite server restarts\n server.ws.on(\"restart\", (path) => {\n server.config.logger.info(\n \"[vite-plugin-react-server] 🔧 Plugin changed, preparing for restart:\",\n path\n );\n\n // Close streams with restart message\n for (const res of activeStreams) {\n res.writeHead(503, {\n \"Content-Type\": \"text/x-component\",\n \"Retry-After\": \"1\",\n });\n res.end(`0:E{\"digest\":\"\",\"name\":\"Error\",\"message\":\"Server restarting...\",\"stack\":\"\",\"env\":\"Server\"}`);\n }\n activeStreams.clear();\n });\n\n server.middlewares.use(async (req, res, next) => {\n try {\n if (req.headers.accept !== \"text/x-component\") return next();\n let route = req.url?.replace(\"/\" + handlerOptions.build.rscOutputPath, \"\");\n if(handlerOptions.moduleBasePath !== '' && !route?.startsWith(handlerOptions.moduleBasePath)) {\n next();\n } else if(route && handlerOptions.moduleBasePath.length) {\n route = route.slice(handlerOptions.moduleBasePath.length);\n }\n if (!route || route === \"\") {\n route = \"/\";\n }\n if(!route.startsWith(\"/\")) {\n route = \"/\" + route;\n }\n if (!autoDiscoveredFiles.urlMap.has(route)) {\n return next();\n }\n const routeFiles = autoDiscoveredFiles.urlMap.get(route)!;\n const pagePath = routeFiles.page;\n const propsPath = routeFiles.props;\n\n // first load the page and props\n const pageAndPropsResult = await resolvePageAndProps({\n pagePath,\n propsPath,\n route,\n loader: server.ssrLoadModule,\n pageExportName: handlerOptions.pageExportName ?? \"default\",\n propsExportName: handlerOptions.propsExportName ?? \"default\",\n });\n if (pageAndPropsResult.type === \"error\") {\n throw pageAndPropsResult.error;\n }\n if (pageAndPropsResult.type === \"skip\") {\n return next();\n }\n\n const eventHandler = createEventHandler(onEvent);\n const cssFilesResult = await collectViteModuleGraphCss({\n moduleGraph: server.moduleGraph, // by having loaded the page and props, we can get them from the module graph\n parentUrl: pagePath,\n handlerOptions: {\n pagePath,\n loader: server.ssrLoadModule,\n // explicitly set for development server\n ...handlerOptions,\n },\n });\n if (cssFilesResult.type === \"skip\") {\n return next();\n }\n if (cssFilesResult.type === \"error\") {\n throw cssFilesResult.error;\n }\n const { PageComponent, pageProps } = pageAndPropsResult;\n // Create the headless RSC stream directly;\n const rscResult = await createHandler({\n ...handlerOptions,\n PageComponent: PageComponent,\n pageProps: pageProps,\n logger: server.config.logger,\n loader: server.ssrLoadModule,\n Html: React.Fragment,\n onEvent: eventHandler,\n manifest: serverManifest,\n worker: server as any,\n route,\n pagePath,\n propsPath,\n cssFiles: cssFilesResult.cssFiles ?? new Map(),\n globalCss: new Map(),\n });\n if (rscResult.type === \"success\") {\n rscResult.stream!.pipe(res);\n }\n activeStreams.add(res);\n res.on(\"close\", () => {\n activeStreams.delete(res);\n });\n } catch (error) {\n res.end();\n }\n });\n}\n"],"names":["React"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectHtmlWorkerContent.js","sources":["../../../plugin/react-static/collectHtmlWorkerContent.ts"],"sourcesContent":["/**\n * rscHandler.ts\n *\n * PURPOSE: Handles collecting HTML content from the htmlCompact stream\n *\n * This module:\n * 1. Collects HTML content from the rscFull stream (which includes <html> and <body> tags)\n * 2. Returns the complete HTML content when the stream is done\n * 3. Provides a clean interface for HTML handling\n */\n\nimport { PassThrough, Transform } from \"node:stream\";\nimport type { CreateHandlerOptions, StreamMetrics } from \"../types.js\";\nimport { createStreamMetrics } from \"../helpers/metrics.js\";\nimport { createRscToHtmlStream } from \"./rscToHtmlStream.js\";\nimport { fileWriter } from \"./fileWriter.js\";\n\n/**\n * Collects RSC content from the rscFull stream\n *\n * @param rscFull The stream containing the RSC content\n * @returns A promise that resolves with the complete RSC content\n */\nexport async function collectHtmlWorkerContent(\n rscStream: PassThrough,\n handlerOptions: CreateHandlerOptions\n): Promise<{ stream: PassThrough; metrics: StreamMetrics }> {\n const metrics = createStreamMetrics();\n const startTime = performance.now();\n\n // Create RSC to HTML transform stream\n const rscToHtmlStream = createRscToHtmlStream({\n worker: handlerOptions.worker,\n route: handlerOptions.route,\n moduleRootPath: handlerOptions.moduleRootPath,\n moduleBaseURL: handlerOptions.moduleBaseURL,\n pipeableStreamOptions: handlerOptions.pipeableStreamOptions,\n build: handlerOptions.build,\n cssFiles: handlerOptions.cssFiles,\n projectRoot: handlerOptions.projectRoot,\n });\n\n // Create transform stream to handle HTML chunks and file writing\n const htmlTransform = new Transform({\n transform(chunk, _encoding, callback) {\n metrics.chunks++;\n callback(null, chunk);\n },\n flush(callback) {\n metrics.duration =
|
|
1
|
+
{"version":3,"file":"collectHtmlWorkerContent.js","sources":["../../../plugin/react-static/collectHtmlWorkerContent.ts"],"sourcesContent":["/**\n * rscHandler.ts\n *\n * PURPOSE: Handles collecting HTML content from the htmlCompact stream\n *\n * This module:\n * 1. Collects HTML content from the rscFull stream (which includes <html> and <body> tags)\n * 2. Returns the complete HTML content when the stream is done\n * 3. Provides a clean interface for HTML handling\n */\n\nimport { PassThrough, Transform } from \"node:stream\";\nimport type { CreateHandlerOptions, StreamMetrics } from \"../types.js\";\nimport { createStreamMetrics } from \"../helpers/metrics.js\";\nimport { createRscToHtmlStream } from \"./rscToHtmlStream.js\";\nimport { fileWriter } from \"./fileWriter.js\";\n\n/**\n * Collects RSC content from the rscFull stream\n *\n * @param rscFull The stream containing the RSC content\n * @returns A promise that resolves with the complete RSC content\n */\nexport async function collectHtmlWorkerContent(\n rscStream: PassThrough,\n handlerOptions: CreateHandlerOptions\n): Promise<{ stream: PassThrough; metrics: StreamMetrics }> {\n const metrics = createStreamMetrics();\n const startTime = performance.now();\n\n // Create RSC to HTML transform stream\n const rscToHtmlStream = createRscToHtmlStream({\n worker: handlerOptions.worker,\n route: handlerOptions.route,\n moduleRootPath: handlerOptions.moduleRootPath,\n moduleBaseURL: handlerOptions.moduleBaseURL,\n pipeableStreamOptions: handlerOptions.pipeableStreamOptions,\n build: handlerOptions.build,\n cssFiles: handlerOptions.cssFiles,\n projectRoot: handlerOptions.projectRoot,\n });\n\n // Create transform stream to handle HTML chunks and file writing\n const htmlTransform = new Transform({\n transform(chunk, _encoding, callback) {\n metrics.chunks++;\n callback(null, chunk);\n },\n flush(callback) {\n metrics.duration = performance.now() - startTime;\n callback();\n },\n });\n\n let isComplete = false;\n\n // Create a promise that resolves when the route is complete\n const routeComplete = new Promise<void>((resolve, reject) => {\n const messageHandler = (msg: any) => {\n switch (msg.type) {\n case \"HTML_CHUNK\":\n if (!isComplete) {\n htmlTransform.write(msg.chunk);\n }\n break;\n case \"HTML_COMPLETE\":\n isComplete = true;\n // End the transform stream\n htmlTransform.end();\n // Send cleanup message to worker\n handlerOptions.worker.postMessage({\n type: \"CLEANUP\",\n id: handlerOptions.route,\n });\n break;\n case \"CLEANUP_COMPLETE\":\n resolve();\n break;\n case \"ERROR\":\n handlerOptions.worker.removeListener(\"message\", messageHandler);\n reject(msg.error);\n break;\n }\n };\n handlerOptions.worker.on(\"message\", messageHandler);\n });\n\n try {\n // Set up event handler to capture content length\n if (handlerOptions.onEvent) {\n const originalOnEvent = handlerOptions.onEvent;\n handlerOptions.onEvent = (event) => {\n if (event.type === \"file.write.done\" && event.data.fileType === \"html\") {\n metrics.bytes = event.data.content.length;\n }\n originalOnEvent(event);\n };\n }\n\n // Pipe RSC through transform to HTML\n rscStream.pipe(rscToHtmlStream);\n\n // Set up file writing using fileWriter\n const writePromise = fileWriter(htmlTransform, \"html\", handlerOptions);\n\n // Wait for route to complete\n await routeComplete;\n\n // Wait for file writing to complete\n await writePromise;\n\n rscToHtmlStream.destroy();\n\n return { stream: rscStream, metrics };\n } catch (error) {\n // Clean up streams on error\n rscToHtmlStream.destroy();\n throw error;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectRscContent.js","sources":["../../../plugin/react-static/collectRscContent.ts"],"sourcesContent":["/**\n * rscHandler.ts\n * \n * PURPOSE: Handles collecting RSC content from the rscHeadless stream\n * \n * This module:\n * 1. Collects RSC content from the rscHeadless stream\n * 2. Returns the complete RSC content when the stream is done\n * 3. Provides a clean interface for RSC handling\n */\n\nimport { PassThrough, Transform } from \"node:stream\";\nimport { dirname, join } from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { CreateHandlerOptions, StreamMetrics } from \"../types.js\";\nimport { createStreamMetrics } from \"../helpers/metrics.js\";\nimport { fileWriter } from \"./fileWriter.js\";\n\n/**\n * Collects RSC content from the rscHeadless stream\n * \n * @param rscStream The stream containing the RSC content\n * @param handlerOptions The options for the handler\n * @returns A promise that resolves with the complete RSC content and metrics\n */\nexport async function collectRscContent(\n rscStream: PassThrough,\n handlerOptions: CreateHandlerOptions\n): Promise<{ stream: PassThrough; metrics: StreamMetrics }> {\n const metrics = createStreamMetrics();\n const startTime = performance.now()
|
|
1
|
+
{"version":3,"file":"collectRscContent.js","sources":["../../../plugin/react-static/collectRscContent.ts"],"sourcesContent":["/**\n * rscHandler.ts\n * \n * PURPOSE: Handles collecting RSC content from the rscHeadless stream\n * \n * This module:\n * 1. Collects RSC content from the rscHeadless stream\n * 2. Returns the complete RSC content when the stream is done\n * 3. Provides a clean interface for RSC handling\n */\n\nimport { PassThrough, Transform } from \"node:stream\";\nimport { dirname, join } from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { CreateHandlerOptions, StreamMetrics } from \"../types.js\";\nimport { createStreamMetrics } from \"../helpers/metrics.js\";\nimport { fileWriter } from \"./fileWriter.js\";\n\n/**\n * Collects RSC content from the rscHeadless stream\n * \n * @param rscStream The stream containing the RSC content\n * @param handlerOptions The options for the handler\n * @returns A promise that resolves with the complete RSC content and metrics\n */\nexport async function collectRscContent(\n rscStream: PassThrough,\n handlerOptions: CreateHandlerOptions\n): Promise<{ stream: PassThrough; metrics: StreamMetrics }> {\n const metrics = createStreamMetrics();\n const startTime = performance.now();\n\n const outputPath = join(\n handlerOptions.build.outDir,\n handlerOptions.build.static,\n handlerOptions.route,\n handlerOptions.build.rscOutputPath\n );\n\n const dir = dirname(outputPath);\n // Ensure directory exists\n await mkdir(join(handlerOptions.projectRoot, dir), { recursive: true });\n\n // Create transform to track metrics\n const metricsTransform = new Transform({\n transform(chunk, _encoding, callback) {\n metrics.chunks++;\n metrics.bytes += chunk.length;\n callback(null, chunk);\n },\n flush(callback) {\n metrics.duration = performance.now() - startTime;\n callback();\n }\n });\n\n try {\n // Pipe RSC stream through metrics tracking\n rscStream.pipe(metricsTransform);\n\n // Set up file writing using fileWriter\n const writePromise = fileWriter(metricsTransform, \"rsc\", handlerOptions);\n\n // Wait for stream to complete\n await new Promise<void>((resolve) => {\n metricsTransform.on('end', resolve);\n });\n\n // Wait for file writing to complete\n await writePromise;\n\n return { stream: rscStream, metrics };\n } catch (error) {\n metricsTransform.destroy();\n throw error;\n }\n} "],"names":[],"mappings":";;;;;;;;;;;AAyBsB,eAAA,iBAAA,CACpB,WACA,cAC0D,EAAA;AAC1D,EAAA,MAAM,UAAU,mBAAoB,EAAA;AACpC,EAAM,MAAA,SAAA,GAAY,YAAY,GAAI,EAAA;AAElC,EAAA,MAAM,UAAa,GAAA,IAAA;AAAA,IACjB,eAAe,KAAM,CAAA,MAAA;AAAA,IACrB,eAAe,KAAM,CAAA,MAAA;AAAA,IACrB,cAAe,CAAA,KAAA;AAAA,IACf,eAAe,KAAM,CAAA;AAAA,GACvB;AAEA,EAAM,MAAA,GAAA,GAAM,QAAQ,UAAU,CAAA;AAE9B,EAAM,MAAA,KAAA,CAAM,KAAK,cAAe,CAAA,WAAA,EAAa,GAAG,CAAG,EAAA,EAAE,SAAW,EAAA,IAAA,EAAM,CAAA;AAGtE,EAAM,MAAA,gBAAA,GAAmB,IAAI,SAAU,CAAA;AAAA,IACrC,SAAA,CAAU,KAAO,EAAA,SAAA,EAAW,QAAU,EAAA;AACpC,MAAQ,OAAA,CAAA,MAAA,EAAA;AACR,MAAA,OAAA,CAAQ,SAAS,KAAM,CAAA,MAAA;AACvB,MAAA,QAAA,CAAS,MAAM,KAAK,CAAA;AAAA,KACtB;AAAA,IACA,MAAM,QAAU,EAAA;AACd,MAAQ,OAAA,CAAA,QAAA,GAAW,WAAY,CAAA,GAAA,EAAQ,GAAA,SAAA;AACvC,MAAS,QAAA,EAAA;AAAA;AACX,GACD,CAAA;AAED,EAAI,IAAA;AAEF,IAAA,SAAA,CAAU,KAAK,gBAAgB,CAAA;AAG/B,IAAA,MAAM,YAAe,GAAA,UAAA,CAAW,gBAAkB,EAAA,KAAA,EAAO,cAAc,CAAA;AAGvE,IAAM,MAAA,IAAI,OAAc,CAAA,CAAC,OAAY,KAAA;AACnC,MAAiB,gBAAA,CAAA,EAAA,CAAG,OAAO,OAAO,CAAA;AAAA,KACnC,CAAA;AAGD,IAAM,MAAA,YAAA;AAEN,IAAO,OAAA,EAAE,MAAQ,EAAA,SAAA,EAAW,OAAQ,EAAA;AAAA,WAC7B,KAAO,EAAA;AACd,IAAA,gBAAA,CAAiB,OAAQ,EAAA;AACzB,IAAM,MAAA,KAAA;AAAA;AAEV;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurePreviewServer.d.ts","sourceRoot":"","sources":["../../../plugin/react-static/configurePreviewServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAMvD,wBAAsB,sBAAsB,CAAC,EAC3C,MAAM,EACN,WAAW,GACZ,EAAE;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,mBAAmB,CAAC;CAClC,
|
|
1
|
+
{"version":3,"file":"configurePreviewServer.d.ts","sourceRoot":"","sources":["../../../plugin/react-static/configurePreviewServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAMvD,wBAAsB,sBAAsB,CAAC,EAC3C,MAAM,EACN,WAAW,GACZ,EAAE;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,mBAAmB,CAAC;CAClC,iBA4EA"}
|
|
@@ -16,9 +16,12 @@ async function configurePreviewServer({
|
|
|
16
16
|
const staticHostDir = join(userOptions.projectRoot, userOptions.build.outDir, userOptions.build.static);
|
|
17
17
|
server.middlewares.use(async (req, res, next) => {
|
|
18
18
|
if (!req.url) {
|
|
19
|
+
console.log("no url");
|
|
19
20
|
return next();
|
|
20
21
|
}
|
|
21
|
-
const [
|
|
22
|
+
const [withoutQuery] = req.url.split("?");
|
|
23
|
+
const [, value] = userOptions.normalizer(withoutQuery);
|
|
24
|
+
const ext = value.slice(value.lastIndexOf("."));
|
|
22
25
|
const isHtml = userOptions.autoDiscover.htmlPattern(value);
|
|
23
26
|
if (isHtml || req.headers.accept?.includes("text/html")) {
|
|
24
27
|
const indexHtml = isHtml ? join(staticHostDir, value) : join(staticHostDir, value, userOptions.build.htmlOutputPath);
|
|
@@ -45,14 +48,30 @@ async function configurePreviewServer({
|
|
|
45
48
|
} catch {
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
|
-
const
|
|
51
|
+
const isCss = userOptions.autoDiscover.cssPattern(value);
|
|
52
|
+
if (isCss || req.headers.accept?.includes("text/css") && ext === "") {
|
|
53
|
+
const css = isCss ? join(staticHostDir, value) : join(staticHostDir, value);
|
|
54
|
+
try {
|
|
55
|
+
const stats = await stat(css);
|
|
56
|
+
if (stats.isFile()) {
|
|
57
|
+
res.setHeader("Content-Type", "text/css; charset=utf-8");
|
|
58
|
+
await pipeline(createReadStream(css), res);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
49
64
|
if (ext) {
|
|
50
65
|
const filePath = join(staticHostDir, value);
|
|
51
66
|
try {
|
|
52
67
|
const stats = await stat(filePath);
|
|
53
68
|
if (stats.isFile()) {
|
|
54
|
-
const contentType = MIME_TYPES[ext]
|
|
55
|
-
|
|
69
|
+
const contentType = MIME_TYPES[ext];
|
|
70
|
+
if (contentType) {
|
|
71
|
+
res.setHeader("Content-Type", `${contentType}; charset=utf-8`);
|
|
72
|
+
} else {
|
|
73
|
+
res.setHeader("Content-Type", "application/octet-stream");
|
|
74
|
+
}
|
|
56
75
|
await pipeline(createReadStream(filePath), res);
|
|
57
76
|
return;
|
|
58
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurePreviewServer.js","sources":["../../../plugin/react-static/configurePreviewServer.ts"],"sourcesContent":["import type { PreviewServer } from \"vite\";\nimport { MIME_TYPES } from \"../config/mimeTypes.js\";\nimport type { ResolvedUserOptions } from \"../types.js\";\nimport { join } from \"node:path\";\nimport { createReadStream } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport { pipeline } from \"node:stream/promises\";\n\nexport async function configurePreviewServer({\n server,\n userOptions,\n}: {\n server: PreviewServer;\n userOptions: ResolvedUserOptions;\n}) {\n const staticHostDir = join(userOptions.projectRoot, userOptions.build.outDir, userOptions.build.static);\n server.middlewares.use(async (req, res, next) => {\n if(!req.url) {\n return next();\n }\n const [, value] = userOptions.normalizer(
|
|
1
|
+
{"version":3,"file":"configurePreviewServer.js","sources":["../../../plugin/react-static/configurePreviewServer.ts"],"sourcesContent":["import type { PreviewServer } from \"vite\";\nimport { MIME_TYPES } from \"../config/mimeTypes.js\";\nimport type { ResolvedUserOptions } from \"../types.js\";\nimport { join } from \"node:path\";\nimport { createReadStream } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport { pipeline } from \"node:stream/promises\";\n\nexport async function configurePreviewServer({\n server,\n userOptions,\n}: {\n server: PreviewServer;\n userOptions: ResolvedUserOptions;\n}) {\n const staticHostDir = join(userOptions.projectRoot, userOptions.build.outDir, userOptions.build.static);\n server.middlewares.use(async (req, res, next) => {\n if(!req.url) {\n console.log(\"no url\")\n return next();\n }\n const [withoutQuery] = req.url.split(\"?\");\n const [, value] = userOptions.normalizer(withoutQuery);\n const ext = value.slice(value.lastIndexOf(\".\"));\n // handle index.html\n const isHtml = userOptions.autoDiscover.htmlPattern(value)\n if (isHtml || (req.headers.accept?.includes(\"text/html\"))) {\n const indexHtml = isHtml ? join(staticHostDir, value) : join(staticHostDir, value, userOptions.build.htmlOutputPath);\n try {\n const stats = await stat(indexHtml);\n if (stats.isFile()) {\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n await pipeline(createReadStream(indexHtml), res);\n return;\n }\n } catch {\n // File doesn't exist, continue to next middleware\n }\n } \n const isRsc = userOptions.autoDiscover.rscPattern(value)\n if (isRsc || (req.headers.accept?.includes(\"text/x-component\"))) {\n const rsc = isRsc ? join(staticHostDir, value) : join(staticHostDir, value, userOptions.build.rscOutputPath);\n try {\n const stats = await stat(rsc);\n if (stats.isFile()) {\n res.setHeader(\"Content-Type\", \"text/x-component; charset=utf-8\");\n await pipeline(createReadStream(rsc), res);\n return;\n }\n } catch {\n // File doesn't exist, continue to next middleware\n }\n }\n const isCss = userOptions.autoDiscover.cssPattern(value)\n if (isCss || (req.headers.accept?.includes(\"text/css\") && (ext === \"\"))) {\n const css = isCss ? join(staticHostDir, value) : join(staticHostDir, value);\n try {\n const stats = await stat(css);\n if (stats.isFile()) {\n res.setHeader(\"Content-Type\", \"text/css; charset=utf-8\");\n await pipeline(createReadStream(css), res);\n return;\n }\n } catch {\n // File doesn't exist, continue to next middleware\n }\n }\n // Handle static files including CSS\n if (ext) {\n const filePath = join(staticHostDir, value);\n try {\n const stats = await stat(filePath);\n if (stats.isFile()) {\n // Set proper MIME type based on file extension\n const contentType = MIME_TYPES[ext];\n // Ensure CSS files are served with the correct MIME type\n if (contentType) {\n res.setHeader(\"Content-Type\", `${contentType}; charset=utf-8`);\n } else {\n res.setHeader(\"Content-Type\", \"application/octet-stream\");\n }\n await pipeline(createReadStream(filePath), res);\n return;\n }\n } catch {\n // File doesn't exist, continue to next middleware\n }\n }\n next();\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileWriter.d.ts","sourceRoot":"","sources":["../../../plugin/react-static/fileWriter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,OAAO,EAAE,QAAQ,EAAa,MAAM,aAAa,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,MAAM,GAAG,KAAK,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"fileWriter.d.ts","sourceRoot":"","sources":["../../../plugin/react-static/fileWriter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,OAAO,EAAE,QAAQ,EAAa,MAAM,aAAa,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,MAAM,GAAG,KAAK,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CA6Ef"}
|