vite-plugin-react-server 0.3.18 → 1.0.0

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 (246) hide show
  1. package/README.md +220 -141
  2. package/bin/patch.mjs +8 -2
  3. package/dist/package.json +15 -8
  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 +131 -0
  10. package/dist/plugin/collect-manifest-client-files.js.map +1 -0
  11. package/dist/plugin/components.d.ts +3 -13
  12. package/dist/plugin/components.d.ts.map +1 -1
  13. package/dist/plugin/components.js +3 -13
  14. package/dist/plugin/config/defaults.d.ts +14 -6
  15. package/dist/plugin/config/defaults.d.ts.map +1 -1
  16. package/dist/plugin/config/defaults.js +9 -5
  17. package/dist/plugin/config/defaults.js.map +1 -1
  18. package/dist/plugin/config/getPaths.d.ts +0 -1
  19. package/dist/plugin/config/getPaths.d.ts.map +1 -1
  20. package/dist/plugin/config/getPaths.js +2 -7
  21. package/dist/plugin/config/getPaths.js.map +1 -1
  22. package/dist/plugin/config/mimeTypes.d.ts +2 -0
  23. package/dist/plugin/config/mimeTypes.d.ts.map +1 -0
  24. package/dist/plugin/config/mimeTypes.js +24 -0
  25. package/dist/plugin/config/mimeTypes.js.map +1 -0
  26. package/dist/plugin/config/resolveOptions.d.ts +2 -2
  27. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  28. package/dist/plugin/config/resolveOptions.js +47 -28
  29. package/dist/plugin/config/resolveOptions.js.map +1 -1
  30. package/dist/plugin/config/resolvePages.d.ts +1 -0
  31. package/dist/plugin/config/resolvePages.d.ts.map +1 -1
  32. package/dist/plugin/config/resolvePages.js +9 -5
  33. package/dist/plugin/config/resolvePages.js.map +1 -1
  34. package/dist/plugin/config/resolveUserConfig.d.ts +2 -1
  35. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  36. package/dist/plugin/config/resolveUserConfig.js +181 -147
  37. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  38. package/dist/plugin/copy-dir.js +23 -18
  39. package/dist/plugin/copy-dir.js.map +1 -0
  40. package/dist/plugin/css-collector-inline.d.ts +10 -0
  41. package/dist/plugin/css-collector-inline.d.ts.map +1 -0
  42. package/dist/plugin/css-collector-inline.js +55 -0
  43. package/dist/plugin/css-collector-inline.js.map +1 -0
  44. package/dist/plugin/css-collector.d.ts +14 -0
  45. package/dist/plugin/css-collector.d.ts.map +1 -0
  46. package/dist/plugin/css-collector.js +49 -0
  47. package/dist/plugin/css-collector.js.map +1 -0
  48. package/dist/plugin/helpers/createHandler.d.ts +17 -0
  49. package/dist/plugin/helpers/createHandler.d.ts.map +1 -0
  50. package/dist/plugin/helpers/createHandler.js +111 -0
  51. package/dist/plugin/helpers/createHandler.js.map +1 -0
  52. package/dist/plugin/helpers/createRscStream.d.ts +27 -0
  53. package/dist/plugin/helpers/createRscStream.d.ts.map +1 -0
  54. package/dist/plugin/helpers/createRscStream.js +80 -0
  55. package/dist/plugin/helpers/createRscStream.js.map +1 -0
  56. package/dist/plugin/helpers/getBundleManifest.d.ts.map +1 -1
  57. package/dist/plugin/helpers/getBundleManifest.js +12 -4
  58. package/dist/plugin/helpers/getBundleManifest.js.map +1 -1
  59. package/dist/plugin/html.d.ts +5 -0
  60. package/dist/plugin/html.d.ts.map +1 -0
  61. package/dist/plugin/html.js +11 -0
  62. package/dist/plugin/html.js.map +1 -0
  63. package/dist/plugin/loader/createBuildLoader.d.ts +1 -1
  64. package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
  65. package/dist/plugin/loader/createBuildLoader.js +8 -5
  66. package/dist/plugin/loader/createBuildLoader.js.map +1 -1
  67. package/dist/plugin/loader/css-loader.d.ts.map +1 -1
  68. package/dist/plugin/loader/css-loader.js.map +1 -1
  69. package/dist/plugin/loader/react-loader.js +2 -2
  70. package/dist/plugin/loader/react-loader.js.map +1 -1
  71. package/dist/plugin/preserver/plugin.d.ts.map +1 -1
  72. package/dist/plugin/preserver/plugin.js +49 -14
  73. package/dist/plugin/preserver/plugin.js.map +1 -1
  74. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  75. package/dist/plugin/react-client/plugin.js +21 -78
  76. package/dist/plugin/react-client/plugin.js.map +1 -1
  77. package/dist/plugin/react-server/index.d.ts.map +1 -1
  78. package/dist/plugin/react-server/index.js +2 -0
  79. package/dist/plugin/react-server/index.js.map +1 -1
  80. package/dist/plugin/react-server/plugin.d.ts +2 -1
  81. package/dist/plugin/react-server/plugin.d.ts.map +1 -1
  82. package/dist/plugin/react-server/plugin.js +92 -225
  83. package/dist/plugin/react-server/plugin.js.map +1 -1
  84. package/dist/plugin/react-static/index.d.ts +2 -0
  85. package/dist/plugin/react-static/index.d.ts.map +1 -0
  86. package/dist/plugin/react-static/index.js +1 -0
  87. package/dist/plugin/react-static/plugin.d.ts +7 -0
  88. package/dist/plugin/react-static/plugin.d.ts.map +1 -0
  89. package/dist/plugin/react-static/plugin.js +207 -0
  90. package/dist/plugin/react-static/plugin.js.map +1 -0
  91. package/dist/plugin/react-static/types.d.ts +2 -0
  92. package/dist/plugin/react-static/types.d.ts.map +1 -0
  93. package/dist/plugin/resolvePage.d.ts.map +1 -1
  94. package/dist/plugin/resolvePage.js +9 -0
  95. package/dist/plugin/resolvePage.js.map +1 -1
  96. package/dist/plugin/root.d.ts +2 -0
  97. package/dist/plugin/root.d.ts.map +1 -0
  98. package/dist/plugin/root.js +12 -0
  99. package/dist/plugin/root.js.map +1 -0
  100. package/dist/plugin/transformer/plugin.d.ts.map +1 -1
  101. package/dist/plugin/transformer/plugin.js +32 -23
  102. package/dist/plugin/transformer/plugin.js.map +1 -1
  103. package/dist/plugin/transformer/types.d.ts +1 -18
  104. package/dist/plugin/transformer/types.d.ts.map +1 -1
  105. package/dist/plugin/types.d.ts +70 -15
  106. package/dist/plugin/types.d.ts.map +1 -1
  107. package/dist/plugin/worker/createWorker.js +0 -1
  108. package/dist/plugin/worker/createWorker.js.map +1 -1
  109. package/dist/plugin/worker/html/html-worker.development.d.ts +30 -0
  110. package/dist/plugin/worker/html/html-worker.development.d.ts.map +1 -1
  111. package/dist/plugin/worker/html/html-worker.development.js +30 -2
  112. package/dist/plugin/worker/html/html-worker.development.js.map +1 -1
  113. package/dist/plugin/worker/html/html-worker.production.js +3 -5
  114. package/dist/plugin/worker/html/html-worker.production.js.map +1 -1
  115. package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
  116. package/dist/plugin/worker/html/messageHandler.js +12 -3
  117. package/dist/plugin/worker/html/messageHandler.js.map +1 -1
  118. package/dist/plugin/worker/html/renderPages.d.ts +13 -26
  119. package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
  120. package/dist/plugin/worker/html/renderPages.js +138 -86
  121. package/dist/plugin/worker/html/renderPages.js.map +1 -1
  122. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
  123. package/dist/plugin/worker/rsc/messageHandler.js +104 -84
  124. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
  125. package/dist/plugin/worker/rsc/rsc-worker.development.js +13 -18
  126. package/dist/plugin/worker/rsc/rsc-worker.development.js.map +1 -1
  127. package/dist/plugin/worker/rsc/rsc-worker.production.js +4 -1
  128. package/dist/plugin/worker/rsc/rsc-worker.production.js.map +1 -1
  129. package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
  130. package/dist/plugin/worker/rsc/state.js.map +1 -1
  131. package/dist/plugin/worker/types.d.ts +3 -0
  132. package/dist/plugin/worker/types.d.ts.map +1 -1
  133. package/dist/tsconfig.tsbuildinfo +1 -1
  134. package/package.json +14 -6
  135. package/plugin/checkFilesExist.ts +7 -3
  136. package/plugin/collect-manifest-client-files.ts +167 -0
  137. package/plugin/components.ts +3 -0
  138. package/plugin/config/defaults.tsx +70 -0
  139. package/plugin/config/getPaths.ts +1 -7
  140. package/plugin/config/mimeTypes.ts +17 -0
  141. package/plugin/config/resolveOptions.ts +58 -45
  142. package/plugin/config/resolvePages.ts +8 -4
  143. package/plugin/config/resolveUserConfig.ts +220 -176
  144. package/plugin/css-collector-inline.tsx +60 -0
  145. package/plugin/css-collector.tsx +62 -0
  146. package/plugin/helpers/createHandler.ts +135 -0
  147. package/plugin/helpers/createRscStream.ts +109 -0
  148. package/plugin/helpers/getBundleManifest.ts +14 -5
  149. package/plugin/html.tsx +9 -0
  150. package/plugin/loader/createBuildLoader.ts +9 -6
  151. package/plugin/loader/css-loader.ts +0 -2
  152. package/plugin/loader/react-loader.ts +2 -2
  153. package/plugin/preserver/plugin.ts +64 -17
  154. package/plugin/react-client/plugin.ts +23 -93
  155. package/plugin/react-server/index.ts +2 -0
  156. package/plugin/react-server/plugin.ts +111 -302
  157. package/plugin/react-static/index.ts +1 -0
  158. package/plugin/react-static/plugin.ts +256 -0
  159. package/plugin/react-static/types.ts +3 -0
  160. package/plugin/resolvePage.ts +9 -0
  161. package/plugin/root.ts +4 -0
  162. package/plugin/transformer/plugin.ts +40 -31
  163. package/plugin/transformer/types.ts +0 -19
  164. package/plugin/types.ts +77 -16
  165. package/plugin/worker/createWorker.ts +1 -1
  166. package/plugin/worker/html/README.md +63 -0
  167. package/plugin/worker/html/html-worker.development.tsx +89 -2
  168. package/plugin/worker/html/html-worker.production.tsx +8 -10
  169. package/plugin/worker/html/messageHandler.ts +12 -3
  170. package/plugin/worker/html/renderPages.ts +178 -138
  171. package/plugin/worker/rsc/README.md +58 -0
  172. package/plugin/worker/rsc/messageHandler.tsx +112 -113
  173. package/plugin/worker/rsc/rsc-worker.development.ts +12 -22
  174. package/plugin/worker/rsc/rsc-worker.production.ts +5 -1
  175. package/plugin/worker/rsc/state.ts +0 -3
  176. package/plugin/worker/types.ts +3 -0
  177. package/scripts/react+0.0.0-experimental-eda36a1c-20250228.patch +114 -12
  178. package/scripts/react-dom+0.0.0-experimental-eda36a1c-20250228.patch +10571 -121
  179. package/tsconfig.json +2 -2
  180. package/dist/plugin/collect-css-manifest.d.ts +0 -4
  181. package/dist/plugin/collect-css-manifest.d.ts.map +0 -1
  182. package/dist/plugin/collect-css-manifest.js +0 -65
  183. package/dist/plugin/collect-css-manifest.js.map +0 -1
  184. package/dist/plugin/config/createModuleIdGenerator.d.ts +0 -11
  185. package/dist/plugin/config/createModuleIdGenerator.d.ts.map +0 -1
  186. package/dist/plugin/config/createModuleIdGenerator.js +0 -44
  187. package/dist/plugin/config/createModuleIdGenerator.js.map +0 -1
  188. package/dist/plugin/getEnv.d.ts +0 -19
  189. package/dist/plugin/getEnv.d.ts.map +0 -1
  190. package/dist/plugin/getEnv.js +0 -107
  191. package/dist/plugin/loader/createCssLoader.d.ts +0 -30
  192. package/dist/plugin/loader/createCssLoader.d.ts.map +0 -1
  193. package/dist/plugin/loader/createCssLoader.js +0 -35
  194. package/dist/plugin/loader/createPageLoader.d.ts +0 -24
  195. package/dist/plugin/loader/createPageLoader.d.ts.map +0 -1
  196. package/dist/plugin/loader/createPageLoader.js +0 -50
  197. package/dist/plugin/loader/rsc/messageHandler.d.ts +0 -2
  198. package/dist/plugin/loader/rsc/messageHandler.d.ts.map +0 -1
  199. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts +0 -2
  200. package/dist/plugin/loader/rsc/rsc-worker.development.d.ts.map +0 -1
  201. package/dist/plugin/loader/rsc/rsc-worker.development.js +0 -1
  202. package/dist/plugin/module-graph.d.ts +0 -10
  203. package/dist/plugin/module-graph.d.ts.map +0 -1
  204. package/dist/plugin/module-graph.js +0 -35
  205. package/dist/plugin/react-server/createHandler.d.ts +0 -17
  206. package/dist/plugin/react-server/createHandler.d.ts.map +0 -1
  207. package/dist/plugin/react-server/createHandler.js +0 -126
  208. package/dist/plugin/react-server/createHandler.js.map +0 -1
  209. package/dist/plugin/react-server/createRscStream.d.ts +0 -16
  210. package/dist/plugin/react-server/createRscStream.d.ts.map +0 -1
  211. package/dist/plugin/react-server/createRscStream.js +0 -70
  212. package/dist/plugin/react-server/createRscStream.js.map +0 -1
  213. package/dist/plugin/react-server/createSsrHandler.d.ts +0 -4
  214. package/dist/plugin/react-server/createSsrHandler.d.ts.map +0 -1
  215. package/dist/plugin/react-server/createSsrHandler.js +0 -95
  216. package/dist/plugin/utils/logger.d.ts +0 -9
  217. package/dist/plugin/utils/logger.d.ts.map +0 -1
  218. package/dist/plugin/utils/logger.js +0 -68
  219. package/dist/plugin/utils/logger.js.map +0 -1
  220. package/dist/plugin/worker/html/plugin.d.ts +0 -4
  221. package/dist/plugin/worker/html/plugin.d.ts.map +0 -1
  222. package/dist/plugin/worker/html/plugin.js +0 -94
  223. package/dist/plugin/worker/plugin.d.ts +0 -19
  224. package/dist/plugin/worker/plugin.d.ts.map +0 -1
  225. package/dist/plugin/worker/plugin.js +0 -23
  226. package/dist/plugin/worker/rsc/plugin.d.ts +0 -4
  227. package/dist/plugin/worker/rsc/plugin.d.ts.map +0 -1
  228. package/dist/plugin/worker/rsc/plugin.js +0 -76
  229. package/plugin/collect-css-manifest.ts +0 -82
  230. package/plugin/components.tsx +0 -14
  231. package/plugin/config/createModuleIdGenerator.ts +0 -52
  232. package/plugin/config/defaults.ts +0 -51
  233. package/plugin/getEnv.ts +0 -135
  234. package/plugin/loader/createCssLoader.ts +0 -73
  235. package/plugin/loader/createPageLoader.ts +0 -103
  236. package/plugin/loader/rsc/messageHandler.tsx +0 -1
  237. package/plugin/loader/rsc/rsc-worker.development.ts +0 -1
  238. package/plugin/module-graph.ts +0 -48
  239. package/plugin/react-server/createHandler.ts +0 -162
  240. package/plugin/react-server/createRscStream.ts +0 -86
  241. package/plugin/react-server/createSsrHandler.ts +0 -125
  242. package/plugin/utils/logger.ts +0 -52
  243. package/plugin/worker/html/plugin.ts +0 -101
  244. package/plugin/worker/plugin.ts +0 -26
  245. package/plugin/worker/rsc/plugin.ts +0 -84
  246. /package/dist/plugin/{loader/rsc/messageHandler.js → react-static/types.js} +0 -0
