vite-plugin-react-server 0.3.18 → 0.3.19

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 (208) hide show
  1. package/README.md +119 -118
  2. package/bin/patch.mjs +8 -2
  3. package/dist/package.json +3 -3
  4. package/dist/plugin/checkFilesExist.d.ts.map +1 -1
  5. package/dist/plugin/checkFilesExist.js +6 -2
  6. package/dist/plugin/checkFilesExist.js.map +1 -1
  7. package/dist/plugin/collect-manifest-client-files.d.ts +23 -0
  8. package/dist/plugin/collect-manifest-client-files.d.ts.map +1 -0
  9. package/dist/plugin/collect-manifest-client-files.js +117 -0
  10. package/dist/plugin/collect-manifest-client-files.js.map +1 -0
  11. package/dist/plugin/components.d.ts +9 -9
  12. package/dist/plugin/components.d.ts.map +1 -1
  13. package/dist/plugin/components.js +50 -9
  14. package/dist/plugin/components.js.map +1 -0
  15. package/dist/plugin/config/defaults.d.ts +7 -6
  16. package/dist/plugin/config/defaults.d.ts.map +1 -1
  17. package/dist/plugin/config/defaults.js +8 -5
  18. package/dist/plugin/config/defaults.js.map +1 -1
  19. package/dist/plugin/config/getPaths.d.ts +0 -1
  20. package/dist/plugin/config/getPaths.d.ts.map +1 -1
  21. package/dist/plugin/config/getPaths.js +2 -7
  22. package/dist/plugin/config/getPaths.js.map +1 -1
  23. package/dist/plugin/config/mimeTypes.d.ts +2 -0
  24. package/dist/plugin/config/mimeTypes.d.ts.map +1 -0
  25. package/dist/plugin/config/mimeTypes.js +24 -0
  26. package/dist/plugin/config/mimeTypes.js.map +1 -0
  27. package/dist/plugin/config/resolveOptions.d.ts +1 -1
  28. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  29. package/dist/plugin/config/resolveOptions.js +41 -28
  30. package/dist/plugin/config/resolveOptions.js.map +1 -1
  31. package/dist/plugin/config/resolvePages.d.ts +1 -0
  32. package/dist/plugin/config/resolvePages.d.ts.map +1 -1
  33. package/dist/plugin/config/resolvePages.js +9 -5
  34. package/dist/plugin/config/resolvePages.js.map +1 -1
  35. package/dist/plugin/config/resolveUserConfig.d.ts +2 -1
  36. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  37. package/dist/plugin/config/resolveUserConfig.js +10 -5
  38. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  39. package/dist/plugin/copy-dir.js +23 -18
  40. package/dist/plugin/copy-dir.js.map +1 -0
  41. package/dist/plugin/helpers/createHandler.d.ts +22 -0
  42. package/dist/plugin/helpers/createHandler.d.ts.map +1 -0
  43. package/dist/plugin/{react-server → helpers}/createHandler.js +36 -48
  44. package/dist/plugin/helpers/createHandler.js.map +1 -0
  45. package/dist/plugin/{react-server → helpers}/createRscStream.d.ts +2 -1
  46. package/dist/plugin/helpers/createRscStream.d.ts.map +1 -0
  47. package/dist/plugin/helpers/createRscStream.js +71 -0
  48. package/dist/plugin/helpers/createRscStream.js.map +1 -0
  49. package/dist/plugin/helpers/getBundleManifest.d.ts.map +1 -1
  50. package/dist/plugin/helpers/getBundleManifest.js +12 -4
  51. package/dist/plugin/helpers/getBundleManifest.js.map +1 -1
  52. package/dist/plugin/loader/createBuildLoader.d.ts +1 -1
  53. package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
  54. package/dist/plugin/loader/createBuildLoader.js +8 -5
  55. package/dist/plugin/loader/createBuildLoader.js.map +1 -1
  56. package/dist/plugin/loader/css-loader.d.ts.map +1 -1
  57. package/dist/plugin/loader/css-loader.js.map +1 -1
  58. package/dist/plugin/loader/react-loader.js +2 -2
  59. package/dist/plugin/loader/react-loader.js.map +1 -1
  60. package/dist/plugin/preserver/plugin.d.ts.map +1 -1
  61. package/dist/plugin/preserver/plugin.js +49 -14
  62. package/dist/plugin/preserver/plugin.js.map +1 -1
  63. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  64. package/dist/plugin/react-client/plugin.js +18 -76
  65. package/dist/plugin/react-client/plugin.js.map +1 -1
  66. package/dist/plugin/react-server/index.d.ts.map +1 -1
  67. package/dist/plugin/react-server/index.js +2 -0
  68. package/dist/plugin/react-server/index.js.map +1 -1
  69. package/dist/plugin/react-server/plugin.d.ts +2 -1
  70. package/dist/plugin/react-server/plugin.d.ts.map +1 -1
  71. package/dist/plugin/react-server/plugin.js +53 -217
  72. package/dist/plugin/react-server/plugin.js.map +1 -1
  73. package/dist/plugin/react-static/index.d.ts +2 -0
  74. package/dist/plugin/react-static/index.d.ts.map +1 -0
  75. package/dist/plugin/react-static/index.js +1 -0
  76. package/dist/plugin/react-static/plugin.d.ts +7 -0
  77. package/dist/plugin/react-static/plugin.d.ts.map +1 -0
  78. package/dist/plugin/react-static/plugin.js +199 -0
  79. package/dist/plugin/react-static/plugin.js.map +1 -0
  80. package/dist/plugin/resolvePage.d.ts.map +1 -1
  81. package/dist/plugin/resolvePage.js +9 -0
  82. package/dist/plugin/resolvePage.js.map +1 -1
  83. package/dist/plugin/root.d.ts +2 -0
  84. package/dist/plugin/root.d.ts.map +1 -0
  85. package/dist/plugin/root.js +12 -0
  86. package/dist/plugin/root.js.map +1 -0
  87. package/dist/plugin/transformer/plugin.d.ts.map +1 -1
  88. package/dist/plugin/transformer/plugin.js +32 -23
  89. package/dist/plugin/transformer/plugin.js.map +1 -1
  90. package/dist/plugin/transformer/types.d.ts +1 -18
  91. package/dist/plugin/transformer/types.d.ts.map +1 -1
  92. package/dist/plugin/types.d.ts +24 -6
  93. package/dist/plugin/types.d.ts.map +1 -1
  94. package/dist/plugin/worker/createWorker.js +0 -1
  95. package/dist/plugin/worker/createWorker.js.map +1 -1
  96. package/dist/plugin/worker/html/html-worker.development.d.ts +30 -0
  97. package/dist/plugin/worker/html/html-worker.development.d.ts.map +1 -1
  98. package/dist/plugin/worker/html/html-worker.development.js +30 -2
  99. package/dist/plugin/worker/html/html-worker.development.js.map +1 -1
  100. package/dist/plugin/worker/html/html-worker.production.js +3 -5
  101. package/dist/plugin/worker/html/html-worker.production.js.map +1 -1
  102. package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
  103. package/dist/plugin/worker/html/messageHandler.js +8 -2
  104. package/dist/plugin/worker/html/messageHandler.js.map +1 -1
  105. package/dist/plugin/worker/html/plugin.d.ts.map +1 -1
  106. package/dist/plugin/worker/html/plugin.js +2 -3
  107. package/dist/plugin/worker/html/renderPages.d.ts +8 -4
  108. package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
  109. package/dist/plugin/worker/html/renderPages.js +118 -83
  110. package/dist/plugin/worker/html/renderPages.js.map +1 -1
  111. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
  112. package/dist/plugin/worker/rsc/messageHandler.js +89 -84
  113. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
  114. package/dist/plugin/worker/rsc/plugin.d.ts.map +1 -1
  115. package/dist/plugin/worker/rsc/plugin.js +1 -2
  116. package/dist/plugin/worker/rsc/rsc-worker.development.js +13 -18
  117. package/dist/plugin/worker/rsc/rsc-worker.development.js.map +1 -1
  118. package/dist/plugin/worker/rsc/rsc-worker.production.js +4 -1
  119. package/dist/plugin/worker/rsc/rsc-worker.production.js.map +1 -1
  120. package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
  121. package/dist/plugin/worker/rsc/state.js.map +1 -1
  122. package/dist/tsconfig.tsbuildinfo +1 -1
  123. package/package.json +3 -3
  124. package/plugin/checkFilesExist.ts +7 -3
  125. package/plugin/collect-manifest-client-files.ts +152 -0
  126. package/plugin/components.tsx +55 -10
  127. package/plugin/config/defaults.tsx +69 -0
  128. package/plugin/config/getPaths.ts +1 -7
  129. package/plugin/config/mimeTypes.ts +17 -0
  130. package/plugin/config/resolveOptions.ts +48 -40
  131. package/plugin/config/resolvePages.ts +8 -4
  132. package/plugin/config/resolveUserConfig.ts +12 -9
  133. package/plugin/{react-server → helpers}/createHandler.ts +46 -63
  134. package/plugin/helpers/createRscStream.ts +81 -0
  135. package/plugin/helpers/getBundleManifest.ts +14 -5
  136. package/plugin/loader/createBuildLoader.ts +9 -6
  137. package/plugin/loader/css-loader.ts +0 -2
  138. package/plugin/loader/react-loader.ts +2 -2
  139. package/plugin/preserver/plugin.ts +64 -17
  140. package/plugin/react-client/plugin.ts +20 -91
  141. package/plugin/react-server/index.ts +2 -0
  142. package/plugin/react-server/plugin.ts +66 -293
  143. package/plugin/react-static/index.ts +1 -0
  144. package/plugin/react-static/plugin.ts +247 -0
  145. package/plugin/resolvePage.ts +9 -0
  146. package/plugin/root.ts +4 -0
  147. package/plugin/transformer/plugin.ts +40 -31
  148. package/plugin/transformer/types.ts +0 -19
  149. package/plugin/types.ts +25 -6
  150. package/plugin/worker/createWorker.ts +1 -1
  151. package/plugin/worker/html/README.md +63 -0
  152. package/plugin/worker/html/html-worker.development.tsx +89 -2
  153. package/plugin/worker/html/html-worker.production.tsx +8 -10
  154. package/plugin/worker/html/messageHandler.ts +8 -2
  155. package/plugin/worker/html/plugin.ts +2 -3
  156. package/plugin/worker/html/renderPages.ts +150 -114
  157. package/plugin/worker/rsc/README.md +58 -0
  158. package/plugin/worker/rsc/messageHandler.tsx +95 -111
  159. package/plugin/worker/rsc/plugin.ts +1 -2
  160. package/plugin/worker/rsc/rsc-worker.development.ts +12 -22
  161. package/plugin/worker/rsc/rsc-worker.production.ts +5 -1
  162. package/plugin/worker/rsc/state.ts +0 -3
  163. package/scripts/react+0.0.0-experimental-eda36a1c-20250228.patch +114 -12
  164. package/scripts/react-dom+0.0.0-experimental-eda36a1c-20250228.patch +10571 -121
  165. package/tsconfig.json +2 -2
  166. package/dist/plugin/collect-css-manifest.d.ts +0 -4
  167. package/dist/plugin/collect-css-manifest.d.ts.map +0 -1
  168. package/dist/plugin/collect-css-manifest.js +0 -65
  169. package/dist/plugin/collect-css-manifest.js.map +0 -1
  170. package/dist/plugin/config/createModuleIdGenerator.d.ts +0 -11
  171. package/dist/plugin/config/createModuleIdGenerator.d.ts.map +0 -1
  172. package/dist/plugin/config/createModuleIdGenerator.js +0 -44
  173. package/dist/plugin/config/createModuleIdGenerator.js.map +0 -1
  174. package/dist/plugin/loader/createCssLoader.d.ts +0 -30
  175. package/dist/plugin/loader/createCssLoader.d.ts.map +0 -1
  176. package/dist/plugin/loader/createCssLoader.js +0 -35
  177. package/dist/plugin/loader/createPageLoader.d.ts +0 -24
  178. package/dist/plugin/loader/createPageLoader.d.ts.map +0 -1
  179. package/dist/plugin/loader/createPageLoader.js +0 -50
  180. package/dist/plugin/loader/rsc/messageHandler.d.ts +0 -2
  181. package/dist/plugin/loader/rsc/messageHandler.d.ts.map +0 -1
  182. package/dist/plugin/loader/rsc/messageHandler.js +0 -1
  183. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts +0 -2
  184. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts.map +0 -1
  185. package/dist/plugin/loader/rsc/rsc-worker.development.js +0 -1
  186. package/dist/plugin/react-server/createHandler.d.ts +0 -17
  187. package/dist/plugin/react-server/createHandler.d.ts.map +0 -1
  188. package/dist/plugin/react-server/createHandler.js.map +0 -1
  189. package/dist/plugin/react-server/createRscStream.d.ts.map +0 -1
  190. package/dist/plugin/react-server/createRscStream.js +0 -70
  191. package/dist/plugin/react-server/createRscStream.js.map +0 -1
  192. package/dist/plugin/react-server/createSsrHandler.d.ts +0 -4
  193. package/dist/plugin/react-server/createSsrHandler.d.ts.map +0 -1
  194. package/dist/plugin/react-server/createSsrHandler.js +0 -95
  195. package/dist/plugin/utils/logger.d.ts +0 -9
  196. package/dist/plugin/utils/logger.d.ts.map +0 -1
  197. package/dist/plugin/utils/logger.js +0 -68
  198. package/dist/plugin/utils/logger.js.map +0 -1
  199. package/plugin/collect-css-manifest.ts +0 -82
  200. package/plugin/config/createModuleIdGenerator.ts +0 -52
  201. package/plugin/config/defaults.ts +0 -51
  202. package/plugin/loader/createCssLoader.ts +0 -73
  203. package/plugin/loader/createPageLoader.ts +0 -103
  204. package/plugin/loader/rsc/messageHandler.tsx +0 -1
  205. package/plugin/loader/rsc/rsc-worker.development.ts +0 -1
  206. package/plugin/react-server/createRscStream.ts +0 -86
  207. package/plugin/react-server/createSsrHandler.ts +0 -125
  208. package/plugin/utils/logger.ts +0 -52
