vite-plugin-react-server 0.3.11 → 0.3.14

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 (221) hide show
  1. package/dist/package.json +15 -11
  2. package/dist/plugin/checkFilesExist.d.ts +2 -2
  3. package/dist/plugin/checkFilesExist.d.ts.map +1 -1
  4. package/dist/plugin/checkFilesExist.js +39 -57
  5. package/dist/plugin/checkFilesExist.js.map +1 -1
  6. package/dist/plugin/collect-css-manifest.d.ts +1 -1
  7. package/dist/plugin/collect-css-manifest.d.ts.map +1 -1
  8. package/dist/plugin/collect-css-manifest.js +8 -3
  9. package/dist/plugin/collect-css-manifest.js.map +1 -1
  10. package/dist/plugin/components.js +10 -15
  11. package/dist/plugin/config/createModuleIdGenerator.js +1 -1
  12. package/dist/plugin/config/createModuleIdGenerator.js.map +1 -1
  13. package/dist/plugin/config/defaults.d.ts +5 -14
  14. package/dist/plugin/config/defaults.d.ts.map +1 -1
  15. package/dist/plugin/config/defaults.js +12 -12
  16. package/dist/plugin/config/defaults.js.map +1 -1
  17. package/dist/plugin/config/getPaths.js +1 -1
  18. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  19. package/dist/plugin/config/resolveOptions.js +73 -52
  20. package/dist/plugin/config/resolveOptions.js.map +1 -1
  21. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  22. package/dist/plugin/config/resolveUserConfig.js +53 -65
  23. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  24. package/dist/plugin/helpers/getBundleManifest.d.ts +6 -1
  25. package/dist/plugin/helpers/getBundleManifest.d.ts.map +1 -1
  26. package/dist/plugin/helpers/getBundleManifest.js +48 -19
  27. package/dist/plugin/helpers/getBundleManifest.js.map +1 -1
  28. package/dist/plugin/helpers/inputNormalizer.d.ts +1 -2
  29. package/dist/plugin/helpers/inputNormalizer.d.ts.map +1 -1
  30. package/dist/plugin/helpers/inputNormalizer.js +52 -46
  31. package/dist/plugin/helpers/inputNormalizer.js.map +1 -1
  32. package/dist/plugin/helpers/tryManifest.d.ts +1 -1
  33. package/dist/plugin/helpers/tryManifest.d.ts.map +1 -1
  34. package/dist/plugin/helpers/tryManifest.js.map +1 -1
  35. package/dist/plugin/loader/createBuildLoader.d.ts +1 -1
  36. package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
  37. package/dist/plugin/loader/createBuildLoader.js +29 -26
  38. package/dist/plugin/loader/createBuildLoader.js.map +1 -1
  39. package/dist/plugin/loader/css-loader.d.ts +16 -0
  40. package/dist/plugin/loader/css-loader.d.ts.map +1 -0
  41. package/dist/plugin/loader/css-loader.js +70 -0
  42. package/dist/plugin/loader/css-loader.js.map +1 -0
  43. package/dist/plugin/loader/react-loader.d.ts +17 -0
  44. package/dist/plugin/loader/react-loader.d.ts.map +1 -0
  45. package/dist/plugin/loader/react-loader.js +647 -0
  46. package/dist/plugin/loader/react-loader.js.map +1 -0
  47. package/dist/plugin/loader/rsc/messageHandler.d.ts +2 -0
  48. package/dist/plugin/loader/rsc/messageHandler.d.ts.map +1 -0
  49. package/dist/plugin/loader/rsc/messageHandler.js +1 -0
  50. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts +2 -0
  51. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts.map +1 -0
  52. package/dist/plugin/loader/rsc/rsc-worker.development.js +1 -0
  53. package/dist/plugin/react-client/index.js +2 -2
  54. package/dist/plugin/react-client/index.js.map +1 -1
  55. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  56. package/dist/plugin/react-client/plugin.js +202 -25
  57. package/dist/plugin/react-client/plugin.js.map +1 -1
  58. package/dist/plugin/react-server/createHandler.d.ts.map +1 -1
  59. package/dist/plugin/react-server/createHandler.js +13 -7
  60. package/dist/plugin/react-server/createHandler.js.map +1 -1
  61. package/dist/plugin/react-server/createRscStream.d.ts +15 -3
  62. package/dist/plugin/react-server/createRscStream.d.ts.map +1 -1
  63. package/dist/plugin/react-server/createRscStream.js +52 -49
  64. package/dist/plugin/react-server/createRscStream.js.map +1 -1
  65. package/dist/plugin/react-server/plugin.d.ts.map +1 -1
  66. package/dist/plugin/react-server/plugin.js +76 -27
  67. package/dist/plugin/react-server/plugin.js.map +1 -1
  68. package/dist/plugin/transformer/plugin.d.ts.map +1 -1
  69. package/dist/plugin/transformer/plugin.js +65 -52
  70. package/dist/plugin/transformer/plugin.js.map +1 -1
  71. package/dist/plugin/types.d.ts +6 -1
  72. package/dist/plugin/types.d.ts.map +1 -1
  73. package/dist/plugin/utils/logger.d.ts +9 -0
  74. package/dist/plugin/utils/logger.d.ts.map +1 -0
  75. package/dist/plugin/utils/logger.js +68 -0
  76. package/dist/plugin/utils/logger.js.map +1 -0
  77. package/dist/plugin/worker/createWorker.d.ts +1 -0
  78. package/dist/plugin/worker/createWorker.d.ts.map +1 -1
  79. package/dist/plugin/worker/createWorker.js +23 -36
  80. package/dist/plugin/worker/createWorker.js.map +1 -1
  81. package/dist/plugin/worker/html/html-worker.production.js +5 -1
  82. package/dist/plugin/worker/html/html-worker.production.js.map +1 -1
  83. package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
  84. package/dist/plugin/worker/html/messageHandler.js +10 -19
  85. package/dist/plugin/worker/html/messageHandler.js.map +1 -1
  86. package/dist/plugin/worker/html/renderPages.d.ts +3 -3
  87. package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
  88. package/dist/plugin/worker/html/renderPages.js +148 -131
  89. package/dist/plugin/worker/html/renderPages.js.map +1 -1
  90. package/dist/plugin/worker/rsc/index.d.ts +1 -3
  91. package/dist/plugin/worker/rsc/index.d.ts.map +1 -1
  92. package/dist/plugin/worker/rsc/index.js +1 -9
  93. package/dist/plugin/worker/rsc/index.js.map +1 -1
  94. package/dist/plugin/worker/rsc/messageHandler.d.ts +3 -0
  95. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -0
  96. package/dist/plugin/worker/rsc/messageHandler.js +107 -0
  97. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -0
  98. package/dist/plugin/worker/rsc/plugin.d.ts.map +1 -1
  99. package/dist/plugin/worker/rsc/plugin.js +74 -80
  100. package/dist/plugin/worker/rsc/rsc-worker.development.d.ts +32 -0
  101. package/dist/plugin/worker/rsc/rsc-worker.development.d.ts.map +1 -0
  102. package/dist/plugin/worker/rsc/rsc-worker.development.js +43 -0
  103. package/dist/plugin/worker/rsc/rsc-worker.development.js.map +1 -0
  104. package/dist/plugin/worker/rsc/rsc-worker.js +4 -106
  105. package/dist/plugin/worker/rsc/rsc-worker.production.d.ts +2 -0
  106. package/dist/plugin/worker/rsc/rsc-worker.production.d.ts.map +1 -0
  107. package/dist/plugin/worker/rsc/rsc-worker.production.js +14 -0
  108. package/dist/plugin/worker/rsc/rsc-worker.production.js.map +1 -0
  109. package/dist/plugin/worker/rsc/state.d.ts +11 -0
  110. package/dist/plugin/worker/rsc/state.d.ts.map +1 -0
  111. package/dist/plugin/worker/rsc/state.js +12 -0
  112. package/dist/plugin/worker/rsc/state.js.map +1 -0
  113. package/dist/plugin/worker/types.d.ts +60 -46
  114. package/dist/plugin/worker/types.d.ts.map +1 -1
  115. package/dist/tsconfig.tsbuildinfo +1 -1
  116. package/package.json +15 -11
  117. package/plugin/checkFilesExist.ts +42 -62
  118. package/plugin/collect-css-manifest.ts +9 -4
  119. package/plugin/config/createModuleIdGenerator.ts +1 -1
  120. package/plugin/config/defaults.ts +13 -15
  121. package/plugin/config/resolveOptions.ts +134 -76
  122. package/plugin/config/resolveUserConfig.ts +75 -76
  123. package/plugin/helpers/getBundleManifest.ts +69 -31
  124. package/plugin/helpers/inputNormalizer.ts +82 -70
  125. package/plugin/helpers/tryManifest.ts +1 -1
  126. package/plugin/loader/createBuildLoader.ts +38 -41
  127. package/plugin/loader/css-loader.ts +96 -0
  128. package/plugin/loader/react-loader.ts +945 -0
  129. package/plugin/loader/rsc/messageHandler.tsx +1 -0
  130. package/plugin/loader/rsc/rsc-worker.development.ts +1 -0
  131. package/plugin/react-client/index.ts +1 -1
  132. package/plugin/react-client/plugin.ts +266 -41
  133. package/plugin/react-server/createHandler.ts +12 -8
  134. package/plugin/react-server/createRscStream.ts +75 -54
  135. package/plugin/react-server/plugin.ts +86 -35
  136. package/plugin/transformer/plugin.ts +67 -76
  137. package/plugin/types/global.d.ts +8 -0
  138. package/plugin/types.ts +3 -1
  139. package/plugin/utils/logger.ts +52 -0
  140. package/plugin/worker/createWorker.ts +43 -44
  141. package/plugin/worker/html/html-worker.production.tsx +7 -2
  142. package/plugin/worker/html/messageHandler.ts +13 -21
  143. package/plugin/worker/html/renderPages.ts +166 -181
  144. package/plugin/worker/rsc/index.ts +4 -13
  145. package/plugin/worker/rsc/messageHandler.tsx +143 -0
  146. package/plugin/worker/rsc/plugin.ts +38 -37
  147. package/plugin/worker/rsc/rsc-worker.development.ts +107 -0
  148. package/plugin/worker/rsc/rsc-worker.production.ts +13 -0
  149. package/plugin/worker/rsc/rsc-worker.tsx +5 -128
  150. package/plugin/worker/rsc/state.ts +37 -0
  151. package/plugin/worker/types.ts +79 -55
  152. package/scripts/check-react-version.mjs +17 -7
  153. package/scripts/react+0.0.0-experimental-b3a95caf-20250113.patch +143 -4170
  154. package/scripts/react-dom+0.0.0-experimental-b3a95caf-20250113.patch +14271 -90079
  155. package/dist/plugin/components.js.map +0 -1
  156. package/dist/plugin/helpers/createClientInputNormalizer.d.ts +0 -8
  157. package/dist/plugin/helpers/createClientInputNormalizer.d.ts.map +0 -1
  158. package/dist/plugin/helpers/createClientInputNormalizer.js +0 -35
  159. package/dist/plugin/helpers/createServerInputNormalizer.d.ts +0 -9
  160. package/dist/plugin/helpers/createServerInputNormalizer.d.ts.map +0 -1
  161. package/dist/plugin/helpers/createServerInputNormalizer.js +0 -37
  162. package/dist/plugin/helpers/createStaticInputNormalizer.d.ts +0 -7
  163. package/dist/plugin/helpers/createStaticInputNormalizer.d.ts.map +0 -1
  164. package/dist/plugin/helpers/createStaticInputNormalizer.js +0 -18
  165. package/dist/plugin/helpers/getModuleManifest.d.ts +0 -17
  166. package/dist/plugin/helpers/getModuleManifest.d.ts.map +0 -1
  167. package/dist/plugin/helpers/getModuleManifest.js +0 -23
  168. package/dist/plugin/helpers/inputNormalizerWorker.d.ts +0 -12
  169. package/dist/plugin/helpers/inputNormalizerWorker.d.ts.map +0 -1
  170. package/dist/plugin/helpers/inputNormalizerWorker.js +0 -33
  171. package/dist/plugin/helpers/normalizedRelativePath.d.ts +0 -11
  172. package/dist/plugin/helpers/normalizedRelativePath.d.ts.map +0 -1
  173. package/dist/plugin/helpers/normalizedRelativePath.js +0 -36
  174. package/dist/plugin/helpers/resolveFilePath.d.ts +0 -13
  175. package/dist/plugin/helpers/resolveFilePath.d.ts.map +0 -1
  176. package/dist/plugin/helpers/resolveFilePath.js +0 -74
  177. package/dist/plugin/helpers/resolveWorkerModule.d.ts +0 -6
  178. package/dist/plugin/helpers/resolveWorkerModule.d.ts.map +0 -1
  179. package/dist/plugin/helpers/resolveWorkerModule.js +0 -24
  180. package/dist/plugin/helpers/validateModuleBase.d.ts +0 -3
  181. package/dist/plugin/helpers/validateModuleBase.d.ts.map +0 -1
  182. package/dist/plugin/helpers/validateModuleBase.js +0 -16
  183. package/dist/plugin/helpers/validateResolvedConfig.d.ts +0 -3
  184. package/dist/plugin/helpers/validateResolvedConfig.d.ts.map +0 -1
  185. package/dist/plugin/helpers/validateResolvedConfig.js +0 -17
  186. package/dist/plugin/transformer/transformer-client-components.d.ts +0 -30
  187. package/dist/plugin/transformer/transformer-client-components.d.ts.map +0 -1
  188. package/dist/plugin/transformer/transformer-client-components.js +0 -122
  189. package/dist/plugin/transformer/transformer-client-components.js.map +0 -1
  190. package/dist/plugin/transformer/transformer-server-actions.d.ts +0 -29
  191. package/dist/plugin/transformer/transformer-server-actions.d.ts.map +0 -1
  192. package/dist/plugin/transformer/transformer-server-actions.js +0 -90
  193. package/dist/plugin/worker/rsc/createRscStream.d.ts +0 -5
  194. package/dist/plugin/worker/rsc/createRscStream.d.ts.map +0 -1
  195. package/dist/plugin/worker/rsc/createRscStream.js +0 -39
  196. package/dist/plugin/worker/rsc/createRscStream.js.map +0 -1
  197. package/dist/plugin/worker/rsc/development.d.ts +0 -5
  198. package/dist/plugin/worker/rsc/development.d.ts.map +0 -1
  199. package/dist/plugin/worker/rsc/development.js +0 -13
  200. package/dist/plugin/worker/rsc/development.js.map +0 -1
  201. package/dist/plugin/worker/rsc/plugin.js.map +0 -1
  202. package/dist/plugin/worker/rsc/production.d.ts +0 -5
  203. package/dist/plugin/worker/rsc/production.d.ts.map +0 -1
  204. package/dist/plugin/worker/rsc/production.js +0 -13
  205. package/dist/plugin/worker/rsc/production.js.map +0 -1
  206. package/plugin/helpers/createClientInputNormalizer.ts +0 -48
  207. package/plugin/helpers/createServerInputNormalizer.ts +0 -52
  208. package/plugin/helpers/createStaticInputNormalizer.ts +0 -26
  209. package/plugin/helpers/getModuleManifest.ts +0 -36
  210. package/plugin/helpers/inputNormalizerWorker.ts +0 -52
  211. package/plugin/helpers/normalizedRelativePath.ts +0 -59
  212. package/plugin/helpers/resolveFilePath.ts +0 -108
  213. package/plugin/helpers/resolveWorkerModule.ts +0 -41
  214. package/plugin/helpers/validateModuleBase.ts +0 -30
  215. package/plugin/helpers/validateResolvedConfig.ts +0 -21
  216. package/plugin/transformer/transformer-client-components.ts +0 -168
  217. package/plugin/transformer/transformer-server-actions.ts +0 -125
  218. package/plugin/worker/rsc/createRscStream.ts +0 -42
  219. package/plugin/worker/rsc/development.ts +0 -6
  220. package/plugin/worker/rsc/production.ts +0 -6
  221. package/scripts/react-server-dom-esm+0.0.1.patch +0 -24775
