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.
Files changed (143) hide show
  1. package/dist/package.json +10 -5
  2. package/dist/plugin/config/defaults.d.ts +1 -1
  3. package/dist/plugin/config/defaults.js +1 -1
  4. package/dist/plugin/config/defaults.js.map +1 -1
  5. package/dist/plugin/config/resolveAutoDiscover.d.ts +2 -0
  6. package/dist/plugin/config/resolveAutoDiscover.d.ts.map +1 -1
  7. package/dist/plugin/config/resolveAutoDiscover.js +15 -18
  8. package/dist/plugin/config/resolveAutoDiscover.js.map +1 -1
  9. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  10. package/dist/plugin/config/resolveOptions.js +4 -1
  11. package/dist/plugin/config/resolveOptions.js.map +1 -1
  12. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  13. package/dist/plugin/config/resolveUserConfig.js +56 -29
  14. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  15. package/dist/plugin/helpers/collectBundleManifestCss.d.ts +0 -6
  16. package/dist/plugin/helpers/collectBundleManifestCss.d.ts.map +1 -1
  17. package/dist/plugin/helpers/collectBundleManifestCss.js +2 -110
  18. package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts +2 -1
  19. package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts.map +1 -1
  20. package/dist/plugin/helpers/collectViteModuleGraphCss.js +19 -18
  21. package/dist/plugin/helpers/collectViteModuleGraphCss.js.map +1 -1
  22. package/dist/plugin/helpers/createCssProps.d.ts +3 -2
  23. package/dist/plugin/helpers/createCssProps.d.ts.map +1 -1
  24. package/dist/plugin/helpers/createCssProps.js +10 -6
  25. package/dist/plugin/helpers/createCssProps.js.map +1 -1
  26. package/dist/plugin/helpers/createRscStream.d.ts.map +1 -1
  27. package/dist/plugin/helpers/createRscStream.js +37 -43
  28. package/dist/plugin/helpers/createRscStream.js.map +1 -1
  29. package/dist/plugin/helpers/formatMetrics.d.ts +4 -0
  30. package/dist/plugin/helpers/formatMetrics.d.ts.map +1 -0
  31. package/dist/plugin/helpers/formatMetrics.js +24 -0
  32. package/dist/plugin/helpers/tryManifest.d.ts.map +1 -1
  33. package/dist/plugin/helpers/tryManifest.js +0 -8
  34. package/dist/plugin/helpers/tryManifest.js.map +1 -1
  35. package/dist/plugin/html.js +1 -1
  36. package/dist/plugin/html.js.map +1 -1
  37. package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
  38. package/dist/plugin/loader/createBuildLoader.js +2 -0
  39. package/dist/plugin/loader/createBuildLoader.js.map +1 -1
  40. package/dist/plugin/metrics/formatMetrics.d.ts +4 -0
  41. package/dist/plugin/metrics/formatMetrics.d.ts.map +1 -0
  42. package/dist/plugin/metrics/formatMetrics.js +39 -0
  43. package/dist/plugin/metrics/formatMetrics.js.map +1 -0
  44. package/dist/plugin/metrics/index.d.ts +3 -0
  45. package/dist/plugin/metrics/index.d.ts.map +1 -0
  46. package/dist/plugin/metrics/index.js +1 -0
  47. package/dist/plugin/metrics.js +7 -0
  48. package/dist/plugin/metrics.js.map +1 -0
  49. package/dist/plugin/react-client/createWorkerStream.d.ts +16 -0
  50. package/dist/plugin/react-client/createWorkerStream.d.ts.map +1 -0
  51. package/dist/plugin/react-client/createWorkerStream.js +88 -0
  52. package/dist/plugin/react-client/createWorkerStream.js.map +1 -0
  53. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  54. package/dist/plugin/react-client/plugin.js +4 -1
  55. package/dist/plugin/react-client/plugin.js.map +1 -1
  56. package/dist/plugin/react-client/restartWorker.d.ts +6 -0
  57. package/dist/plugin/react-client/restartWorker.d.ts.map +1 -0
  58. package/dist/plugin/react-client/restartWorker.js +53 -0
  59. package/dist/plugin/react-client/restartWorker.js.map +1 -0
  60. package/dist/plugin/react-client/server.d.ts +5 -4
  61. package/dist/plugin/react-client/server.d.ts.map +1 -1
  62. package/dist/plugin/react-client/server.js +79 -110
  63. package/dist/plugin/react-client/server.js.map +1 -1
  64. package/dist/plugin/react-server/server.d.ts.map +1 -1
  65. package/dist/plugin/react-server/server.js +23 -28
  66. package/dist/plugin/react-server/server.js.map +1 -1
  67. package/dist/plugin/react-static/collectHtmlWorkerContent.js +1 -1
  68. package/dist/plugin/react-static/collectHtmlWorkerContent.js.map +1 -1
  69. package/dist/plugin/react-static/collectRscContent.js +1 -1
  70. package/dist/plugin/react-static/collectRscContent.js.map +1 -1
  71. package/dist/plugin/react-static/configurePreviewServer.d.ts.map +1 -1
  72. package/dist/plugin/react-static/configurePreviewServer.js +23 -4
  73. package/dist/plugin/react-static/configurePreviewServer.js.map +1 -1
  74. package/dist/plugin/react-static/fileWriter.d.ts.map +1 -1
  75. package/dist/plugin/react-static/fileWriter.js +5 -1
  76. package/dist/plugin/react-static/fileWriter.js.map +1 -1
  77. package/dist/plugin/react-static/plugin.d.ts.map +1 -1
  78. package/dist/plugin/react-static/plugin.js +50 -33
  79. package/dist/plugin/react-static/plugin.js.map +1 -1
  80. package/dist/plugin/types.d.ts +6 -7
  81. package/dist/plugin/types.d.ts.map +1 -1
  82. package/dist/plugin/utils/callServer.d.ts +2 -0
  83. package/dist/plugin/utils/callServer.d.ts.map +1 -0
  84. package/dist/plugin/utils/callServer.js +26 -0
  85. package/dist/plugin/utils/callServer.js.map +1 -0
  86. package/dist/plugin/utils/createReactFetcher.d.ts +7 -0
  87. package/dist/plugin/utils/createReactFetcher.d.ts.map +1 -0
  88. package/dist/plugin/utils/createReactFetcher.js +33 -0
  89. package/dist/plugin/utils/createReactFetcher.js.map +1 -0
  90. package/dist/plugin/utils/index.d.ts +4 -0
  91. package/dist/plugin/utils/index.d.ts.map +1 -0
  92. package/dist/plugin/utils/index.js +3 -0
  93. package/dist/plugin/utils/pageURL.d.ts +2 -0
  94. package/dist/plugin/utils/pageURL.d.ts.map +1 -0
  95. package/dist/plugin/utils/pageURL.js +21 -0
  96. package/dist/plugin/utils/pageURL.js.map +1 -0
  97. package/dist/plugin/utils.js +9 -0
  98. package/dist/plugin/utils.js.map +1 -0
  99. package/dist/plugin/worker/rsc/handleRender.d.ts +6 -2
  100. package/dist/plugin/worker/rsc/handleRender.d.ts.map +1 -1
  101. package/dist/plugin/worker/rsc/handleRender.js +26 -55
  102. package/dist/plugin/worker/rsc/handleRender.js.map +1 -1
  103. package/dist/plugin/worker/rsc/messageHandler.d.ts +1 -2
  104. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
  105. package/dist/plugin/worker/rsc/messageHandler.js +45 -2
  106. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
  107. package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
  108. package/dist/plugin/worker/rsc/state.js +1 -5
  109. package/dist/plugin/worker/rsc/state.js.map +1 -1
  110. package/dist/tsconfig.tsbuildinfo +1 -1
  111. package/package.json +10 -5
  112. package/plugin/config/defaults.tsx +1 -1
  113. package/plugin/config/resolveAutoDiscover.ts +17 -22
  114. package/plugin/config/resolveOptions.ts +5 -1
  115. package/plugin/config/resolveUserConfig.ts +64 -36
  116. package/plugin/helpers/collectBundleManifestCss.ts +1 -160
  117. package/plugin/helpers/collectViteModuleGraphCss.ts +31 -29
  118. package/plugin/helpers/createCssProps.tsx +22 -11
  119. package/plugin/helpers/createRscStream.tsx +42 -46
  120. package/plugin/helpers/formatMetrics.ts +37 -0
  121. package/plugin/helpers/tryManifest.ts +0 -9
  122. package/plugin/html.tsx +1 -1
  123. package/plugin/loader/createBuildLoader.ts +2 -0
  124. package/plugin/metrics/formatMetrics.ts +37 -0
  125. package/plugin/metrics/index.ts +2 -0
  126. package/plugin/react-client/createWorkerStream.ts +107 -0
  127. package/plugin/react-client/plugin.ts +3 -0
  128. package/plugin/react-client/restartWorker.ts +65 -0
  129. package/plugin/react-client/server.ts +97 -146
  130. package/plugin/react-server/server.ts +24 -29
  131. package/plugin/react-static/collectHtmlWorkerContent.ts +1 -1
  132. package/plugin/react-static/collectRscContent.ts +2 -2
  133. package/plugin/react-static/configurePreviewServer.ts +29 -6
  134. package/plugin/react-static/fileWriter.ts +5 -1
  135. package/plugin/react-static/plugin.ts +58 -38
  136. package/plugin/types.ts +11 -11
  137. package/plugin/utils/callServer.ts +25 -0
  138. package/plugin/utils/createReactFetcher.ts +31 -0
  139. package/plugin/utils/index.ts +3 -0
  140. package/plugin/utils/pageURL.ts +28 -0
  141. package/plugin/worker/rsc/handleRender.ts +33 -71
  142. package/plugin/worker/rsc/messageHandler.tsx +48 -6
  143. 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, serializedDevServerConfig } from '../helpers/serializeUserOptions.js';
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
- let currentWorker = null;
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(worker, message)) {
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
- controller.error(error);
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(routeFiles.error.message, {
147
- error: routeFiles.error,
148
- timestamp: true
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 stream = handleWorkerRscStream(currentWorker, {
161
- ...serializedUserOptions,
162
- // we make the worker stream aware of the route, pagePath, propsPath
163
- route,
164
- pagePath: page,
165
- propsPath: props,
166
- // override these at all times to ensure the settings will work for the dev server
167
- projectRoot: server.config.root,
168
- build: serializedUserOptions.build,
169
- manifest: autoDiscoveredFiles.staticManifest,
170
- cssFiles: /* @__PURE__ */ new Map(),
171
- globalCss: /* @__PURE__ */ new Map()
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 = setTimeout(() => {
193
- server.config.logger.error("[react-client] RSC render timeout");
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":";;;;;;;;;;;AAoBA,IAAI,aAAmC,GAAA,IAAA;AACvC,IAAI,YAAe,GAAA,KAAA;AAEnB,eAAe,aACb,CAAA,MAAA,EACA,mBACA,EAAA,WAAA,EACA,UACA,EAAA;AACA,EAAA,IAAI,YAAc,EAAA;AAClB,EAAe,YAAA,GAAA,IAAA;AAEf,EAAI,IAAA;AAEF,IAAA,IAAI,aAAe,EAAA;AACjB,MAAA,aAAA,CAAc,SAAU,EAAA;AACxB,MAAgB,aAAA,GAAA,IAAA;AAAA;AAGlB,IAAM,MAAA,YAAA,GAAe,MAAM,YAAa,CAAA;AAAA,MACtC,WAAA,EAAa,OAAO,MAAO,CAAA,IAAA;AAAA,MAC3B,YAAY,WAAY,CAAA,aAAA;AAAA,MACxB,gBAAkB,EAAA,cAAA;AAAA,MAClB,gBAAkB,EAAA,cAAA;AAAA,MAClB,UAAY,EAAA;AAAA,QACV,SAAS,UAAW,CAAA,KAAA;AAAA,QACpB,cAAA,EAAgB,yBAA0B,CAAA,MAAA,CAAO,MAAM,CAAA;AAAA,QACvD,WAAA,EAAa,iBAAkB,CAAA,WAAA,EAAa,mBAAmB;AAAA,OACjE;AAAA,MACA,YAAA,EAAc,CAAC,UAAA,CAAW,KAAK;AAAA,KAChC,CAAA;AAED,IAAI,IAAA,YAAA,CAAa,SAAS,SAAW,EAAA;AACnC,MAAA,aAAA,GAAgB,YAAa,CAAA,MAAA;AAAA,KAC/B,MAAA,IAAW,YAAa,CAAA,IAAA,KAAS,OAAS,EAAA;AACxC,MAAO,MAAA,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,CAAM,4BAA8B,EAAA;AAAA,QACvD,OAAO,YAAa,CAAA;AAAA,OACrB,CAAA;AAAA;AACH,GACA,SAAA;AACA,IAAe,YAAA,GAAA,KAAA;AAAA;AAEnB;AAYA,gBAAgB,kBAAA,CACd,QACA,OAC2C,EAAA;AAC3C,EAAI,IAAA,cAAA;AACJ,EAAA,IAAI,UAAsB,MAAM;AAAA,GAAC;AAGjC,EAAA,MAAM,MAAM,IAAI,OAAoB,CAAA,CAAC,OAAY,KAAA;AAC/C,IAAA,cAAA,GAAiB,CAACA,QAAoC,KAAA;AACpD,MAAIA,IAAAA,QAAAA,CAAQ,SAAS,WAAa,EAAA;AAChC,QAAA,OAAA,CAAQA,SAAQ,KAAK,CAAA;AAAA;AAEvB,MAAIA,IAAAA,QAAAA,CAAQ,SAAS,OAAS,EAAA;AAC5B,QAAQ,OAAA,CAAA,IAAI,YAAY,CAAA;AAAA;AAC1B,KACF;AAEA,IAAA,OAAA,GAAU,MAAM;AACd,MAAO,MAAA,CAAA,GAAA,CAAI,WAAW,cAAc,CAAA;AAAA,KACtC;AAEA,IAAO,MAAA,CAAA,EAAA,CAAG,WAAW,cAAc,CAAA;AAGnC,IAAA,MAAA,CAAO,WAAY,CAAA;AAAA,MACjB,IAAM,EAAA,YAAA;AAAA,MACN,IAAI,OAAQ,CAAA,KAAA;AAAA,MACZ,GAAG;AAAA,KACJ,CAAA;AAAA,GACF,CAAA;AAGD,EAAA,OAAO,IAAM,EAAA;AACX,IAAA,MAAM,KAAQ,GAAA,MAAM,IAAI,OAAA,CAAoB,CAAC,OAAY,KAAA;AACvD,MAAA,cAAA,GAAiB,CAACA,QAAoC,KAAA;AACpD,QAAIA,IAAAA,QAAAA,CAAQ,SAAS,SAAW,EAAA;AAC9B,UAAQ,OAAA,EAAA;AACR,UAAQ,OAAA,CAAA,IAAI,YAAY,CAAA;AACxB,UAAA;AAAA;AAEF,QAAIA,IAAAA,QAAAA,CAAQ,SAAS,WAAa,EAAA;AAChC,UAAA,OAAA,CAAQA,SAAQ,KAAK,CAAA;AAAA;AAEvB,QAAIA,IAAAA,QAAAA,CAAQ,SAAS,OAAS,EAAA;AAC5B,UAAQ,OAAA,EAAA;AACR,UAAQ,OAAA,CAAA,IAAI,YAAY,CAAA;AACxB,UAAA;AAAA;AACF,OACF;AACA,MAAO,MAAA,CAAA,IAAA,CAAK,WAAW,cAAc,CAAA;AAAA,KACtC,CAAA;AAED,IAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACtB,MAAA;AAAA;AAEF,IAAM,MAAA,KAAA;AAAA;AAEV;AAUgB,SAAA,qBAAA,CACd,QACA,OAC4B,EAAA;AAE5B,EAAA,OAAO,IAAI,cAA2B,CAAA;AAAA,IACpC,MAAM,MAAM,UAAY,EAAA;AACtB,MAAI,IAAA;AACF,QAAA,WAAA,MAAiB,KAAS,IAAA,kBAAA,CAAmB,MAAQ,EAAA,OAAO,CAAG,EAAA;AAC7D,UAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA;AAC1B,eACO,KAAO,EAAA;AACd,QAAA,UAAA,CAAW,MAAM,KAAK,CAAA;AAAA,OACtB,SAAA;AACA,QAAA,UAAA,CAAW,KAAM,EAAA;AAAA;AACnB;AACF,GACD,CAAA;AACH;AAQA,eAAsB,6BAA8B,CAAA;AAAA,EAClD,MAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAa,EAAA,YAAA;AAAA,EACb;AACF,CAKG,EAAA;AACD,EAAI,IAAA;AAAA;AAAA,IAEF,aAAe,EAAA,cAAA;AAAA,IACf,WAAa,EAAA,YAAA;AAAA,IACb,GAAG;AAAA,GACD,GAAA,YAAA;AACJ,EAAA,MAAM,cAAiB,GAAA,MAAA,CAAO,MAAO,CAAA,IAAI,kBAAoB,EAAA;AAAA,IAC3D,aAAA,EACE,OAAO,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,SAAS,QACjC,GAAA,CAAA,EAAG,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,GAAQ,UAAU,MAAM,CAAA,GAAA,EAC9C,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,IACvB,IAAI,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,IAAI,CAC7B,CAAA,GAAA,EAAA;AAAA,IACN,cAAA,EACE,OAAO,MAAO,CAAA,IAAA,KAAS,MACnB,EACA,GAAA,MAAA,CAAO,OAAO,IAAK,CAAA,QAAA,CAAS,GAAG,CAC/B,GAAA,MAAA,CAAO,OAAO,IAAK,CAAA,KAAA,CAAM,GAAG,EAAE,CAAA,GAC9B,OAAO,MAAO,CAAA,IAAA;AAAA,IACpB,WAAA,EAAa,OAAO,MAAO,CAAA;AAAA,GAC5B,CAAA;AAGD,EAAA,MAAM,aAAc,CAAA,MAAA,EAAQ,mBAAqB,EAAA,cAAA,EAAgB,UAAU,CAAA;AAG3E,EAAA,MAAM,OAA0B,GAAA,OAAO,GAAK,EAAA,GAAA,EAAK,IAAS,KAAA;AACxD,IAAI,IAAA,CAAC,IAAI,GAAO,IAAA,GAAA,CAAI,QAAQ,MAAW,KAAA,kBAAA,SAA2B,IAAK,EAAA;AACvE,IAAI,IAAA;AACF,MAAA,IAAI,CAAC,aAAe,EAAA;AAClB,QAAO,MAAA,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,CAAM,oCAAoC,CAAA;AAC/D,QAAA,OAAO,IAAK,EAAA;AAAA;AAId,MAAI,IAAA,KAAA,GAAQ,eAAe,GAAK,EAAA;AAAA,QAC9B,gBAAgB,cAAe,CAAA,cAAA;AAAA,QAC/B,OAAO,cAAe,CAAA;AAAA,OACvB,CAAA;AACD,MAAA,IAAI,CAAC,KAAO,EAAA;AACV,QAAA,OAAO,IAAK,EAAA;AAAA;AAId,MAAA,MAAM,aAAa,MAAM,aAAA;AAAA,QACvB,KAAA;AAAA,QACA,mBAAA;AAAA,QACA;AAAA,OACF;AACA,MAAI,IAAA,UAAA,CAAW,SAAS,OAAS,EAAA;AAC/B,QAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,KAAM,CAAA,UAAA,CAAW,MAAM,OAAS,EAAA;AAAA,UACnD,OAAO,UAAW,CAAA,KAAA;AAAA,UAClB,SAAW,EAAA;AAAA,SACZ,CAAA;AACD,QAAA,OAAO,IAAK,EAAA;AAAA;AAEd,MAAM,MAAA,EAAE,IAAM,EAAA,KAAA,EAAU,GAAA,UAAA;AAGxB,MAAI,GAAA,CAAA,SAAA,CAAU,gBAAgB,iCAAiC,CAAA;AAC/D,MAAI,GAAA,CAAA,SAAA,CAAU,qBAAqB,SAAS,CAAA;AAC5C,MAAI,GAAA,CAAA,SAAA,CAAU,cAAc,YAAY,CAAA;AACxC,MAAA,MAAM,qBAAwB,GAAA,iBAAA;AAAA,QAC5B,cAAA;AAAA,QACA;AAAA,OACF;AACA,MAAM,MAAA,MAAA,GAAS,sBAAsB,aAAe,EAAA;AAAA,QAClD,GAAG,qBAAA;AAAA;AAAA,QAEH,KAAA;AAAA,QACA,QAAU,EAAA,IAAA;AAAA,QACV,SAAW,EAAA,KAAA;AAAA;AAAA,QAEX,WAAA,EAAa,OAAO,MAAO,CAAA,IAAA;AAAA,QAC3B,OAAO,qBAAsB,CAAA,KAAA;AAAA,QAC7B,UAAU,mBAAoB,CAAA,cAAA;AAAA,QAC9B,QAAA,sBAAc,GAAI,EAAA;AAAA,QAClB,SAAA,sBAAe,GAAI;AAAA,OACpB,CAAA;AACD,MAAM,MAAA,WAAA,GAAc,IAAI,cAAe,CAAA;AAAA,QACrC,MAAM,KAAO,EAAA;AACX,UAAA,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,SACjB;AAAA,QAEA,KAAQ,GAAA;AACN,UAAA,YAAA,CAAa,OAAO,CAAA;AACpB,UAAA,GAAA,CAAI,GAAI,EAAA;AAAA,SACV;AAAA,QACA,KAAQ,GAAA;AACN,UAAA,YAAA,CAAa,OAAO,CAAA;AAEpB,UAAA,aAAA;AAAA,YACE,MAAA;AAAA,YACA,mBAAA;AAAA,YACA,cAAA;AAAA,YACA;AAAA,WACF;AACA,UAAA,GAAA,CAAI,GAAI,EAAA;AAAA;AACV,OACD,CAAA;AACD,MAAI,IAAA,OAAA,GAAU,WAAW,MAAM;AAC7B,QAAO,MAAA,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,CAAM,mCAAmC,CAAA;AAC9D,QAAA,GAAA,CAAI,GAAI,EAAA;AAAA,SACP,GAAI,CAAA;AAGP,MAAA,MAAA,CAAO,OAAO,WAAW,CAAA;AAAA,aAClB,KAAO,EAAA;AACd,MAAA,IAAI,iBAAiB,KAAO,EAAA;AAC1B,QAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,KAAM,CAAA,KAAA,CAAM,OAAS,EAAA;AAAA,UACxC;AAAA,SACD,CAAA;AAAA;AACH;AACF,GACF;AAEA,EAAO,MAAA,CAAA,WAAA,CAAY,IAAI,OAAO,CAAA;AAEhC;;;;"}
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,iBAuIA"}
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
- console.log(
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('{"error":"Server restarting..."}');
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 : \"\",\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 console.log(\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('{\"error\":\"Server restarting...\"}');\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(!route?.startsWith(handlerOptions.moduleBasePath)) {\n next();\n } else {\n route = route.slice(handlerOptions.moduleBasePath.length);\n }\n if(typeof route !== \"string\" ) {\n throw new Error(\"req.url is not a string\");\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 // Create a unified event handler\n await server.warmupRequest(pagePath);\n const eventHandler = createEventHandler(onEvent);\n const cssFilesResult = await collectViteModuleGraphCss({\n moduleGraph: server.moduleGraph,\n pagePath,\n loader: (i) => server.ssrLoadModule(i, { fixStacktrace: true }),\n // explicitly set for development server\n moduleBaseURL: handlerOptions.moduleBaseURL,\n moduleBasePath: handlerOptions.moduleBasePath,\n moduleRootPath: handlerOptions.moduleRootPath,\n projectRoot: handlerOptions.projectRoot,\n css: handlerOptions.css,\n parentUrl: pagePath,\n });\n if (cssFilesResult.type === \"skip\") {\n return next();\n }\n if (cssFilesResult.type === \"error\") {\n throw cssFilesResult.error;\n }\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 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
+ {"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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"}
@@ -27,7 +27,7 @@ async function collectHtmlWorkerContent(rscStream, handlerOptions) {
27
27
  callback(null, chunk);
28
28
  },
29
29
  flush(callback) {
30
- metrics.duration = Date.now() - startTime;
30
+ metrics.duration = performance.now() - startTime;
31
31
  callback();
32
32
  }
33
33
  });
@@ -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 = Date.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
+ {"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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"}
@@ -27,7 +27,7 @@ async function collectRscContent(rscStream, handlerOptions) {
27
27
  callback(null, chunk);
28
28
  },
29
29
  flush(callback) {
30
- metrics.duration = Date.now() - startTime;
30
+ metrics.duration = performance.now() - startTime;
31
31
  callback();
32
32
  }
33
33
  });
@@ -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()\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 = Date.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,IAAK,CAAA,GAAA,EAAQ,GAAA,SAAA;AAChC,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
+ {"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,iBAqDA"}
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 [, value] = userOptions.normalizer(req.url);
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 ext = value.slice(value.lastIndexOf("."));
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] || "application/octet-stream";
55
- res.setHeader("Content-Type", `${contentType}; charset=utf-8`);
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(req.url);\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 ext = value.slice(value.lastIndexOf(\".\"));\n if (ext) {\n const filePath = join(staticHostDir, value);\n try {\n const stats = await stat(filePath);\n if (stats.isFile()) {\n const contentType = MIME_TYPES[ext] || \"application/octet-stream\";\n res.setHeader(\"Content-Type\", `${contentType}; charset=utf-8`);\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":";;;;;;;;;;;AAQA,eAAsB,sBAAuB,CAAA;AAAA,EAC3C,MAAA;AAAA,EACA;AACF,CAGG,EAAA;AACD,EAAM,MAAA,aAAA,GAAgB,KAAK,WAAY,CAAA,WAAA,EAAa,YAAY,KAAM,CAAA,MAAA,EAAQ,WAAY,CAAA,KAAA,CAAM,MAAM,CAAA;AACtG,EAAA,MAAA,CAAO,WAAY,CAAA,GAAA,CAAI,OAAO,GAAA,EAAK,KAAK,IAAS,KAAA;AAC/C,IAAG,IAAA,CAAC,IAAI,GAAK,EAAA;AACX,MAAA,OAAO,IAAK,EAAA;AAAA;AAEd,IAAA,MAAM,GAAG,KAAK,IAAI,WAAY,CAAA,UAAA,CAAW,IAAI,GAAG,CAAA;AAEhD,IAAA,MAAM,MAAS,GAAA,WAAA,CAAY,YAAa,CAAA,WAAA,CAAY,KAAK,CAAA;AACzD,IAAA,IAAI,UAAU,GAAI,CAAA,OAAA,CAAQ,MAAQ,EAAA,QAAA,CAAS,WAAW,CAAG,EAAA;AACvD,MAAM,MAAA,SAAA,GAAY,MAAS,GAAA,IAAA,CAAK,aAAe,EAAA,KAAK,CAAI,GAAA,IAAA,CAAK,aAAe,EAAA,KAAA,EAAO,WAAY,CAAA,KAAA,CAAM,cAAc,CAAA;AACnH,MAAI,IAAA;AACF,QAAM,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAS,CAAA;AAClC,QAAI,IAAA,KAAA,CAAM,QAAU,EAAA;AAClB,UAAI,GAAA,CAAA,SAAA,CAAU,gBAAgB,0BAA0B,CAAA;AACxD,UAAA,MAAM,QAAS,CAAA,gBAAA,CAAiB,SAAS,CAAA,EAAG,GAAG,CAAA;AAC/C,UAAA;AAAA;AACF,OACM,CAAA,MAAA;AAAA;AAER;AAEF,IAAA,MAAM,KAAQ,GAAA,WAAA,CAAY,YAAa,CAAA,UAAA,CAAW,KAAK,CAAA;AACvD,IAAA,IAAI,SAAS,GAAI,CAAA,OAAA,CAAQ,MAAQ,EAAA,QAAA,CAAS,kBAAkB,CAAG,EAAA;AAC7D,MAAM,MAAA,GAAA,GAAM,KAAQ,GAAA,IAAA,CAAK,aAAe,EAAA,KAAK,CAAI,GAAA,IAAA,CAAK,aAAe,EAAA,KAAA,EAAO,WAAY,CAAA,KAAA,CAAM,aAAa,CAAA;AAC3G,MAAI,IAAA;AACF,QAAM,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,GAAG,CAAA;AAC5B,QAAI,IAAA,KAAA,CAAM,QAAU,EAAA;AAClB,UAAI,GAAA,CAAA,SAAA,CAAU,gBAAgB,iCAAiC,CAAA;AAC/D,UAAA,MAAM,QAAS,CAAA,gBAAA,CAAiB,GAAG,CAAA,EAAG,GAAG,CAAA;AACzC,UAAA;AAAA;AACF,OACM,CAAA,MAAA;AAAA;AAER;AAEF,IAAA,MAAM,MAAM,KAAM,CAAA,KAAA,CAAM,KAAM,CAAA,WAAA,CAAY,GAAG,CAAC,CAAA;AAC9C,IAAA,IAAI,GAAK,EAAA;AACP,MAAM,MAAA,QAAA,GAAW,IAAK,CAAA,aAAA,EAAe,KAAK,CAAA;AAC1C,MAAI,IAAA;AACF,QAAM,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAQ,CAAA;AACjC,QAAI,IAAA,KAAA,CAAM,QAAU,EAAA;AAClB,UAAM,MAAA,WAAA,GAAc,UAAW,CAAA,GAAG,CAAK,IAAA,0BAAA;AACvC,UAAA,GAAA,CAAI,SAAU,CAAA,cAAA,EAAgB,CAAG,EAAA,WAAW,CAAiB,eAAA,CAAA,CAAA;AAC7D,UAAA,MAAM,QAAS,CAAA,gBAAA,CAAiB,QAAQ,CAAA,EAAG,GAAG,CAAA;AAC9C,UAAA;AAAA;AACF,OACM,CAAA,MAAA;AAAA;AAER;AAEF,IAAK,IAAA,EAAA;AAAA,GACN,CAAA;AACH;;;;"}
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,CAyEf"}
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"}