@@ -12,21 +12,18 @@ import { dirname, join } from "node:path";
12
12
  import { getBundleManifest } from "../helpers/getBundleManifest.js";
13
13
  import { checkFilesExist } from "../checkFilesExist.js";
14
14
  import { resolvePages } from "../config/resolvePages.js";
15
- import { tryManifest } from "../helpers/tryManifest.js";
16
15
  import { createInputNormalizer } from "../helpers/inputNormalizer.js";
17
16
  import { createWorker } from "../worker/createWorker.js";
18
17
  import type { Worker } from "node:worker_threads";
19
- import { getPluginRoot } from "../config/getPaths.js";
20
18
  import { DEFAULT_CONFIG } from "../config/defaults.js";
21
19
  import type {
22
20
  RscRenderMessage,
23
21
  RscWorkerMessage,
24
22
  RscWorkerResponse,
25
23
  } from "../worker/types.js";
26
- import { createLogger } from "../utils/logger.js";
27
- import { readFileSync } from "node:fs";
24
+ import { MIME_TYPES } from "../config/mimeTypes.js";
25
+
28
26
 
29
- const log = createLogger("react-client");
30
27
  let userOptions: ResolvedUserOptions;
31
28
  let userConfig: ResolvedUserConfig;
32
29
  let clientManifest: Manifest = {};