@@ -29,9 +29,10 @@ import { type StreamPluginOptions } from "../types.js";
29
29
  import { createWorker } from "../worker/createWorker.js";
30
30
  import { renderPages } from "../worker/html/renderPages.js";
31
31
  import { createHandler } from "./createHandler.js";
32
- import { mkdir, writeFile } from "node:fs/promises";
32
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
33
33
  import { getBundleManifest } from "../helpers/getBundleManifest.js";
34
34
  import type { ServerResponse } from "node:http";
35
+ import { collectManifestCss } from "../collect-css-manifest.js";
35
36
 
36
37
  let resolvedConfig: ResolvedConfig | null = null;
37
38
  let serverManifestPath: string | null = null;
@@ -39,6 +40,7 @@ let clientManifestPath: string | null = null;
39
40
  let outpuptBundle: any;
40
41
  let outputOptions: any;
41
42
  let loader: ((id: string) => Promise<Record<string, any>>) | null = null;
43
+ let worker: Worker;
42
44
  export function reactServerPlugin(
43
45
  options: StreamPluginOptions
44
46
  ): import("vite").Plugin<{
@@ -51,7 +53,6 @@ export function reactServerPlugin(
51
53
 
52
54
  let files: CheckFilesExistReturn;
53
55
  // let env: Awaited<ReturnType<typeof getEnv>>;
54
- let worker: Worker;
55
56
  let cssModules = new Set<string>();
56
57
  let clientComponents = new Map<string, string>();
57
58
  // let define: Record<string, string>;
@@ -145,9 +146,7 @@ export function reactServerPlugin(
145
146
  );
146
147
  }
147
148
  },
