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
@@ -11,6 +11,7 @@ import { globSync } from "fs";
11
11
  import type { OutputOptions } from "rollup";
12
12
  export type ResolveUserConfigProps = {
13
13
  isClient?: boolean;
14
+ isStatic?: boolean;
14
15
  config: UserConfig;
15
16
  configEnv: ConfigEnv;
16
17
  userOptions: ResolvedUserOptions;
@@ -23,6 +24,7 @@ export type ResolveUserConfigReturn =
23
24
 
24
25
  export function resolveUserConfig({
25
26
  isClient = false,
27
+ isStatic = false,
26
28
  config,
27
29
  configEnv,
28
30
  userOptions,
@@ -110,7 +112,7 @@ export function resolveUserConfig({
110
112
  ? autoDiscoveredClientFiles(clientEntry)
111
113
  : autoDiscoveredServerFiles(autoDiscoveredFiles(serverEntry ?? {}));
112
114
 
113
- const envDir = isClient
115
+ const envDir = isStatic ? userOptions.build.static : isClient
114
116
  ? userOptions.build.client
115
117
  : userOptions.build.server;
116
118
 
@@ -132,7 +134,7 @@ export function resolveUserConfig({
132
134
  interop: "auto",
133
135
  } satisfies OutputOptions;
134
136
 
135
- const newOutput = Array.isArray(config.build?.rollupOptions?.output)
137
+ let newOutput = Array.isArray(config.build?.rollupOptions?.output)
136
138
  ? [...config.build?.rollupOptions?.output, pluginOutput]
137
139
  : typeof config.build?.rollupOptions?.output === "object" &&
138
140
  config.build?.rollupOptions?.output !== null
@@ -140,7 +142,7 @@ export function resolveUserConfig({
140
142
  : pluginOutput;
141
143
 
142
144
  if (isClient) {
143
- // client build options
145
+ // client plugin build options (client plugin still outputs server files)
144
146
  return {
145
147
  type: "success",
146
148
  userConfig: {
@@ -168,13 +170,11 @@ export function resolveUserConfig({
168
170
  emptyOutDir: config.build?.emptyOutDir ?? true,
169
171
  outDir: join(userOptions.build.outDir, envDir),
170
172
  assetsDir: config.build?.assetsDir ?? userOptions.build.assetsDir,
173
+ copyPublicDir: config.build?.copyPublicDir ?? true,
171
174
  // modern browsers
172
175
  target: ["esnext"],
173
176
  minify: true,
174
- ssr:
175
- typeof configEnv.isSsrBuild === "boolean"
176
- ? configEnv.isSsrBuild
177
- : true,
177
+ ssr: typeof config.build?.ssr === "boolean" ? config.build?.ssr : configEnv.isSsrBuild ?? false,
178
178
  manifest: config.build?.manifest ?? `.vite/manifest.json`,
179
179
  ssrManifest: config.build?.ssrManifest ?? `.vite/ssr-manifest.json`,
180
180
  ssrEmitAssets: config.build?.ssrEmitAssets ?? true,
@@ -189,6 +189,9 @@ export function resolveUserConfig({
189
189
  };
190
190
  }
191
191
  // server build options
192
+ if(configEnv.isSsrBuild === false) {
193
+ configEnv.isSsrBuild = true
194
+ }
192
195
  return {
193
196
  type: "success",
194
197
  userConfig: {
@@ -196,7 +199,6 @@ export function resolveUserConfig({
196
199
  root: root,
197
200
  mode: configEnv.mode ?? configEnv.command === "build" ? "production" : "development",
198
201
  resolve: {
199
- alias: {},
200
202
  externalConditions: ["react-server"],
201
203
  },
202
204
  // server build options
@@ -206,10 +208,11 @@ export function resolveUserConfig({
206
208
  outDir: join(userOptions.build.outDir, envDir),
207
209
  target: config.build?.target ?? "node18",
208
210
  minify: config.build?.minify ?? true,
209
- ssr: config.build?.ssr ?? configEnv.isSsrBuild ?? true,
211
+ ssr: typeof config.build?.ssr === "boolean" ? config.build?.ssr : configEnv.isSsrBuild ?? true,
210
212
  manifest: config.build?.manifest ?? `.vite/manifest.json`,
211
213
  ssrManifest: config.build?.ssrManifest ?? `.vite/ssr-manifest.json`,
212
214
  ssrEmitAssets: config.build?.ssrEmitAssets ?? true,
215
+ copyPublicDir: config.build?.copyPublicDir ?? isStatic,
213
216
  assetsDir: config.build?.assetsDir ?? userOptions.build.assetsDir,
214
217
  rollupOptions: {
215
218
  ...config.build?.rollupOptions,
@@ -1,13 +1,13 @@
1
1
  import type { PipeableStream } from "react-dom/server";
2
2
  import { createLogger } from "vite";
3
3
  import {
4
- collectManifestCss,
4
+ collectManifestClientFiles,
5
5
  collectModuleGraphCss,
6
- } from "../collect-css-manifest.js";
6
+ } from "../collect-manifest-client-files.js";
7
7
  import { DEFAULT_CONFIG } from "../config/defaults.js";
8
8
  import { resolvePage } from "../resolvePage.js";
9
9
  import { resolveProps } from "../resolveProps.js";
10
- import type { CreateHandlerOptions, ResolvedUserOptions } from "../types.js";
10
+ import type { CheckFilesExistReturn, CreateHandlerOptions, ResolvedUserOptions } from "../types.js";
11
11
  import { createRscStream } from "./createRscStream.js";
12
12
 
13
13
  type CreateHandlerResult =
@@ -16,15 +16,21 @@ type CreateHandlerResult =
16
16
  | { type: "skip" };
17
17
 
18
18
  interface HandlerAssets {
19
- css: Set<string>;
20
- clientPath: string;
19
+ css: string[];
20
+ bootstrapModules: string[];
21
21
  }
22
22
 
23
- export async function createHandler<T>(
23
+ export async function createHandler<T>({
24
+ url,
25
+ urlMap,
26
+ pluginOptions,
27
+ streamOptions,
28
+ }: {
24
29
  url: string,
30
+ urlMap: CheckFilesExistReturn['urlMap'],
25
31
  pluginOptions: ResolvedUserOptions,
26
32
  streamOptions: CreateHandlerOptions<T>
27
- ): Promise<CreateHandlerResult> {
33
+ }): Promise<CreateHandlerResult> {
28
34
  const root = pluginOptions.projectRoot ?? process.cwd();
29
35
 
30
36
  const Html = pluginOptions.Html ?? DEFAULT_CONFIG.HTML;
@@ -35,29 +41,29 @@ export async function createHandler<T>(
35
41
  const controller = new AbortController();
36
42
 
37
43
  const cssFiles = streamOptions.cssFiles;
38
- const propsPath =
39
- typeof pluginOptions.props === "function"
40
- ? pluginOptions.props(url)
41
- : pluginOptions.props;
42
- const pagePath =
43
- typeof pluginOptions.Page === "function"
44
- ? pluginOptions.Page(url)
45
- : pluginOptions.Page;
46
44
 
47
- const cssModules = new Set<string>();
45
+
46
+ const cssModules = streamOptions.cssModules ?? new Set<string>();
48
47
 
49
48
  if (!(streamOptions.serverManifest || streamOptions.moduleGraph))
50
49
  throw new Error("Missing server manifest or moduleGraph, pass it to options.");
51
50
 
52
51
  const getCss = streamOptions.serverManifest
53
52
  ? (id: string) =>
54
- collectManifestCss(
55
- streamOptions.serverManifest!,
56
- root,
57
- id,
58
- streamOptions.onCssFile
59
- )
60
- : (id: string) => collectModuleGraphCss(streamOptions.moduleGraph!, id);
53
+ collectManifestClientFiles({
54
+ manifest: streamOptions.serverManifest!,
55
+ root: root,
56
+ pagePath: id,
57
+ onCss: streamOptions.onCssFile,
58
+ moduleBase: pluginOptions.moduleBase,
59
+ preserveModulesRoot: pluginOptions.build.preserveModulesRoot,
60
+ }).cssFiles
61
+ : (id: string) =>
62
+ collectModuleGraphCss({
63
+ moduleGraph: streamOptions.moduleGraph!,
64
+ pagePath: id,
65
+ onCss: streamOptions.onCssFile,
66
+ });
61
67
 
62
68
  const loadWithCss = async (id: string, parentUrl: string) => {
63
69
  try {
@@ -81,45 +87,22 @@ export async function createHandler<T>(
81
87
  };
82
88
 
83
89
  const PropsModule = await resolveProps({
84
- propsModule: await loadWithCss(propsPath ?? pagePath, url),
85
- path: String(propsPath ?? pagePath),
90
+ propsModule: await loadWithCss(urlMap.get(url)?.props ?? url, url),
91
+ path: String(urlMap.get(url)?.props ?? url),
86
92
  exportName: propsExportName,
87
93
  url,
88
94
  });
89
- if (PropsModule.type === "error")
90
- return { type: PropsModule.type, error: PropsModule?.error };
91
- if (PropsModule.type === "skip") return { type: PropsModule.type };
92
- const props = PropsModule[propsExportName as keyof typeof PropsModule] as any;
93
- if (props?.type === "error") return { type: props.type, error: props.error };
94
- if (props?.type === "skip") return { type: props.type };
95
-
95
+ if (PropsModule.type !== "success") {
96
+ return PropsModule
97
+ }
96
98
  const PageModule = await resolvePage({
97
- pageModule: await loadWithCss(pagePath, url),
98
- path: pagePath,
99
+ pageModule: await loadWithCss(urlMap.get(url)?.page ?? url, url),
100
+ path: String(urlMap.get(url)?.page ?? url),
99
101
  exportName: pageExportName,
100
102
  url,
101
103
  });
102
- if (PageModule.type === "error")
103
- return { type: PageModule.type, error: PageModule.error };
104
- if (PageModule.type === "skip") return { type: PageModule.type };
105
- const Page = PageModule[pageExportName as keyof typeof PageModule] as any;
106
- if (Page?.type === "error") return { type: Page.type, error: Page.error };
107
- if (Page?.type === "skip") return { type: Page.type };
108
- if (!(typeof Page === "function")) {
109
- return {
110
- type: "error",
111
- error: new Error("Invalid Page component: " + pagePath, {
112
- cause: Page,
113
- }),
114
- };
115
- }
116
- if (!(typeof props === "object")) {
117
- return {
118
- type: "error",
119
- error: new Error("Invalid props: " + propsPath, {
120
- cause: props,
121
- }),
122
- }
104
+ if (PageModule.type !== "success") {
105
+ return PageModule
123
106
  }
124
107
 
125
108
  // Add any additional CSS files
@@ -128,16 +111,17 @@ export async function createHandler<T>(
128
111
  }
129
112
  const stream = createRscStream({
130
113
  Html: Html,
131
- Page: Page,
132
- props: props,
133
- moduleBasePath: '',
114
+ Page: PageModule[pageExportName as keyof typeof PageModule],
115
+ props: PropsModule[propsExportName as keyof typeof PropsModule],
116
+ moduleBasePath: streamOptions.moduleBasePath,
117
+ moduleBaseURL: streamOptions.moduleBaseURL,
134
118
  logger: streamOptions.logger ?? createLogger(),
135
119
  cssFiles: Array.from(cssModules),
136
120
  route: url,
137
121
  url,
138
122
  pipableStreamOptions: streamOptions.pipableStreamOptions,
139
123
  htmlProps: {
140
- pageProps: props,
124
+ pageProps: PropsModule[propsExportName as keyof typeof PropsModule],
141
125
  route: url,
142
126
  url: url,
143
127
  },
@@ -148,15 +132,14 @@ export async function createHandler<T>(
148
132
  }
149
133
 
150
134
  const assets: HandlerAssets = {
151
- css: new Set(cssFiles ?? []),
152
- clientPath: pagePath ?? ''
135
+ css: Array.from(cssModules).concat(cssFiles ?? []),
136
+ bootstrapModules: streamOptions.pipableStreamOptions?.bootstrapModules ?? [],
153
137
  };
154
-
155
138
  return {
156
139
  type: "success",
157
140
  controller,
158
141
  stream,
159
142
  assets,
160
- clientPath: assets.clientPath,
143
+ clientPath: urlMap.get(url)?.page ?? '',
161
144
  };
162
145
  }
@@ -0,0 +1,81 @@
1
+ import * as React from "react";
2
+ // @ts-ignore
3
+ import { renderToPipeableStream } from "react-server-dom-esm/server.node";
4
+ import type { PipeableStreamOptions } from "../worker/types.js";
5
+ import type { Logger } from "vite";
6
+ import { CssCollector } from "../components.js";
7
+
8
+ export function createRscStream({
9
+ Html,
10
+ Page,
11
+ props,
12
+ moduleBasePath,
13
+ moduleBaseURL,
14
+ logger,
15
+ cssFiles = [],
16
+ route,
17
+ url,
18
+ pipableStreamOptions,
19
+ htmlProps,
20
+ }: {
21
+ Html: React.ComponentType<any>;
22
+ Page: React.ComponentType<any>;
23
+ props: any;
24
+ moduleBasePath: string;
25
+ moduleBaseURL: string;
26
+ logger: Logger;
27
+ cssFiles?: string[];
28
+ route: string;
29
+ url: string;
30
+ pipableStreamOptions?: PipeableStreamOptions;
31
+ htmlProps?: any;
32
+ }) {
33
+ const htmlIsFragment = Html == React.Fragment;
34
+ if (!htmlIsFragment) {
35
+ if (!htmlProps) {
36
+ htmlProps = {};
37
+ }
38
+ if(!("moduleBaseUrl" in htmlProps)) {
39
+ htmlProps["moduleBaseUrl"] = moduleBaseURL;
40
+ }
41
+ if(!("moduleBasePath" in htmlProps)) {
42
+ htmlProps["moduleBasePath"] = moduleBasePath;
43
+ }
44
+ if (!("url" in htmlProps)) {
45
+ htmlProps["url"] = url;
46
+ }
47
+ if (!("route" in htmlProps)) {
48
+ htmlProps["route"] = route;
49
+ }
50
+ if (!("pageProps" in htmlProps)) {
51
+ htmlProps["pageProps"] = props;
52
+ }
53
+ }
54
+ const withCss = React.createElement(
55
+ CssCollector,
56
+ { cssFiles, route, moduleBaseUrl: moduleBaseURL },
57
+ React.createElement(Page, props)
58
+ );
59
+ // Otherwise wrap with Html component
60
+ const content = htmlIsFragment
61
+ ? withCss
62
+ : React.createElement(Html, htmlProps, withCss);
63
+ try {
64
+ return renderToPipeableStream(content, moduleBaseURL, {
65
+ onError: (error: Error) => {
66
+ if (process.env["NODE_ENV"] === "development") {
67
+ console.trace(error);
68
+ }
69
+ logger.error(`Stream error at ${route}.`, { error });
70
+ },
71
+ onPostpone: logger.info ?? console.info,
72
+ environmentName: "Server",
73
+ ...pipableStreamOptions,
74
+ });
75
+ } catch (error) {
76
+ logger.error(`Failed to create stream for ${route}.`, {
77
+ error: error as Error,
78
+ });
79
+ return null;
80
+ }
81
+ }
@@ -4,8 +4,7 @@ import type {
4
4
  OutputChunk,
5
5
  } from "rollup";
6
6
  import { createInputNormalizer } from "./inputNormalizer.js";
7
- import { join } from "path";
8
- import { DEFAULT_CONFIG, resolveOptions } from "../config/index.js";
7
+ import { DEFAULT_CONFIG } from "../config/index.js";
9
8
 
10
9
  interface BundleManifestEntry {
11
10
  file: string;
@@ -70,7 +69,7 @@ export function getBundleManifest({
70
69
  }
71
70
 
72
71
  // Normalize both paths, removing the root prefix
73
- const [normalizedId, sourcePath] = normalizer(moduleId);
72
+ let [normalizedId, sourcePath] = normalizer(moduleId);
74
73
 
75
74
  // For virtual modules, use a consistent naming scheme
76
75
  let finalFileName = fileName;
@@ -91,12 +90,22 @@ export function getBundleManifest({
91
90
 
92
91
  finalFileName = virtualModules.get(virtualKey)!;
93
92
  }
93
+ // handle preserveModulesRoot
94
+ if(normalizedId.startsWith('\x00')){
95
+ normalizedId = normalizedId.slice(1);
96
+ }
97
+ if(sourcePath.startsWith('/')){
98
+ sourcePath = sourcePath.slice(1);
99
+ }
100
+ if(moduleBase && preserveModulesRoot && normalizedId?.startsWith(moduleBase + '/')) {
101
+ normalizedId = normalizedId.slice(moduleBase.length + 1);
102
+ }
94
103
  const bundleManifestEntry = [
95
104
  sourcePath,
96
105
  {
97
106
  file: finalFileName,
98
- name: normalizedId.startsWith('\x00') ? normalizedId.replace('\x00', '') : normalizedId,
99
- src: sourcePath.startsWith('/') ? sourcePath.slice(1) : sourcePath,
107
+ name: normalizedId,
108
+ src: sourcePath,
100
109
  isEntry: chunk.isEntry,
101
110
  ...(chunk.imports?.length > 0 ? { imports: chunk.imports } : {}),
102
111
  ...(chunk.dynamicImports?.length > 0 ? { dynamicImports: chunk.dynamicImports } : {}),
@@ -1,4 +1,4 @@
1
- import { join, relative, resolve } from "node:path";
1
+ import { join } from "node:path";
2
2
  import type { PluginContext } from "rollup";
3
3
  import type { ResolvedUserConfig, ResolvedUserOptions } from "../../server.js";
4
4
  import type { Manifest } from "vite";
@@ -15,26 +15,29 @@ export interface BuildLoaderOptions {
15
15
 
16
16
  export function createBuildLoader({
17
17
  root,
18
- userConfig,
18
+ userConfig: _userConfig,
19
19
  userOptions,
20
- pluginContext,
20
+ pluginContext: _pluginContext,
21
21
  serverManifest,
22
22
  clientManifest,
23
23
  }: BuildLoaderOptions) {
24
24
  const normalizer = createInputNormalizer({
25
25
  root,
26
- preserveModulesRoot: undefined,
27
- removeExtension: false,
26
+ preserveModulesRoot: userOptions.build.preserveModulesRoot === true ? userOptions.moduleBase : undefined,
27
+ removeExtension: true,
28
28
  });
29
29
  return async function buildLoader(id: string) {
30
30
  const [key, value] = normalizer(id);
31
+ if(value !== id){
32
+ console.warn(`[vite-plugin-react-server] Mismatch in build loader for ${id} !== ${value} (${key})`);
33
+ }
31
34
  // Remove leading slash if present
32
35
  const distDir = userOptions.build.outDir;
33
36
  const manifests = [clientManifest, serverManifest];
34
37
  // Try to find the module in the manifest
35
38
  for (const n of [0, 1]) {
36
39
  const manifest = manifests[n];
37
- const manifestEntry = manifest[key]
40
+ const manifestEntry = manifest[value]
38
41
  if (!manifestEntry) {
39
42
  continue;
40
43
  }
@@ -20,10 +20,8 @@ export async function initialize(data: { port: MessagePort }) {
20
20
 
21
21
  // CSS file tracking per page
22
22
  const cssFilesByPage = new Map<string, Set<string>>();
23
- let currentPage: string | null = null;
24
23
 
25
24
  export function setCurrentPage(page: string | null) {
26
- currentPage = page;
27
25
  if (page && !cssFilesByPage.has(page)) {
28
26
  cssFilesByPage.set(page, new Set());
29
27
  }
@@ -117,7 +117,7 @@ function transformServerModule(
117
117
  program: any,
118
118
  url: string,
119
119
  sourceMap: any,
120
- loader: any,
120
+ _loader: any,
121
121
  port: MessagePort | undefined
122
122
  ) {
123
123
  const body = program.body; // This entry list needs to be in source location order.
@@ -934,7 +934,7 @@ export async function transformSource(
934
934
  const newSrc = await transformModuleIfNeeded(
935
935
  transformedSource,
936
936
  context.url,
937
- (url: string, ctx: any, defaultLoad: any) =>
937
+ (url: string) =>
938
938
  loadClientImport(url, defaultTransformSource),
939
939
  context.data?.port!
940
940
  );
@@ -1,10 +1,41 @@
1
1
  import type { Node } from "estree";
2
- import MagicString from "magic-string";
3
2
  import type { StreamPluginOptions } from "../types.js";
4
3
  import { DEFAULT_CONFIG } from "../config/defaults.js";
4
+ import { basename } from "path";
5
5
 
6
6
  const REACT_DIRECTIVES = new Set(["use client", "use server"]);
7
7
 
8
+ function createSourceMap(id: string, code: string, mappings: string) {
9
+ return {
10
+ version: 3,
11
+ file: basename(id),
12
+ sources: [id],
13
+ sourcesContent: [code],
14
+ names: [],
15
+ mappings,
16
+ sourceRoot: "",
17
+ };
18
+ }
19
+
20
+ function removeRanges(code: string, ranges: Array<{ start: number; end: number }>) {
21
+ // Sort ranges in reverse order to not affect positions
22
+ ranges.sort((a, b) => b.start - a.start);
23
+
24
+ let result = code;
25
+ for (const range of ranges) {
26
+ result = result.slice(0, range.start) + result.slice(range.end);
27
+ }
28
+ return result;
29
+ }
30
+
31
+ function countLines(str: string): number {
32
+ let count = 1;
33
+ for (let i = 0; i < str.length; i++) {
34
+ if (str[i] === '\n') count++;
35
+ }
36
+ return count;
37
+ }
38
+
8
39
  export function reactPreservePlugin(_options: StreamPluginOptions): import("vite").Plugin {
9
40
  const meta: Record<string, Set<string>> = {};
10
41
 
@@ -35,8 +66,10 @@ export function reactPreservePlugin(_options: StreamPluginOptions): import("vite
35
66
  return null;
36
67
  }
37
68
 
38
- const magicString = new MagicString(code);
69
+ const rangesToRemove: Array<{ start: number; end: number }> = [];
39
70
  let hasChanged = false;
71
+ let lineCount = 1;
72
+ let mappings = "AAAA"; // Initial mapping for first line
40
73
 
41
74
  // Only look at top-level directives
42
75
  for (const node of ast.body) {
@@ -55,13 +88,20 @@ export function reactPreservePlugin(_options: StreamPluginOptions): import("vite
55
88
  directive = node.expression.value;
56
89
  }
57
90
 
58
- if (directive) {
91
+ if (directive && "start" in node && "end" in node) {
59
92
  meta[id] ||= new Set<string>();
60
93
  meta[id].add(directive);
61
-
62
- if ("start" in node && "end" in node) {
63
- magicString.remove(node.start as number, node.end as number);
64
- hasChanged = true;
94
+ rangesToRemove.push({
95
+ start: node.start as number,
96
+ end: node.end as number
97
+ });
98
+ hasChanged = true;
99
+
100
+ // Add mapping for each line removed
101
+ const removedLines = code.slice(node.start as number, node.end as number).split('\n').length - 1;
102
+ for (let i = 0; i < removedLines; i++) {
103
+ mappings += ";AACA";
104
+ lineCount++;
65
105
  }
66
106
  }
67
107
  }
@@ -70,9 +110,12 @@ export function reactPreservePlugin(_options: StreamPluginOptions): import("vite
70
110
  return null;
71
111
  }
72
112
 
113
+ const newCode = removeRanges(code, rangesToRemove);
114
+ const sourceMap = createSourceMap(id, code, mappings);
115
+
73
116
  return {
74
- code: magicString.toString(),
75
- map: magicString.generateMap({ hires: true }),
117
+ code: newCode,
118
+ map: sourceMap,
76
119
  meta: {
77
120
  directives: Array.from(meta[id] || []),
78
121
  },
@@ -91,16 +134,20 @@ export function reactPreservePlugin(_options: StreamPluginOptions): import("vite
91
134
  }
92
135
 
93
136
  if (chunkDirectives.size) {
94
- const magicString = new MagicString(code);
95
- magicString.prepend(
96
- Array.from(chunkDirectives)
97
- .map((d) => `"${d}";`)
98
- .join("\n") + "\n"
99
- );
137
+ const directivesCode = Array.from(chunkDirectives)
138
+ .map((d) => `"${d}";`)
139
+ .join("\n") + "\n";
140
+
141
+ const newCode = directivesCode + code;
142
+
143
+ // Create source map for the prepended directives
144
+ const lineCount = countLines(directivesCode);
145
+ const mappings = "AAAA" + ";AACA".repeat(lineCount - 1);
146
+ const sourceMap = createSourceMap(chunk.fileName, code, mappings);
100
147
 
101
148
  return {
102
- code: magicString.toString(),
103
- map: magicString.generateMap({ hires: true }),
149
+ code: newCode,
150
+ map: sourceMap,
104
151
  };
105
152
  }
106
153