@@ -44,9 +41,6 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
44
41
  }
45
42
  userOptions = resolvedOptions.userOptions;
46
43
  root = userOptions.projectRoot;
47
- const rscWorkerPath = join(getPluginRoot(), DEFAULT_CONFIG.RSC_WORKER_PATH);
48
-
49
- log.info("RSC worker path:" + rscWorkerPath);
50
44
 
51
45
  return {
52
46
  name: "vite:react-client",
@@ -64,7 +58,7 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
64
58
  if (configEnv.command === "serve" && !configEnv.isPreview && !worker) {
65
59
  worker = await createWorker({
66
60
  projectRoot: root,
67
- workerPath: rscWorkerPath,
61
+ workerPath: userOptions.rscWorkerPath,
68
62
  reverseCondition: true,
69
63
  });
70
64
  }
@@ -106,7 +100,7 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
106
100
  resolvedConfig = config;
107
101
  },
108
102
 
109
- async generateBundle(options, bundle) {
103
+ async generateBundle(_options, bundle) {
110
104
  // Create manifest entries for each chunk
111
105
  clientManifest = getBundleManifest({
112
106
  pluginContext: this,
@@ -147,84 +141,23 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
147
141
  const [key, value] = normalize(req.url);
148
142
  const fileRoot = key.startsWith("node_modules")
149
143
  ? root
150
- : join(root, userOptions.build.outDir, userOptions.build.client);
151
- if (value.endsWith(".js")) {
152
- try {
153
- const stats = await stat(join(fileRoot, value));
154
- if (stats.isFile()) {
155
- const content = await readFile(join(fileRoot, value), "utf-8");
156
- res.setHeader("Content-Type", "application/javascript");
157
- res.end(content);
158
- return;
159
- } else {
160
- next();
161
- }
162
- } catch (error) {
163
- const { manifest: clientManifest } = tryManifest({
164
- root,
165
- outDir: join(userOptions.build.outDir, userOptions.build.client),
166
- });
167
- const { manifest: serverManifest } = tryManifest({
168
- root,
169
- outDir: join(userOptions.build.outDir, userOptions.build.server),
170
- });
171
- if (clientManifest && value in clientManifest) {
172
- res.setHeader("Content-Type", "application/javascript");
173
- res.end(clientManifest[value]);
174
- return;
175
- } else if (serverManifest && value in serverManifest) {
176
- res.setHeader("Content-Type", "application/javascript");
177
- res.end(serverManifest[value]);
178
- return;
179
- }
180
- const foundClient =
181
- clientManifest &&
182
- Object.entries(clientManifest).find(
183
- ([key, value]) =>
184
- value === key ||
185
- value === value.file ||
186
- value === value.src ||
187
- value === value.name
188
- );
189
- if (foundClient) {
190
- res.setHeader("Content-Type", "application/javascript");
191
- res.end(foundClient);
192
- return;
193
- }
194
- const foundServer =
195
- serverManifest &&
196
- Object.entries(serverManifest).find(
197
- ([key, value]) =>
198
- value === key ||
199
- value === value.file ||
200
- value === value.src ||
201
- value === value.name
202
- );
203
-
204
- if (foundServer) {
205
- res.setHeader("Content-Type", "application/javascript");
206
- res.end(foundServer);
207
- return;
208
- }
209
- next();
210
- }
211
- } else {
212
- let html = '';
213
- try {
214
- const last = value.split('/').pop();
215
- if(!last?.includes('.')) {
216
- const isDir = await stat(join(fileRoot, value));
217
- if (isDir.isDirectory()) {
218
- html = readFileSync(join(fileRoot, value, 'index.html'), 'utf-8');
219
- res.setHeader("Content-Type", "text/html");
220
- res.end(html);
221
- return;
222
- }
223
- }
224
- } catch (error) {
225
-
144
+ : join(root, userOptions.build.outDir, userOptions.build.static);
145
+ try {
146
+ const filePath = join(fileRoot, value);
147
+ const stats = await stat(filePath);
148
+
149
+ if (stats.isFile()) {
150
+ const ext = value.slice(value.lastIndexOf('.'));
151
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream';
152
+ res.setHeader('Content-Type', contentType);
153
+ const content = await readFile(filePath);
154
+ res.end(content);
155
+ return;
226
156
  }
227
157
  next();
158
+ } catch (error) {
159
+ console.log("Error serving static file:", error);
160
+ next();
228
161
  }
229
162
  });
230
163
  },
@@ -234,13 +167,11 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
234
167
  loader = server.ssrLoadModule;
235
168
  }
236
169
  if (!worker) {
237
- log.info("Creating RSC worker...");
238
170
  worker = await createWorker({
239
171
  projectRoot: root,
240
- workerPath: rscWorkerPath,
172
+ workerPath: userOptions.rscWorkerPath,
241
173
  condition: "react-client",
242
174
  });
243
- log.info("RSC worker created");
244
175
  }
245
176
  const normalize = createInputNormalizer({
246
177
  root,
@@ -323,7 +254,6 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
323
254
 
324
255
  case "ERROR":
325
256
  clearTimeout(timeout);
326
- log.error("Render error", message);
327
257
  if (!hasError) {
328
258
  hasError = true;
329
259
  res.statusCode = 500;
@@ -377,7 +307,6 @@ export function reactClientPlugin(options: StreamPluginOptions): Plugin {
377
307
  cssFiles: []
378
308
  } satisfies RscRenderMessage);
379
309
  } catch (error) {
380
- log.error("Middleware error:", error);
381
310
  res.statusCode = 500;
382
311
  res.end(error instanceof Error ? error.message : String(error));
383
312
  }
@@ -1,4 +1,5 @@
1
1
  import { reactPreservePlugin } from "../preserver/plugin.js";
2
+ import { reactStaticPlugin } from "../react-static/plugin.js";
2
3
  import { reactTransformPlugin } from "../transformer/plugin.js";
3
4
  import type { StreamPluginOptions } from "../types.js";
4
5
  import { reactServerPlugin } from "./plugin.js";
@@ -7,6 +8,7 @@ export function vitePluginReactServer(options = {} as StreamPluginOptions): impo
7
8
  return [
8
9
  reactTransformPlugin(options),
9
10
  reactServerPlugin(options),
11
+ reactStaticPlugin(options),
10
12
  reactPreservePlugin(options),
11
13
  ];
12
14
  }
@@ -1,6 +1,5 @@
1
- import { join, resolve, dirname } from "node:path";
1
+ import { join, dirname } from "node:path";
2
2
  import { performance } from "node:perf_hooks";
3
- import { Worker } from "node:worker_threads";
4
3
  import React from "react";
5
4
  import {
6
5
  createLogger,
@@ -8,43 +7,31 @@ import {
8
7
  type UserConfig,
9
8
  type ViteDevServer,
10
9
  type Manifest,
11
- build,
10
+ type Plugin as VitePlugin,
12
11
  } from "vite";
13
12
  import { checkFilesExist } from "../checkFilesExist.js";
14
- import { DEFAULT_CONFIG } from "../config/defaults.js";
15
- import { getPluginRoot } from "../config/getPaths.js";
16
13
  import { resolveOptions } from "../config/resolveOptions.js";
17
14
  import { resolvePages } from "../config/resolvePages.js";
18
15
  import { resolveUserConfig } from "../config/resolveUserConfig.js";
19
- import { tryManifest } from "../helpers/tryManifest.js";
20
- import { createBuildLoader } from "../loader/createBuildLoader.js";
21
16
  import type {
22
17
  BuildTiming,
23
18
  CheckFilesExistReturn,
24
19
  ReactStreamPluginMeta,
25
- ResolvedUserConfig,
26
20
  ResolvedUserOptions,
27
21
  } from "../types.js";
28
22
  import { type StreamPluginOptions } from "../types.js";
29
- import { createWorker } from "../worker/createWorker.js";
30
- import { renderPages } from "../worker/html/renderPages.js";
31
- import { createHandler } from "./createHandler.js";
32
- import { mkdir, readFile, writeFile } from "node:fs/promises";
23
+ import { createHandler } from "../helpers/createHandler.js";
24
+ import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
33
25
  import { getBundleManifest } from "../helpers/getBundleManifest.js";
34
26
  import type { ServerResponse } from "node:http";
35
- import { collectManifestCss } from "../collect-css-manifest.js";
36
- import { cssFiles } from "../worker/rsc/state.js";
27
+ import { createInputNormalizer } from "../helpers/inputNormalizer.js";
28
+ import { MIME_TYPES } from "../config/mimeTypes.js";
37
29
 
38
30
  let resolvedConfig: ResolvedConfig | null = null;
39
31
  let serverManifestPath: string | null = null;
40
- let clientManifestPath: string | null = null;
41
- let outpuptBundle: any;
42
- let outputOptions: any;
43
32
  let loader: ((id: string) => Promise<Record<string, any>>) | null = null;
44
- let worker: Worker;
45
- export function reactServerPlugin(
46
- options: StreamPluginOptions
47
- ): import("vite").Plugin<{
33
+
34
+ export function reactServerPlugin(options: StreamPluginOptions): VitePlugin<{
48
35
  meta: ReactStreamPluginMeta;
49
36
  addCssFile: (path: string) => void;
50
37
  }> {
@@ -55,39 +42,14 @@ export function reactServerPlugin(
55
42
  let files: CheckFilesExistReturn;
56
43
  // let env: Awaited<ReturnType<typeof getEnv>>;
57
44
  let cssModules = new Set<string>();
58
- let clientComponents = new Map<string, string>();
59
45
  // let define: Record<string, string>;
60
46
  let buildCssFiles = new Set<string>();
61
47
  let root: string = process.cwd();
62
- let userConfig: ResolvedUserConfig;
63
48
  let userOptions: ResolvedUserOptions;
64
- let moduleGraph: Record<
65
- string,
66
- {
67
- file: string;
68
- src: string;
69
- name: string;
70
- isEntry: boolean;
71
- imports: string[];
72
- dynamicImports: string[];
73
- }
74
- > = {};
49
+ let resolvedPages: string[];
75
50
  let serverManifest: Manifest = {};
76
51
 
77
- interface BuildStats {
78
- htmlFiles: number;
79
- clientComponents: number;
80
- cssFiles: number;
81
- totalRoutes: number;
82
- timing: {
83
- config: number;
84
- build: number;
85
- render: number;
86
- total: number;
87
- };
88
- }
89
-
90
- const resolvedOptions = resolveOptions(options);
52
+ const resolvedOptions = resolveOptions(options, false);
91
53
  if (resolvedOptions.type === "error") {
92
54
  throw resolvedOptions.error;
93
55
  }
@@ -105,6 +67,7 @@ export function reactServerPlugin(
105
67
  root
106
68
  );
107
69
  }
70
+
108
71
  return {
109
72
  name: "vite:react-stream-server",
110
73
  enforce: "post",
@@ -122,11 +85,6 @@ export function reactServerPlugin(
122
85
  userOptions.build.server,
123
86
  ".vite/manifest.json"
124
87
  );
125
- clientManifestPath = join(
126
- resolvedConfig.build.outDir,
127
- userOptions.build.client,
128
- ".vite/manifest.json"
129
- );
130
88
  timing.configResolved = performance.now();
131
89
 
132
90
  // Verify transformer runs first, preserver runs last
@@ -147,7 +105,45 @@ export function reactServerPlugin(
147
105
  );
148
106
  }
149
107
  },
150
- async configurePreviewServer(server) {},
108
+
109
+ async configurePreviewServer(server) {
110
+ if (root !== server.config.root) {
111
+ root = server.config.root;
112
+ }
113
+ if (typeof loader !== "function") {
114
+ loader = (id: string) => import(id);
115
+ }
116
+ const normalize = createInputNormalizer({
117
+ root,
118
+ removeExtension: false,
119
+ preserveModulesRoot: userOptions.build.preserveModulesRoot
120
+ ? userOptions.moduleBase
121
+ : undefined,
122
+ });
123
+ server.middlewares.use(async (req, res, next) => {
124
+ const [key, value] = normalize(req.url);
125
+ const fileRoot = key.startsWith("node_modules")
126
+ ? root
127
+ : join(root, userOptions.build.outDir, userOptions.build.static);
128
+ try {
129
+ const filePath = join(fileRoot, value);
130
+ const stats = await stat(filePath);
131
+
132
+ if (stats.isFile()) {
133
+ const ext = value.slice(value.lastIndexOf('.'));
134
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream';
135
+ res.setHeader('Content-Type', contentType);
136
+ const content = await readFile(filePath);
137
+ res.end(content);
138
+ return;
139
+ }
140
+ next();
141
+ } catch (error) {
142
+ console.log("Error serving static file:", error);
143
+ next();
144
+ }
145
+ });
146
+ },
151
147
  async configureServer(server: ViteDevServer) {
152
148
  if (typeof loader !== "function") {
153
149
  loader = server.ssrLoadModule;
@@ -186,35 +182,31 @@ export function reactServerPlugin(
186
182
  activeStreams.clear();
187
183
  });
188
184
 
189
- // server.ws.on("connection", (_socket, _req) => {
190
- // console.log("[vite-plugin-react-server] hooking up ws connection");
191
- // });
192
-
193
- // server.ws.on("listening", () => {
194
- // console.log("[vite-plugin-react-server] hooking up ws listening");
195
- // });
196
-
197
185
  server.middlewares.use(async (req, res, next) => {
198
186
  if (req.headers.accept !== "text/x-component") return next();
199
187
  if (typeof loader !== "function") {
200
188
  loader = server.ssrLoadModule;
201
189
  }
190
+ const route = req.url?.replace('/index.rsc', '');
202
191
  try {
203
- const handler = await createHandler(
204
- req.url ?? "",
205
- {
192
+ const handler = await createHandler({
193
+ url: !route || route === "" ? "/" : route,
194
+ urlMap: files.urlMap,
195
+ pluginOptions: {
206
196
  ...userOptions,
207
197
  // we'll leave the Html generation for later
208
198
  Html: React.Fragment,
209
199
  projectRoot: root,
210
200
  },
211
- {
201
+ streamOptions: {
212
202
  cssFiles: [],
213
203
  logger: createLogger(),
214
204
  loader,
215
205
  moduleGraph: server.moduleGraph,
206
+ moduleBasePath: '',
207
+ moduleBaseURL: '',
216
208
  }
217
- );
209
+ });
218
210
  if (handler.type === "success") {
219
211
  handler.stream?.pipe(res);
220
212
  }
@@ -240,12 +232,12 @@ export function reactServerPlugin(
240
232
  );
241
233
  root = config.root;
242
234
  }
243
- const resolvedPages = await resolvePages(userOptions.build.pages);
244
- if (resolvedPages.type === "error") {
245
- throw resolvedPages.error;
235
+ const resolvedPagesResult = await resolvePages(userOptions.build.pages);
236
+ if (resolvedPagesResult.type === "error") {
237
+ throw resolvedPagesResult.error;
246
238
  }
247
-
248
- files = await checkFilesExist(resolvedPages.pages, userOptions, root);
239
+ resolvedPages = resolvedPagesResult.pages;
240
+ files = await checkFilesExist(resolvedPages, userOptions, root);
249
241
 
250
242
  const resolvedConfig = resolveUserConfig({
251
243
  isClient: false,
@@ -259,7 +251,6 @@ export function reactServerPlugin(
259
251
  throw resolvedConfig.error;
260
252
  }
261
253
 
262
- userConfig = resolvedConfig.userConfig;
263
254
  return resolvedConfig.userConfig;
264
255
  },
265
256
  async buildStart() {
@@ -269,234 +260,16 @@ export function reactServerPlugin(
269
260
  console.log("Build already started");
270
261
  }
271
262
  },
272
- async closeBundle() {
273
- if (!userConfig || resolvedConfig?.command !== "build") return;
274
- try {
275
- timing.renderStart = performance.now();
276
-
277
- // Get the client manifest
278
- const clientManifestResult = tryManifest({
279
- root: root,
280
- outDir: join(userOptions.build.outDir, userOptions.build.client),
281
- ssrManifest: false,
282
- });
283
-
284
- if (clientManifestResult.type === "error") {
285
- throw clientManifestResult.error;
286
- }
287
-
288
- const clientManifest = clientManifestResult.manifest;
289
-
290
-
291
- worker = await createWorker({
292
- projectRoot: root,
293
- workerPath: userOptions.htmlWorkerPath,
294
- condition: 'react-server',
295
- reverseCondition: true,
296
- mode: (resolvedConfig?.mode ?? "production") as
297
- | "production"
298
- | "development",
299
- nodeOptions: "--conditions=react-client",
300
- });
301
-
302
- // Create the loader
303
- if (typeof loader !== "function") {
304
- if (!Object.keys(serverManifest).length) {
305
- console.warn(
306
- "[vite-plugin-react-server] No server manifest found, the plugin will try to use the plugin context - it may differ from vite's manifest."
307
- );
308
- serverManifest = getBundleManifest({
309
- pluginContext: this,
310
- bundle: outpuptBundle,
311
- moduleBase: userOptions.moduleBase,
312
- preserveModulesRoot: userOptions.build.preserveModulesRoot,
313
- });
314
- if (!Object.keys(serverManifest).length) {
315
- console.warn(
316
- "[vite-plugin-react-server] That didn't work, retrying to read manifest."
317
- );
318
- const resolvedServerManifest = tryManifest({
319
- root: root,
320
- outDir: join(
321
- userOptions.build.outDir,
322
- userOptions.build.server
323
- ),
324
- ssrManifest: false,
325
- });
326
- if (resolvedServerManifest.type === "error") {
327
- // dont build the static files without a server manifest
328
- console.error(
329
- "[vite-plugin-react-server] Failed to read manifest, aborting build."
330
- );
331
- return;
332
- }
333
- serverManifest = resolvedServerManifest.manifest;
334
- }
335
- }
336
- loader = createBuildLoader({
337
- root: root,
338
- userConfig,
339
- userOptions,
340
- pluginContext: this,
341
- serverManifest,
342
- clientManifest,
343
- });
344
- }
345
- const resolvedPages = await resolvePages(userOptions.build.pages);
346
- if (resolvedPages.type === "error") {
347
- throw resolvedPages.error;
348
- }
349
-
350
- const onCssFile = async (path: string, parentUrl: string) => {
351
- if (buildCssFiles && path.endsWith(".css")) {
352
- buildCssFiles.add(path);
353
- if (parentUrl.endsWith(userOptions.build.client)) {
354
- // copy the file to the client build dir
355
- const serverPath = join(
356
- userOptions.build.outDir,
357
- userOptions.build.server,
358
- path
359
- );
360
- await writeFile(
361
- serverPath,
362
- await readFile(
363
- join(
364
- root,
365
- userOptions.build.outDir,
366
- userOptions.build.client,
367
- path
368
- )
369
- )
370
- );
371
- } else {
372
- // copy the file to the client build dir, assume it's in server build dir
373
- const clientPath = join(
374
- userOptions.build.outDir,
375
- userOptions.build.client,
376
- path
377
- );
378
- await mkdir(dirname(clientPath), { recursive: true });
379
- await writeFile(
380
- clientPath,
381
- await readFile(
382
- join(
383
- root,
384
- userOptions.build.outDir,
385
- userOptions.build.server,
386
- path
387
- )
388
- )
389
- );
390
- }
391
- }
392
- };
393
-
394
- const { failedRoutes, completedRoutes } = await renderPages(
395
- this,
396
- resolvedPages.pages,
397
- files,
398
- {
399
- pipableStreamOptions: {
400
- bootstrapModules: clientManifest["index.html"]?.file
401
- ? [clientManifest["index.html"].file.startsWith('/') ? clientManifest["index.html"].file : '/' + clientManifest["index.html"].file]
402
- : [],
403
- },
404
- moduleBasePath: "",
405
- moduleBaseURL: "",
406
- clientCss: clientManifest["index.html"]?.css
407
- ? clientManifest["index.html"].css.map(css => css.startsWith('/') ? css : '/' + css)
408
- : [],
409
- userConfig,
410
- pluginOptions: userOptions,
411
- worker: worker,
412
- clientManifest: clientManifest,
413
- serverManifest: serverManifest,
414
- loader,
415
- onCssFile: onCssFile,
416
- }
417
- );
418
-
419
- if (failedRoutes.size) {
420
- console.error(
421
- "[vite-plugin-react-server] Failed to render routes:",
422
- failedRoutes
423
- );
424
- }
425
- if (worker) await worker.terminate();
426
-
427
- timing.renderEnd = performance.now();
428
- timing.total = (timing.renderEnd - timing.start) / 1000;
429
-
430
- // Update stats to include CSS and client components
431
- const stats: BuildStats = {
432
- htmlFiles: files.urlMap.size,
433
- clientComponents: clientComponents.size,
434
- cssFiles: cssFiles.size,
435
- totalRoutes: files.urlMap.size,
436
- timing: {
437
- config: ((timing.configResolved ?? 0) - timing.start) / 1000,
438
- build:
439
- ((timing.buildStart ?? 0) - (timing.configResolved ?? 0)) / 1000,
440
- render:
441
- ((timing.renderEnd ?? 0) - (timing.renderStart ?? 0)) / 1000,
442
- total: (timing.renderEnd ?? 0 - timing.start) / 1000,
443
- },
444
- };
445
-
446
- // Format duration helper
447
- const formatDuration = (seconds: number) => {
448
- if (seconds < 0.001) {
449
- return `${(seconds * 1000000).toFixed(0)}μs`;
450
- }
451
- if (seconds < 1) {
452
- return `${(seconds * 1000).toFixed(0)}ms`;
453
- }
454
- return `${seconds.toFixed(2)}s`;
455
- };
456
-
457
- console.log("\n[vite-plugin-react-server] Build Summary:");
458
- console.log("─".repeat(50));
459
- console.log(`🎨 Included ${buildCssFiles.size} CSS files`);
460
- console.log(`🛣️ Total routes: ${files.urlMap.size}`);
461
- console.log("─".repeat(50));
462
- console.log("⏱️ Timing:");
463
- console.log(` Config: ${formatDuration(stats.timing.config)}`);
464
- console.log(` Build: ${formatDuration(stats.timing.build)}`);
465
- console.log(` Render: ${formatDuration(stats.timing.render)}`);
466
- console.log(" ".repeat(12));
467
- console.log(` Total: ${formatDuration(stats.timing.total)}`);
468
- console.log("─".repeat(50));
469
-
470
- // Ensure worker is terminated
471
- if (worker) {
472
- await worker.terminate();
473
- worker = null as any;
474
- }
475
- } catch (error) {
476
- console.error("[vite-plugin-react-server] Build failed:", error);
477
- // Make sure to terminate worker even on error
478
- if (worker) await worker.terminate();
479
- worker = null as any;
480
- throw error;
481
- }
482
- },
483
- async buildEnd(error) {
484
- if (error) {
485
- console.error("[vite-plugin-react-server] Build error:", error);
486
- return;
487
- }
488
- },
489
263
  handleHotUpdate({ file }) {
490
264
  if (file.endsWith(".css")) {
491
265
  cssModules.add(file);
492
266
  }
493
267
  },
494
- async generateBundle(options, bundle) {
268
+ async generateBundle(_options, bundle) {
495
269
  if (!resolvedConfig) {
496
270
  throw new Error("Resolved config not found");
497
271
  }
498
- outpuptBundle = bundle;
499
- outputOptions = options;
272
+
500
273
  // Create manifest entries for each chunk
501
274
  serverManifest = getBundleManifest({
502
275
  pluginContext: this,
@@ -0,0 +1 @@
1
+ export { reactStaticPlugin } from "./plugin.js";