@@ -0,0 +1,256 @@
1
+ import { join, dirname } from "node:path";
2
+ import { Worker } from "node:worker_threads";
3
+ import {
4
+ type ResolvedConfig,
5
+ type UserConfig,
6
+ type Manifest,
7
+ type IndexHtmlTransformHook,
8
+ type Plugin as VitePlugin,
9
+ createLogger,
10
+ } from "vite";
11
+ import { checkFilesExist } from "../checkFilesExist.js";
12
+ import { resolveOptions } from "../config/resolveOptions.js";
13
+ import { resolvePages } from "../config/resolvePages.js";
14
+ import { resolveUserConfig } from "../config/resolveUserConfig.js";
15
+ import { tryManifest } from "../helpers/tryManifest.js";
16
+ import { createBuildLoader } from "../loader/createBuildLoader.js";
17
+ import type {
18
+ BuildTiming,
19
+ CheckFilesExistReturn,
20
+ ReactStreamPluginMeta,
21
+ ResolvedUserConfig,
22
+ ResolvedUserOptions,
23
+ } from "../types.js";
24
+ import { type StreamPluginOptions } from "../types.js";
25
+ import { createWorker } from "../worker/createWorker.js";
26
+ import { renderPages } from "../worker/html/renderPages.js";
27
+ import { mkdir } from "node:fs/promises";
28
+ import { collectManifestClientFiles } from "../collect-manifest-client-files.js";
29
+ import { mkdirSync, copyFileSync } from "node:fs";
30
+ import { copyDir } from "../copy-dir.js";
31
+
32
+ let resolvedConfig: ResolvedConfig | null = null;
33
+ let loader: ((id: string) => Promise<Record<string, any>>) | null = null;
34
+ let worker: Worker;
35
+ let htmlTransform: IndexHtmlTransformHook | null = null;
36
+ let clientAssets = new Set<string>();
37
+
38
+ export function reactStaticPlugin(options: StreamPluginOptions): VitePlugin<{
39
+ meta: ReactStreamPluginMeta;
40
+ }> {
41
+ const timing: BuildTiming = {
42
+ start: Date.now(),
43
+ };
44
+
45
+ let files: CheckFilesExistReturn;
46
+ let root: string = process.cwd();
47
+ let userConfig: ResolvedUserConfig;
48
+ let userOptions: ResolvedUserOptions;
49
+ let pages: string[];
50
+ let serverManifest: Manifest = {};
51
+ let clientManifest: Manifest = {};
52
+
53
+ const resolvedOptions = resolveOptions(options, false);
54
+ if (resolvedOptions.type === "error") {
55
+ throw resolvedOptions.error;
56
+ }
57
+ userOptions = resolvedOptions.userOptions;
58
+ if (
59
+ userOptions.projectRoot != root &&
60
+ typeof userOptions.projectRoot === "string" &&
61
+ userOptions.projectRoot !== process.cwd() &&
62
+ userOptions.projectRoot !== ""
63
+ ) {
64
+ root = userOptions.projectRoot;
65
+ console.log(
66
+ "[vite:plugin-react-server] Root dir changed in plugin",
67
+ userOptions.projectRoot,
68
+ root
69
+ );
70
+ }
71
+
72
+ return {
73
+ name: "vite:plugin-react-server/static",
74
+ enforce: "post",
75
+ api: {
76
+ meta: { timing },
77
+ },
78
+ async config(config, configEnv): Promise<UserConfig> {
79
+ if (
80
+ typeof config.root === "string" &&
81
+ config.root !== root &&
82
+ config.root !== process.cwd() &&
83
+ config.root !== ""
84
+ ) {
85
+ root = config.root;
86
+ }
87
+ const resolvePagesResult = await resolvePages(userOptions.build.pages);
88
+ if (resolvePagesResult.type === "error") {
89
+ throw resolvePagesResult.error;
90
+ }
91
+ pages = resolvePagesResult.pages;
92
+ files = await checkFilesExist(pages, userOptions, root);
93
+
94
+ const resolvedConfig = resolveUserConfig({
95
+ isStatic: true,
96
+ config,
97
+ configEnv,
98
+ userOptions,
99
+ files,
100
+ });
101
+
102
+ if (resolvedConfig.type === "error") {
103
+ throw resolvedConfig.error;
104
+ }
105
+
106
+ userConfig = resolvedConfig.userConfig;
107
+ timing.configResolved = Date.now();
108
+ return {};
109
+ },
110
+ async buildStart() {
111
+ timing.buildStart = Date.now();
112
+ },
113
+ async closeBundle() {
114
+ timing.renderStart = Date.now();
115
+
116
+ // Create the loader
117
+ const serverManifestResult = tryManifest({
118
+ root: root,
119
+ outDir: join(userOptions.build.outDir, userOptions.build.server),
120
+ ssrManifest: false,
121
+ });
122
+ if (serverManifestResult.type === "error") {
123
+ throw serverManifestResult.error;
124
+ }
125
+ serverManifest = serverManifestResult.manifest;
126
+
127
+ // Get the client manifest
128
+ const clientManifestResult = tryManifest({
129
+ root: root,
130
+ outDir: join(userOptions.build.outDir, userOptions.build.client),
131
+ ssrManifest: false,
132
+ });
133
+
134
+ if (clientManifestResult.type === "error") {
135
+ throw clientManifestResult.error;
136
+ }
137
+ clientManifest = clientManifestResult.manifest;
138
+
139
+ // Ensure static directory exists
140
+ const staticDir = join(root, userOptions.build.outDir, userOptions.build.static);
141
+ await mkdir(staticDir, { recursive: true });
142
+
143
+ worker = await createWorker({
144
+ projectRoot: root,
145
+ workerPath: userOptions.htmlWorkerPath,
146
+ condition: "react-server",
147
+ reverseCondition: true,
148
+ mode: (resolvedConfig?.mode ?? "production") as "production" | "development",
149
+ });
150
+
151
+ if (typeof loader !== "function") {
152
+ loader = createBuildLoader({
153
+ root: root,
154
+ userConfig,
155
+ userOptions,
156
+ pluginContext: this,
157
+ serverManifest,
158
+ clientManifest,
159
+ });
160
+ }
161
+
162
+ // Collect CSS files per route
163
+ const routeCssMap = new Map<string, Set<string>>();
164
+ const globalCss = new Set<string>();
165
+ // copy whole client directory to static directory
166
+ await mkdir(staticDir, { recursive: true });
167
+ await copyDir(join(root, userOptions.build.outDir, userOptions.build.client), join(root, userOptions.build.outDir, userOptions.build.static));
168
+ // Add global CSS from index.html - use client manifest
169
+ const {cssFiles: indexCss} = collectManifestClientFiles({
170
+ manifest: clientManifest,
171
+ root: root,
172
+ pagePath: 'index.html',
173
+ moduleBase: userOptions.moduleBase,
174
+ preserveModulesRoot: userOptions.build.preserveModulesRoot,
175
+ testClient: ()=>true,
176
+ });
177
+ indexCss.forEach((css) => globalCss.add(css));
178
+
179
+ // Add CSS for each route's page component - use server manifest
180
+ for (const route of pages) {
181
+ const routeFiles = files.urlMap.get(route);
182
+ if (routeFiles) {
183
+ const pageCss = collectManifestClientFiles({
184
+ manifest: serverManifest,
185
+ root: root,
186
+ pagePath: routeFiles.page,
187
+ moduleBase: userOptions.moduleBase,
188
+ preserveModulesRoot: userOptions.build.preserveModulesRoot,
189
+ onClientModule(path) {
190
+ // copy the css file to the static directory
191
+ const targetPath = join(root, userOptions.build.outDir, userOptions.build.server, path);
192
+ const destinationPath = join(root, userOptions.build.outDir, userOptions.build.static, path);
193
+ mkdirSync(dirname(destinationPath), { recursive: true });
194
+ copyFileSync(targetPath, destinationPath);
195
+ },
196
+ testClient: userOptions.autoDiscover.cssPattern,
197
+ testJson: userOptions.autoDiscover.jsonPattern,
198
+ });
199
+ routeCssMap.set(route, new Set([...globalCss, ...pageCss.cssFiles.keys()]));
200
+ }
201
+ }
202
+ const bootstrapModules = clientManifest["index.html"]?.file
203
+ ? [clientManifest["index.html"].file.startsWith("/")
204
+ ? clientManifest["index.html"].file.slice(1)
205
+ : clientManifest["index.html"].file]
206
+ : [];
207
+
208
+ const { failedRoutes, completedRoutes} = await renderPages(
209
+ pages,
210
+ files,
211
+ {
212
+ root: root,
213
+ outDir: userOptions.build.outDir,
214
+ htmlOutputPath: join( userOptions.build.outDir, userOptions.build.static, "index.html"),
215
+ pipableStreamOptions: {
216
+ bootstrapModules: bootstrapModules,
217
+ },
218
+ moduleRootPath: join(root, userOptions.build.outDir, userOptions.build.static, userOptions.moduleBasePath),
219
+ moduleBasePath: userOptions.moduleBasePath,
220
+ moduleBaseURL: userOptions.moduleBaseURL,
221
+ inlineCss: userOptions.inlineCss,
222
+ pageExportName: userOptions.pageExportName,
223
+ propsExportName: userOptions.propsExportName,
224
+ Html: userOptions.Html,
225
+ CssCollector: userOptions.CssCollector,
226
+ cssFiles: [],
227
+ logger: createLogger(),
228
+ moduleBase: userOptions.moduleBase,
229
+ worker,
230
+ clientManifest,
231
+ serverManifest,
232
+ loader,
233
+ transformIndexHtml: htmlTransform!,
234
+ onClientJSFile: (url) => {
235
+ if (!clientAssets.has(url)) {
236
+ const clientPath = join(root, userOptions.build.outDir, userOptions.build.client, url);
237
+ const targetPath = join(root, userOptions.build.outDir, userOptions.build.static, url);
238
+ mkdirSync(dirname(targetPath), { recursive: true });
239
+ copyFileSync(clientPath, targetPath);
240
+ clientAssets.add(url);
241
+ }
242
+ }
243
+ }
244
+ );
245
+
246
+ if (failedRoutes.size > 0) {
247
+ console.error(
248
+ "[vite-plugin-react-server] Failed to render routes:",
249
+ failedRoutes
250
+ );
251
+ }
252
+ console.log(`Rendered ${completedRoutes.size} unique routes to ${join(userOptions.build.outDir, userOptions.build.static)}`);
253
+ await worker.terminate();
254
+ },
255
+ };
256
+ }
@@ -0,0 +1,3 @@
1
+ export type ReactStaticPluginOptions = {
2
+
3
+ };
@@ -1,3 +1,5 @@
1
+ import { stashedPages } from "./config/resolvePages.js";
2
+
1
3
  type ResolvePageOptions = {
2
4
  pageModule: Record<string, any>;
3
5
  path: string;
@@ -16,6 +18,13 @@ export async function resolvePage({
16
18
  url,
17
19
  exportName,
18
20
  }: ResolvePageOptions): Promise<ResolvePageResult> {
21
+ if(stashedPages.length > 0 && stashedPages.includes(path)){
22
+ return {
23
+ type: "success",
24
+ key: path,
25
+ Page: pageModule,
26
+ }
27
+ }
19
28
  if (!pageModule) {
20
29
  return {
21
30
  type: "error",
package/plugin/root.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { dirname } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ export const pluginRoot = dirname(fileURLToPath(import.meta.url));
4
+
@@ -1,6 +1,6 @@
1
1
  import { resolveOptions } from "../config/resolveOptions.js";
2
- import type { StreamPluginOptions } from "../types.js";
3
- import { type Plugin } from "vite";
2
+ import type { InputNormalizer, ResolvedUserOptions, StreamPluginOptions } from "../types.js";
3
+ import { type Manifest, type Plugin } from "vite";
4
4
  import { transformModuleIfNeeded } from "../loader/react-loader.js";
5
5
  import { DEFAULT_CONFIG } from "../config/defaults.js";
6
6
  import { createInputNormalizer } from "../helpers/inputNormalizer.js";
@@ -32,37 +32,47 @@ import { join } from "node:path";
32
32
  */
33
33
 
34
34
  export function reactTransformPlugin(options: StreamPluginOptions): Plugin {
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
- });
43
-
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
- });
53
-
35
+ let normalizer: InputNormalizer;
36
+ let clientManifest: Manifest;
37
+ let isDev:boolean;
38
+ let userOptions: ResolvedUserOptions
54
39
  return {
55
40
  name: "vite:react-transform",
56
41
  enforce: "pre", // Run before Vite's transforms
57
42
  config(config, configEnv) {
58
- isDev = configEnv.mode === "development" && configEnv.command === "serve";
43
+ const resolvedOptionsResult = resolveOptions(
44
+ options,
45
+ config.build?.outDir?.startsWith(
46
+ join(options.build?.outDir ?? DEFAULT_CONFIG.BUILD.outDir, options.build?.client ?? DEFAULT_CONFIG.BUILD.client)
47
+ ) ?? false
48
+ );
49
+ isDev = configEnv.mode === "development" && configEnv.command === "serve"
50
+ if (resolvedOptionsResult.type === "error") throw resolvedOptionsResult.error;
51
+ userOptions = resolvedOptionsResult.userOptions;
52
+ normalizer = createInputNormalizer({
53
+ root: resolvedOptionsResult.userOptions.projectRoot,
54
+ preserveModulesRoot: undefined,
55
+ removeExtension: false,
56
+ });
57
+
59
58
  },
60
59
  async transform(code, id, options) {
61
60
  const ssr = options?.ssr ?? false;
62
61
  if (!ssr) return null;
63
62
  if (!id.match(DEFAULT_CONFIG.FILE_REGEX)) return null;
64
- if (!code.match('"use client"'))
65
- return null;
63
+ if (!code.match('"use client"')) return null;
64
+
65
+ // Get the client manifest
66
+ const clientManifestResult = tryManifest({
67
+ root: userOptions.projectRoot,
68
+ outDir: join(
69
+ userOptions.build.outDir,
70
+ userOptions.build.client
71
+ ),
72
+ ssrManifest: false,
73
+ });
74
+ if (clientManifestResult.type === "error") throw clientManifestResult.error;
75
+ clientManifest = clientManifestResult.manifest;
66
76
  const [key, value] = normalizer(id);
67
77
  const transformed = await transformModuleIfNeeded(
68
78
  code,
@@ -87,16 +97,15 @@ export function reactTransformPlugin(options: StreamPluginOptions): Plugin {
87
97
  transformed,
88
98
  }
89
99
  );
90
- return null
91
- }
92
- if (clientManifestResult.type === "error") {
93
- throw clientManifestResult.error;
100
+ return null;
94
101
  }
95
- const clientPath = clientManifestResult.manifest[key]?.file;
102
+ const clientPath = clientManifest[key]?.file;
96
103
 
97
104
  if (!clientPath) {
98
- console.warn(`[vite-plugin-react-server] Could not find client path for ${value}. Ignoring.`)
99
- return null
105
+ console.warn(
106
+ `[vite-plugin-react-server] Could not find client path for ${value}. Ignoring.`
107
+ );
108
+ return null;
100
109
  }
101
110
  return {
102
111
  code: transformed.replace(key, clientPath),
@@ -1,19 +0,0 @@
1
- export interface ViteReactClientTransformOptions {
2
- projectRoot?: string;
3
- moduleId?: (path: string, ssr: boolean) => string;
4
- validateModuleId?: (moduleId: string) => boolean;
5
- include?: string | RegExp | (string | RegExp)[];
6
- exclude?: string | RegExp | (string | RegExp)[];
7
- }
8
-
9
- export interface TransformerOptions {
10
- moduleId: (path: string, ssr: boolean) => string;
11
- /**
12
- * Optional validation function for module IDs
13
- */
14
- validateModuleId?: (moduleId: string) => boolean;
15
- /**
16
- * The directory to use for the module IDs
17
- */
18
- moduleBase: string;
19
- }
package/plugin/types.ts CHANGED
@@ -1,5 +1,3 @@
1
- import type { ComponentType } from "react";
2
- import type { RenderToPipeableStreamOptions } from "react-dom/server";
3
1
  import type { PreRenderedChunk } from "rollup";
4
2
  import type { PreRenderedAsset } from "rollup";
5
3
  import type {
@@ -25,7 +23,7 @@ export type ResolvedUserConfig = Required<
25
23
  Pick<UserConfig, "root" | "mode" | "build" | "resolve">
26
24
  > &
27
25
  Omit<UserConfig, "root" | "mode" | "build" | "resolve"> & {
28
- resolve: {alias:AliasOptions} & ResolveOptions;
26
+ resolve: ResolveOptions;
29
27
  } & {
30
28
  build: NonNullable<
31
29
  Required<
@@ -67,7 +65,7 @@ export interface StreamPluginOptionsClient {
67
65
  cssFiles?: AliasOptions;
68
66
  }
69
67
 
70
- export type ResolvedUserOptions = Required<
68
+ export type ResolvedUserOptions<InlineCSS extends boolean = boolean> = Required<
71
69
  Pick<
72
70
  StreamPluginOptions,
73
71
  | "moduleBase"
@@ -78,10 +76,12 @@ export type ResolvedUserOptions = Required<
78
76
  | "Page"
79
77
  | "props"
80
78
  | "Html"
79
+ | "CssCollector"
81
80
  | "pageExportName"
82
81
  | "propsExportName"
83
82
  | "collectCss"
84
83
  | "collectAssets"
84
+ | "inlineCss"
85
85
  | "htmlWorkerPath"
86
86
  | "rscWorkerPath"
87
87
  | "loaderPath"
@@ -89,10 +89,9 @@ export type ResolvedUserOptions = Required<
89
89
  | "serverEntry"
90
90
  | "moduleBaseExceptions"
91
91
  | "pipableStreamOptions"
92
- | "moduleId"
93
92
  >
94
93
  > & {
95
- build: NonNullable<Required<StreamPluginOptions["build"]>>;
94
+ build: NonNullable<Required<StreamPluginOptions<InlineCSS>["build"]>>;
96
95
  autoDiscover: {
97
96
  modulePattern: (path: string) => boolean;
98
97
  cssPattern: (path: string) => boolean;
@@ -119,7 +118,7 @@ export type createBuildConfigFn<C extends "react-client" | "react-server"> =
119
118
  ? Promise<InlineConfig>
120
119
  : Promise<InlineConfig>;
121
120
 
122
- export interface StreamPluginOptions {
121
+ export interface StreamPluginOptions<InlineCSS extends boolean = boolean> {
123
122
  projectRoot?: string;
124
123
  moduleBase: string;
125
124
  moduleBasePath?: string;
@@ -167,23 +166,38 @@ export interface StreamPluginOptions {
167
166
  url: string;
168
167
  children: React.ReactNode;
169
168
  }>;
169
+ CssCollector?: InlineCSS extends true ? React.FC<React.PropsWithChildren<InlineCssCollectorProps>> : React.FC<React.PropsWithChildren<CssCollectorProps>>;
170
170
  collectCss?: boolean;
171
171
  collectAssets?: boolean;
172
+ inlineCss?: InlineCSS;
172
173
  build?: BuildConfig;
173
174
  moduleBaseExceptions?: string[];
174
175
  pipableStreamOptions?: PipeableStreamOptions;
175
- moduleId?: (id: string, ssr: boolean) => string;
176
176
  }
177
177
 
178
- export interface CreateHandlerOptions<T = any> {
178
+ export interface CreateHandlerOptions<T = any, InlineCSS extends boolean = boolean> {
179
+ root: string;
180
+ url: string;
181
+ route: string;
182
+ getCss: (id: string) => Promise<Map<string, string | CssContent>> | Map<string, string | CssContent>;
179
183
  loader: (id: string) => Promise<T>;
180
- clientManifest?: import("vite").Manifest;
181
- serverManifest?: import("vite").Manifest;
182
- moduleGraph?: import("vite").ModuleGraph;
183
- cssFiles?: string[];
184
+ Html: NonNullable<StreamPluginOptions['Html']>
185
+ CssCollector: InlineCSS extends true ? React.FC<React.PropsWithChildren<InlineCssCollectorProps>> : React.FC<React.PropsWithChildren<CssCollectorProps>>;
186
+ inlineCss: InlineCSS;
187
+ propsPath?: string;
188
+ pagePath?: string;
189
+ pageExportName: string
190
+ propsExportName: string
191
+ moduleBase: string
192
+ preserveModulesRoot?: boolean | undefined
193
+ moduleBasePath: string;
194
+ moduleRootPath: string;
195
+ moduleBaseURL: string;
196
+ cssFiles: (string | CssContent)[];
197
+ cssModules?: Map<string, string | CssContent> | undefined;
184
198
  onCssFile?: (path: string, parentUrl: string) => void;
185
- logger?: import("vite").Logger;
186
- pipableStreamOptions?: PipeableStreamOptions;
199
+ logger: import("vite").Logger;
200
+ pipableStreamOptions: PipeableStreamOptions;
187
201
  }
188
202
 
189
203
  export type ModuleLoader = (
@@ -245,7 +259,7 @@ export interface BuildOutput {
245
259
  }
246
260
 
247
261
  export interface BuildConfig {
248
- pages: string[] | (() => Promise<string[]> | string[]);
262
+ pages: string[] | (() => Promise<string[]> | string[]) | Promise<string[]>;
249
263
  assetsDir?: string;
250
264
  client?: string; // Output directory for client files
251
265
  server?: string; // Output directory for server files
@@ -359,3 +373,50 @@ export type HtmlProps = {
359
373
  url: string;
360
374
  cssFiles: string[];
361
375
  };
376
+
377
+ export interface PageAsset {
378
+ type: 'css' | 'js';
379
+ path: string;
380
+ parentUrl: string;
381
+ }
382
+
383
+ export interface PageData {
384
+ route: string;
385
+ clientComponents?: string[];
386
+ html?: {
387
+ raw: string;
388
+ transformed?: string;
389
+ assets: PageAsset[];
390
+ };
391
+ rsc?: {
392
+ content: string;
393
+ modules: Array<[string, string]>; // [modulePath, exportName]
394
+ };
395
+ }
396
+
397
+ export interface CssContent {
398
+ type?: string;
399
+ content: string;
400
+ key?: string;
401
+ path: string;
402
+ }
403
+
404
+ export interface InlineCssCollectorProps {
405
+ cssFiles: CssContent[];
406
+ root: string;
407
+ moduleBaseURL: string;
408
+ moduleBasePath: string;
409
+ moduleRootPath: string;
410
+ route: string;
411
+ children?: React.ReactNode;
412
+ }
413
+
414
+ export interface CssCollectorProps {
415
+ cssFiles: CssContent[];
416
+ root: string;
417
+ moduleBaseURL: string;
418
+ moduleBasePath: string;
419
+ moduleRootPath: string;
420
+ route: string;
421
+ children?: React.ReactNode;
422
+ }
@@ -1,7 +1,7 @@
1
1
  import { Worker, type ResourceLimits } from "node:worker_threads";
2
2
  import { getMode, getNodePath } from "../config/getPaths.js";
3
3
  import { getCondition } from "../config/getCondition.js";
4
- import { join } from "node:path";
4
+
5
5
  type CreateWorkerOptions = {
6
6
  projectRoot?: string;
7
7
  condition?: "react-server" | "react-client";
@@ -0,0 +1,63 @@
1
+ # HTML Worker
2
+
3
+ The HTML worker handles HTML generation and transformation as part of the server plugin (which runs under the `react-server` condition). Since the main thread is already in the correct condition for RSC, the HTML worker can work directly with RSC streams without needing a separate RSC worker.
4
+
5
+ The worker receives RSC streams directly from the main thread (which is running under `react-server` condition) and transforms them into HTML. This is different from the client plugin, which needs a separate RSC worker to handle server-condition tasks.
6
+
7
+ ## Extending the Worker
8
+
9
+ Users can create their own HTML workers for application-level use. This allows for:
10
+
11
+ 1. Custom HTML processing
12
+ 2. Specialized asset handling
13
+ 3. Custom build pipelines
14
+
15
+ Example of creating a custom HTML worker:
16
+
17
+ ```typescript
18
+ import { messageHandler } from 'vite-plugin-react-server/worker/html/messageHandler'
19
+ import type { HtmlWorkerMessage } from 'vite-plugin-react-server/worker/types'
20
+
21
+ // Create your custom message handler
22
+ const customMessageHandler = async (msg: HtmlWorkerMessage) => {
23
+ // Add your custom logic here
24
+ return messageHandler(msg)
25
+ }
26
+
27
+ // Initialize your worker
28
+ if (typeof WorkerGlobalScope !== 'undefined') {
29
+ parentPort.on('message', customMessageHandler)
30
+ }
31
+ ```
32
+
33
+ ## Messages
34
+ You have two options, either directly write the files from the worker or pass them back to the main thread through messages.
35
+
36
+ ```ts
37
+
38
+ ```
39
+
40
+ ## Client Dev Mode Integration
41
+
42
+ When running in client dev mode, you can use your custom HTML worker as part of your application:
43
+
44
+ 1. The worker runs in the client environment
45
+ 2. It can handle HTML transformations in real-time
46
+ 3. Provides immediate feedback during development
47
+ 4. Can be integrated with other development tools
48
+
49
+ ## Future Possibilities
50
+
51
+ The HTML worker architecture supports various potential enhancements:
52
+
53
+ - Custom HTML transformation pipelines
54
+ - Advanced asset optimization strategies
55
+ - Integration with other build tools
56
+ - Real-time HTML processing in development
57
+
58
+ ## Notes
59
+
60
+ - The worker must handle streaming HTML content
61
+ - Asset paths need to be properly resolved
62
+ - Consider memory usage when processing large HTML files
63
+ - Ensure proper coordination with the RSC worker