148
- async configurePreviewServer(server) {
149
-
150
- },
149
+ async configurePreviewServer(server) {},
151
150
  async configureServer(server: ViteDevServer) {
152
151
  if (typeof loader !== "function") {
153
152
  loader = server.ssrLoadModule;
@@ -209,7 +208,7 @@ export function reactServerPlugin(
209
208
  projectRoot: root,
210
209
  },
211
210
  {
212
- cssFiles: Array.from(cssModules),
211
+ cssFiles: [],
213
212
  logger: createLogger(),
214
213
  loader,
215
214
  moduleGraph: server.moduleGraph,
@@ -260,7 +259,6 @@ export function reactServerPlugin(
260
259
  }
261
260
 
262
261
  userConfig = resolvedConfig.userConfig;
263
-
264
262
  return resolvedConfig.userConfig;
265
263
  },
266
264
  async buildStart() {
@@ -305,18 +303,35 @@ export function reactServerPlugin(
305
303
  nodeOptions: "--conditions=react-client",
306
304
  });
307
305
 
308
- // Use both manifests directly
306
+ // Create the loader
309
307
  if (typeof loader !== "function") {
310
308
  if (!Object.keys(serverManifest).length) {
311
- serverManifest = getBundleManifest(this, outpuptBundle, undefined);
309
+ console.warn(
310
+ "[vite-plugin-react-server] No server manifest found, the plugin will try to use the plugin context - it may differ from vite's manifest."
311
+ );
312
+ serverManifest = getBundleManifest({
313
+ pluginContext: this,
314
+ bundle: outpuptBundle,
315
+ moduleBase: userOptions.moduleBase,
316
+ preserveModulesRoot: userOptions.build.preserveModulesRoot,
317
+ });
312
318
  if (!Object.keys(serverManifest).length) {
319
+ console.warn(
320
+ "[vite-plugin-react-server] That didn't work, retrying to read manifest."
321
+ );
313
322
  const resolvedServerManifest = tryManifest({
314
323
  root: root,
315
- outDir: join(userOptions.build.outDir, userOptions.build.server),
324
+ outDir: join(
325
+ userOptions.build.outDir,
326
+ userOptions.build.server
327
+ ),
316
328
  ssrManifest: false,
317
329
  });
318
330
  if (resolvedServerManifest.type === "error") {
319
331
  // dont build the static files without a server manifest
332
+ console.error(
333
+ "[vite-plugin-react-server] Failed to read manifest, aborting build."
334
+ );
320
335
  return;
321
336
  }
322
337
  serverManifest = resolvedServerManifest.manifest;
@@ -335,30 +350,73 @@ export function reactServerPlugin(
335
350
  if (resolvedPages.type === "error") {
336
351
  throw resolvedPages.error;
337
352
  }
353
+
354
+ const onCssFile = async (path: string, parentUrl: string) => {
355
+ if (buildCssFiles && path.endsWith(".css")) {
356
+ buildCssFiles.add(path);
357
+ if (parentUrl.endsWith(userOptions.build.client)) {
358
+ // copy the file to the client build dir
359
+ const serverPath = join(
360
+ userOptions.build.outDir,
361
+ userOptions.build.server,
362
+ path
363
+ );
364
+ await writeFile(
365
+ serverPath,
366
+ await readFile(
367
+ join(
368
+ root,
369
+ userOptions.build.outDir,
370
+ userOptions.build.client,
371
+ path
372
+ )
373
+ )
374
+ );
375
+ } else {
376
+ // copy the file to the client build dir, assume it's in server build dir
377
+ const clientPath = join(
378
+ userOptions.build.outDir,
379
+ userOptions.build.client,
380
+ path
381
+ );
382
+ await mkdir(dirname(clientPath), { recursive: true });
383
+ await writeFile(
384
+ clientPath,
385
+ await readFile(
386
+ join(
387
+ root,
388
+ userOptions.build.outDir,
389
+ userOptions.build.server,
390
+ path
391
+ )
392
+ )
393
+ );
394
+ }
395
+ }
396
+ };
397
+
338
398
  const { failedRoutes, completedRoutes } = await renderPages(
339
399
  this,
340
400
  resolvedPages.pages,
401
+ files,
341
402
  {
342
- pipableStreamOptions: {},
403
+ pipableStreamOptions: {
404
+ bootstrapModules: clientManifest["index.html"]?.file
405
+ ? [clientManifest["index.html"].file]
406
+ : [],
407
+ },
343
408
  moduleBasePath: "",
344
409
  moduleBaseURL: "",
345
- clientCss:
346
- Object.values(clientManifest)
347
- .flatMap((entry) => entry.css)
348
- .filter((css) => typeof css === "string")
349
- .map((css) => "/" + css) ?? [],
410
+ clientCss: clientManifest["index.html"]?.css
411
+ ? clientManifest["index.html"].css
412
+ : [],
350
413
  userConfig,
351
414
  pluginOptions: userOptions,
352
415
  worker: worker,
353
416
  clientManifest: clientManifest,
354
417
  serverManifest: serverManifest,
355
418
  loader,
356
- onCssFile: (path: string) => {
357
- console.log("[vite-plugin-react-server] onCssFile", path);
358
- if (buildCssFiles && path.endsWith(".css")) {
359
- buildCssFiles.add(path);
360
- }
361
- },
419
+ onCssFile: onCssFile,
362
420
  }
363
421
  );
364
422
 
@@ -421,7 +479,6 @@ export function reactServerPlugin(
421
479
 
422
480
  // Ensure worker is terminated
423
481
  if (worker) {
424
- console.log("[vite-plugin-react-server] Terminating worker...");
425
482
  await worker.terminate();
426
483
  worker = null as any;
427
484
  }
@@ -451,8 +508,12 @@ export function reactServerPlugin(
451
508
  outpuptBundle = bundle;
452
509
  outputOptions = options;
453
510
  // Create manifest entries for each chunk
454
- serverManifest = getBundleManifest(this, bundle, undefined);
455
- console.log("[vite:plugin-react-server] Server manifest", serverManifest);
511
+ serverManifest = getBundleManifest({
512
+ pluginContext: this,
513
+ bundle,
514
+ moduleBase: userOptions.moduleBase,
515
+ preserveModulesRoot: userOptions.build.preserveModulesRoot,
516
+ });
456
517
  if (serverManifestPath) {
457
518
  await mkdir(dirname(serverManifestPath), { recursive: true });
458
519
  await writeFile(
@@ -461,15 +522,5 @@ export function reactServerPlugin(
461
522
  );
462
523
  }
463
524
  },
464
- async renderChunk(code: string, chunk, options) {
465
- if (chunk.fileName.includes("html-worker")) {
466
- const workerPath = resolve(root, chunk.fileName);
467
- worker = await createWorker({
468
- projectRoot: userOptions.projectRoot,
469
- workerPath,
470
- });
471
- }
472
- return null;
473
- },
474
525
  };
475
526
  }
@@ -1,20 +1,11 @@
1
1
  import { resolveOptions } from "../config/resolveOptions.js";
2
- import type {
3
- ResolvedUserConfig,
4
- ResolvedUserOptions,
5
- StreamPluginOptions,
6
- } from "../types.js";
7
- import { createClientComponentTransformer } from "./transformer-client-components.js";
8
- import { createModuleIdGenerator } from "../config/createModuleIdGenerator.js";
9
- import { type ConfigEnv, type Plugin, type ResolvedConfig } from "vite";
2
+ import type { StreamPluginOptions } from "../types.js";
3
+ import { type Plugin } from "vite";
4
+ import { transformModuleIfNeeded } from "../loader/react-loader.js";
5
+ import { DEFAULT_CONFIG } from "../config/defaults.js";
10
6
  import { createInputNormalizer } from "../helpers/inputNormalizer.js";
11
- import { resolveUserConfig } from "../config/resolveUserConfig.js";
12
-
13
- let userOptions: ResolvedUserOptions;
14
- let userConfig: ResolvedUserConfig;
15
- let resolvedConfig: ResolvedConfig;
16
- let resolvedConfigEnv: ConfigEnv;
17
-
7
+ import { tryManifest } from "../helpers/tryManifest.js";
8
+ import { join } from "node:path";
18
9
  /**
19
10
  * Plugin for transforming React Client Components.
20
11
  *
@@ -41,76 +32,76 @@ let resolvedConfigEnv: ConfigEnv;
41
32
  */
42
33
 
43
34
  export function reactTransformPlugin(options: StreamPluginOptions): Plugin {
44
- const resolvedUserOptions = resolveOptions(options);
45
- if (resolvedUserOptions.type === "error") {
46
- throw resolvedUserOptions.error;
47
- }
48
- userOptions = resolvedUserOptions.userOptions;
35
+ const resolvedOptions = resolveOptions(options);
36
+ let isDev = false;
37
+ if (resolvedOptions.type === "error") throw resolvedOptions.error;
38
+ const normalizer = createInputNormalizer({
39
+ root: resolvedOptions.userOptions.projectRoot,
40
+ preserveModulesRoot: undefined,
41
+ removeExtension: false,
42
+ });
49
43
 
50
- let manifest: Record<string, { file: string }> = {};
51
- const pendingEmits = new Map<string, { referenceId: string }>();
44
+ // Get the client manifest
45
+ const clientManifestResult = tryManifest({
46
+ root: resolvedOptions.userOptions.projectRoot,
47
+ outDir: join(
48
+ resolvedOptions.userOptions.build.outDir,
49
+ resolvedOptions.userOptions.build.client
50
+ ),
51
+ ssrManifest: false,
52
+ });
52
53
 
53
54
  return {
54
55
  name: "vite:react-transform",
55
- enforce: "post",
56
-
56
+ enforce: "pre", // Run before Vite's transforms
57
57
  config(config, configEnv) {
58
- const resolvedUserConfig = resolveUserConfig({
59
- isClient: false,
60
- config,
61
- configEnv,
62
- userOptions,
63
- });
64
- if (resolvedUserConfig.type === "error") {
65
- throw resolvedUserConfig.error;
66
- }
67
- userConfig = resolvedUserConfig.userConfig;
68
- resolvedConfigEnv = configEnv;
58
+ isDev = configEnv.mode === "development" && configEnv.command === "serve";
69
59
  },
70
- configResolved(config) {
71
- resolvedConfig = config;
72
- },
73
-
74
- transform(code: string, id: string, opt: { ssr?: boolean } = {}) {
75
- const hasClientDirective = code.match(/^["']use client["'];?/);
76
- if (!hasClientDirective) return null;
77
-
78
- const moduleInfo = this.getModuleInfo(id);
79
- if (!moduleInfo) return null;
80
-
81
- // In dev mode, just transform the code without emitting
82
- if (resolvedConfigEnv.command === 'serve') {
83
- const transformer = createClientComponentTransformer(userOptions, userConfig, resolvedConfigEnv);
84
- return transformer.transform!.bind(this)(code, id, opt);
60
+ async transform(code, id, options) {
61
+ const ssr = options?.ssr ?? false;
62
+ if (!ssr) return null;
63
+ if (!id.match(DEFAULT_CONFIG.FILE_REGEX)) return null;
64
+ if (!code.match('"use client"'))
65
+ return null;
66
+ const [key, value] = normalizer(id);
67
+ const transformed = await transformModuleIfNeeded(
68
+ code,
69
+ id,
70
+ // Pass null for nextLoad since we don't need module loading in the plugin
71
+ null
72
+ );
73
+ if (!transformed) return null;
74
+ if (isDev) {
75
+ return {
76
+ code: transformed,
77
+ map: null,
78
+ };
85
79
  }
80
+ const moduleIdIndex = transformed.indexOf(value);
81
+ if (moduleIdIndex === -1) {
82
+ console.warn(
83
+ `[vite-plugin-react-server] Could not find module id in transformed code. Ignoring.`,
84
+ {
85
+ code,
86
+ id,
87
+ transformed,
88
+ }
89
+ );
90
+ return null
91
+ }
92
+ if (clientManifestResult.type === "error") {
93
+ throw clientManifestResult.error;
94
+ }
95
+ const clientPath = clientManifestResult.manifest[key]?.file;
86
96
 
87
- // Production build logic...
88
- const normalizer = createInputNormalizer({
89
- root: resolvedConfig.root,
90
- preserveModulesRoot: undefined,
91
- });
92
- const [normalizedId, normalizedPath] = normalizer(id);
93
-
94
- // Add to manifest immediately with a temporary path
95
- manifest[normalizedId] = { file: normalizedPath };
96
-
97
- const referenceId = this.emitFile({
98
- type: "chunk",
99
- id: normalizedPath,
100
- name: normalizedId,
101
- });
102
- pendingEmits.set(normalizedId, { referenceId });
103
-
104
- const transformer = createClientComponentTransformer(userOptions, userConfig, resolvedConfigEnv);
105
- return transformer.transform!.bind(this)(code, id, opt);
106
- },
107
-
108
- renderDynamicImport() {
109
- // Update manifest with real file names
110
- for (const [normalizedId, { referenceId }] of pendingEmits) {
111
- const fileName = this.getFileName(referenceId);
112
- manifest[normalizedId] = { file: fileName };
97
+ if (!clientPath) {
98
+ console.warn(`[vite-plugin-react-server] Could not find client path for ${value}. Ignoring.`)
99
+ return null
113
100
  }
101
+ return {
102
+ code: transformed.replace(key, clientPath),
103
+ map: null,
104
+ };
114
105
  },
115
106
  };
116
107
  }
@@ -0,0 +1,8 @@
1
+ import type { EventEmitter } from 'node:events';
2
+
3
+ declare global {
4
+ var __RSC_CSS_FILES__: Set<string>;
5
+ var __RSC_CSS_EVENTS__: EventEmitter;
6
+ }
7
+
8
+ export {};
package/plugin/types.ts CHANGED
@@ -181,7 +181,7 @@ export interface CreateHandlerOptions<T = any> {
181
181
  serverManifest?: import("vite").Manifest;
182
182
  moduleGraph?: import("vite").ModuleGraph;
183
183
  cssFiles?: string[];
184
- onCssFile?: (path: string) => void;
184
+ onCssFile?: (path: string, parentUrl: string) => void;
185
185
  logger?: import("vite").Logger;
186
186
  pipableStreamOptions?: PipeableStreamOptions;
187
187
  }
@@ -337,6 +337,8 @@ export type CheckFilesExistReturn = {
337
337
  propsSet: Set<string>;
338
338
  pageMap: Map<string, string>;
339
339
  pageSet: Set<string>;
340
+ urlMap: Map<string, {props: string, page: string}>;
341
+ errors: string[];
340
342
  };
341
343
 
342
344
  // Add strict type checking for worker messages
@@ -0,0 +1,52 @@
1
+ import { createLogger as createViteLogger, type LogLevel } from 'vite';
2
+
3
+
4
+ const isPrimitive = (value: any) => {
5
+ return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'symbol';
6
+ }
7
+
8
+ const buildMessage = (prefix: string, msg: string, ...args: any[]) => {
9
+ let buildMsg = `[${prefix}] ${msg}`
10
+ for(const arg of args) {
11
+ if(isPrimitive(arg)) {
12
+ buildMsg += `\n[${prefix}] ${String(arg)}`;
13
+ } else if(arg instanceof Error) {
14
+ buildMsg += `\n[${prefix}] ${arg.name}`
15
+ buildMsg += `\n[${prefix}] ${arg.message}`
16
+ buildMsg += `\n[${prefix}] ${arg.stack}`
17
+ buildMsg += `\n[${prefix}] ${arg.cause}`
18
+ } else {
19
+ buildMsg += `\n[${prefix}] ${JSON.stringify(arg)}`;
20
+ }
21
+ }
22
+ return buildMsg;
23
+ }
24
+
25
+ export const createLogger = (process.env['NODE_ENV'] === 'development') ? (prefix: string, logLevel: LogLevel = 'info') => {
26
+ const logger = createViteLogger(logLevel, {
27
+ allowClearScreen: true
28
+ });
29
+ return {
30
+ clear: () => logger.clearScreen('info'),
31
+ info: (msg: string, ...args: any[]) => {
32
+ console.log(buildMessage(prefix, msg, ...args))
33
+ },
34
+ warn: (msg: string, ...args: any[]) => {
35
+ console.warn(buildMessage(prefix, msg, ...args))
36
+ },
37
+ error: (msg: string, ...args: any[]) => {
38
+ console.error(buildMessage(prefix, msg, ...args))
39
+ },
40
+ debug: (msg: string, ...args: any[]) => {
41
+ console.debug(buildMessage(prefix, msg, ...args))
42
+ }
43
+ };
44
+ } : () => {
45
+ return {
46
+ clear: () => {},
47
+ info: () => {},
48
+ warn: () => {},
49
+ error: () => {},
50
+ debug: () => {},
51
+ };
52
+ };
@@ -12,6 +12,7 @@ type CreateWorkerOptions = {
12
12
  maxListeners?: number;
13
13
  workerPath: string;
14
14
  resourceLimits?: ResourceLimits;
15
+ typescript?: boolean;
15
16
  };
16
17
 
17
18
  export async function createWorker(options: CreateWorkerOptions) {
@@ -26,59 +27,57 @@ export async function createWorker(options: CreateWorkerOptions) {
26
27
  resourceLimits = {
27
28
  maxOldGenerationSizeMb: 512,
28
29
  maxYoungGenerationSizeMb: 128,
29
- }
30
+ },
30
31
  } = options;
31
32
 
32
33
  // Ensure consistent NODE_ENV between main thread and worker
33
- const isTestEnv = process.env['VITEST'] || process.env['NODE_ENV'] === 'test';
34
- const nodeEnv = isTestEnv ? 'development' : mode;
34
+ const isTestEnv = process.env["VITEST"] || process.env["NODE_ENV"] === "test";
35
+ const nodeEnv = isTestEnv ? "development" : mode;
35
36
 
36
37
  const env = {
37
38
  ...process.env,
38
39
  NODE_ENV: nodeEnv,
39
40
  NODE_PATH: nodePath,
40
- // Clear any inherited conditions for worker
41
- NODE_OPTIONS: reverseCondition ?
42
- (condition === 'react-server' ? '--conditions=react-client' : '--conditions=react-server')
43
- : process.env['NODE_OPTIONS']
41
+ NODE_OPTIONS: `${
42
+ reverseCondition
43
+ ? condition === "react-server"
44
+ ? process.env["NODE_OPTIONS"]?.includes("react-server")
45
+ ? process.env["NODE_OPTIONS"]?.replace("react-server", "react-client")
46
+ : `${process.env["NODE_OPTIONS"] ?? ''} --conditions=react-client`
47
+ : process.env["NODE_OPTIONS"]?.includes("react-client")
48
+ ? process.env["NODE_OPTIONS"]?.replace("react-client", "react-server")
49
+ : `${process.env["NODE_OPTIONS"] ?? ''} --conditions=react-server`
50
+ : process.env["NODE_OPTIONS"]
51
+ }`,
44
52
  };
45
- const maxRetries = 3;
46
- for (let tries = 0; tries < maxRetries; tries++) {
47
- try {
48
- const worker = new Worker(workerPath.startsWith('/') ? workerPath : join(projectRoot, workerPath), {
49
- env,
50
- // Increase resource limits for stream handling
51
- resourceLimits: resourceLimits
52
- });
53
-
54
- worker.setMaxListeners(maxListeners);
55
53
 
56
- // Wait for worker to be ready and verify environment
57
- const ready = await Promise.race([
58
- new Promise((_, reject) => {
59
- setTimeout(() => reject(new Error(`Worker startup timeout: ${workerPath}`)), 5000);
60
- }),
61
- new Promise((resolve, reject) => {
62
- worker.once('message', (msg) => {
63
- if (msg.type === 'READY') {
64
- if(msg.env === nodeEnv) {
65
- resolve(true);
66
- } else {
67
- reject(new Error(`Worker environment mismatch: expected ${nodeEnv}, got ${msg.env}`));
68
- }
69
- } else if (msg.type === 'ERROR') {
70
- reject(new Error(msg.error));
71
- }
72
- });
73
- worker.once('error', reject);
74
- })
75
- ]);
76
-
77
- if (ready) return worker;
78
- } catch (error) {
79
- console.warn(`Worker startup attempt ${tries + 1} failed:`, error);
80
- if (tries === maxRetries - 1) throw error;
54
+ // Create worker with proper environment
55
+ const worker = new Worker(
56
+ workerPath.startsWith("/") ? workerPath : join(projectRoot, workerPath),
57
+ {
58
+ env,
59
+ resourceLimits,
81
60
  }
82
- }
83
- throw new Error('Failed to start worker after retries');
61
+ );
62
+
63
+ worker.setMaxListeners(maxListeners);
64
+
65
+ // Wait for worker to be ready
66
+ return await new Promise<Worker>((resolve, reject) => {
67
+ const timeout = setTimeout(() => {
68
+ reject(new Error('Worker ready timeout'));
69
+ }, 5000);
70
+
71
+ worker.once("message", (msg) => {
72
+ if (msg.type === "READY" && msg.env === nodeEnv) {
73
+ clearTimeout(timeout);
74
+ resolve(worker);
75
+ }
76
+ });
77
+
78
+ worker.once("error", (error) => {
79
+ clearTimeout(timeout);
80
+ reject(error);
81
+ });
82
+ });
84
83
  }
@@ -1,8 +1,13 @@
1
1
  import { messageHandler } from "./messageHandler.js";
2
2
  import { parentPort } from "node:worker_threads";
3
3
 
4
+ let ready = false;
4
5
  if (!parentPort) throw new Error("This module must be run as a worker");
5
- parentPort?.on("message", messageHandler);
6
6
 
7
7
  // Signal ready with environment
8
- parentPort?.postMessage({ type: "READY", env: process.env["NODE_ENV"] });
8
+ parentPort?.on("message", messageHandler);
9
+ parentPort?.postMessage({
10
+ type: "READY",
11
+ env: process.env["NODE_ENV"],
12
+ pid: process.pid
13
+ });
@@ -8,30 +8,19 @@ import {
8
8
  // @ts-ignore
9
9
  } from "react-server-dom-esm/client.node";
10
10
  import { join } from "path";
11
- import { readFileSync } from "node:fs";
12
- import { existsSync } from "node:fs";
13
11
 
14
12
  // Track active renders and streams
15
13
  const activeRenders = new Map<string, HtmlRenderState>();
16
14
  const htmlContent = new Map<string, string>();
17
15
  const htmlPromises = new Map<string, Promise<string>>();
18
16
 
17
+
19
18
  export const messageHandler = async (message: HtmlWorkerMessage) => {
20
19
  try {
21
20
  switch (message.type) {
22
21
  case "RSC_CHUNK": {
23
- const {
24
- id,
25
- chunk,
26
- moduleRootPath,
27
- moduleBaseURL,
28
- outDir,
29
- pipableStreamOptions,
30
- clientManifest = {},
31
- serverManifest = {},
32
- htmlOutputPath,
33
- } = message;
34
-
22
+ const { id, chunk, moduleRootPath, moduleBaseURL, htmlOutputPath, pipableStreamOptions } = message;
23
+
35
24
  const render = activeRenders.get(id);
36
25
  if (!render) {
37
26
  activeRenders.set(id, {
@@ -41,8 +30,8 @@ export const messageHandler = async (message: HtmlWorkerMessage) => {
41
30
  rendered: false,
42
31
  moduleRootPath,
43
32
  moduleBaseURL,
44
- outDir,
45
- htmlOutputPath: htmlOutputPath ?? join(outDir, 'index.html'),
33
+ outDir: '',
34
+ htmlOutputPath: htmlOutputPath ?? join(process.cwd(), 'index.html'),
46
35
  pipableStreamOptions: pipableStreamOptions,
47
36
  });
48
37
  } else {
@@ -120,12 +109,15 @@ export const messageHandler = async (message: HtmlWorkerMessage) => {
120
109
  htmlPromises.delete(id);
121
110
  break;
122
111
  }
112
+
113
+ case "SHUTDOWN": {
114
+ console.log('Received shutdown signal');
115
+ parentPort?.close();
116
+ break;
117
+ }
123
118
  }
124
119
  } catch (error) {
125
- parentPort?.postMessage({
126
- type: "ERROR",
127
- id: message.type === "RSC_CHUNK" || message.type === "RSC_END" ? message.id : "",
128
- error: error instanceof Error ? error.message : String(error),
129
- });
120
+ console.error('Error in messageHandler:', error);
121
+ throw error;
130
122
  }
131
123
  };