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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-react-server",
3
- "version": "0.3.18",
3
+ "version": "0.3.19",
4
4
  "description": "Vite plugin for React Server Components (RSC)",
5
5
  "type": "module",
6
6
  "main": "./dist/plugin/index.js",
@@ -91,8 +91,8 @@
91
91
  },
92
92
  "homepage": "https://github.com/nicobrinkkemper/vite-plugin-react-server#readme",
93
93
  "peerDependencies": {
94
- "react": "^0.0.0-experimental-d55cc79b-20250228",
95
- "react-dom": "^0.0.0-experimental-d55cc79b-20250228",
94
+ "react": "^0.0.0-experimental-f9d78089-20250306",
95
+ "react-dom": "^0.0.0-experimental-f9d78089-20250306",
96
96
  "vite": "*"
97
97
  },
98
98
  "peerDependenciesMeta": {
@@ -1,9 +1,10 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import type { CheckFilesExistReturn, ResolvedUserOptions } from "./types.js";
4
- import { normalizePath } from "vite";
5
4
  import { createInputNormalizer } from "./helpers/inputNormalizer.js";
6
5
 
6
+ let stashedFiles: CheckFilesExistReturn | null = null;
7
+
7
8
  const resolveFileOption = (pageOrProps: string | ((url: string) => string)) => {
8
9
  if (typeof pageOrProps === "string") {
9
10
  return () => pageOrProps;
@@ -16,6 +17,9 @@ export async function checkFilesExist(
16
17
  options: ResolvedUserOptions,
17
18
  root: string
18
19
  ): Promise<CheckFilesExistReturn> {
20
+ if(stashedFiles){
21
+ return stashedFiles;
22
+ }
19
23
  if (!root || root === "") {
20
24
  throw new Error("Root not found");
21
25
  }
@@ -57,6 +61,6 @@ export async function checkFilesExist(
57
61
  pageMap.set(pageKey, pageValue);
58
62
  propsMap.set(propsKey, propsValue);
59
63
  }
60
-
61
- return { pageMap, pageSet, propsMap, propsSet, urlMap, errors };
64
+ stashedFiles = { pageMap, pageSet, propsMap, propsSet, urlMap, errors };
65
+ return stashedFiles;
62
66
  }
@@ -0,0 +1,152 @@
1
+ import type { Manifest, ModuleGraph } from "vite";
2
+ import { createInputNormalizer } from "./helpers/inputNormalizer.js";
3
+ import { DEFAULT_CONFIG } from "./config/defaults.js";
4
+
5
+ export async function collectModuleGraphCss({
6
+ moduleGraph,
7
+ pagePath,
8
+ onCss,
9
+ parentUrl,
10
+ }: {
11
+ moduleGraph: ModuleGraph;
12
+ pagePath: string;
13
+ onCss?: (path: string, parentUrl: string) => void;
14
+ parentUrl?: string;
15
+ }) {
16
+ if (!pagePath) return new Map<string, string>();
17
+
18
+ const cssFiles = new Map<string, string>();
19
+ const pageModule = await moduleGraph.getModuleByUrl(pagePath, true);
20
+ if (!pageModule) {
21
+ return new Map<string, string>();
22
+ }
23
+ const seen = new Set<string>();
24
+ const walkModule = (mod: any) => {
25
+ if (!mod?.id || seen.has(mod.id)) return;
26
+ seen.add(mod.id);
27
+ if (mod?.id?.endsWith(".css")) {
28
+ cssFiles.set(mod?.url, mod?.id);
29
+ onCss?.(mod?.url, parentUrl ?? pagePath);
30
+ }
31
+ mod?.importedModules?.forEach((imp: any) => walkModule(imp));
32
+ };
33
+ walkModule(pageModule);
34
+ return cssFiles;
35
+ }
36
+
37
+ export function collectManifestClientFiles({
38
+ manifest,
39
+ root,
40
+ pagePath,
41
+ preserveModulesRoot,
42
+ moduleBase,
43
+ onCss,
44
+ onClientModule,
45
+ testClient = DEFAULT_CONFIG.AUTO_DISCOVER.clientComponents,
46
+ testJson = DEFAULT_CONFIG.AUTO_DISCOVER.jsonPattern,
47
+ }: {
48
+ manifest: Manifest;
49
+ root: string;
50
+ pagePath: string;
51
+ preserveModulesRoot?: boolean;
52
+ moduleBase?: string;
53
+ onCss?: (path: string, parentUrl: string) => void;
54
+ onClientModule?: (path: string, parentUrl: string) => void;
55
+ parentUrl?: string;
56
+ testClient?: (id: string) => boolean;
57
+ testJson?: (id: string) => boolean;
58
+ }) {
59
+ const normalizer = createInputNormalizer({
60
+ root,
61
+ removeExtension: true,
62
+ preserveModulesRoot: preserveModulesRoot ? moduleBase : undefined,
63
+ });
64
+ const [_, value] = normalizer(pagePath);
65
+
66
+ const cssFiles = new Map<string, string>();
67
+ const clientFiles = new Map<string, string>();
68
+ const seen = new Set<string>();
69
+ const manifestValues = Object.values(manifest);
70
+
71
+ // Try different variations of the path
72
+ const possibleKeys = [
73
+ value, // Relative path
74
+ ];
75
+
76
+ const walkManifestEntry = (id: string, parentUrl: string) => {
77
+ if (seen.has(id)) return;
78
+ seen.add(id);
79
+
80
+ // Get the manifest entry
81
+ const entry = manifest[id] ?? manifestValues.find((e) => id === e.file);
82
+ if (!entry) {
83
+ console.log(
84
+ `No manifest entry found for ${id}, possible keys: ${Object.keys(
85
+ manifest
86
+ ).join(", ")}`
87
+ );
88
+ return;
89
+ }
90
+ if (
91
+ (typeof testClient === "function" &&
92
+ typeof onClientModule === "function" &&
93
+ testClient(entry.file)) ||
94
+ (typeof testJson === "function" && testJson(entry.file))
95
+ ) {
96
+ onClientModule?.(entry.file ?? "", parentUrl);
97
+ clientFiles.set(id, entry.name ?? "");
98
+ }
99
+
100
+ // Add direct CSS from the css array
101
+ if (entry.css) {
102
+ entry.css.forEach((css: string) => {
103
+ cssFiles.set(css, css);
104
+ onCss?.(css, id);
105
+ onClientModule?.(css, id);
106
+ });
107
+ }
108
+
109
+ // Walk imports recursively
110
+ if (entry.imports) {
111
+ entry.imports.forEach((imp: string) =>
112
+ walkManifestEntry(imp, entry.file)
113
+ );
114
+ }
115
+
116
+ // Also check dynamicImports
117
+ if (entry.dynamicImports) {
118
+ entry.dynamicImports.forEach((imp: string) =>
119
+ walkManifestEntry(imp, entry.file)
120
+ );
121
+ }
122
+ };
123
+
124
+ // Try all possible keys
125
+ for (const possibleKey of possibleKeys) {
126
+ if (manifest[possibleKey]) {
127
+ walkManifestEntry(possibleKey, pagePath);
128
+ break;
129
+ }
130
+ }
131
+
132
+ // If no entry found by key, try matching by file
133
+ if (cssFiles.size === 0) {
134
+ const entry = manifestValues.find(
135
+ (e) =>
136
+ possibleKeys.includes(e.file) ||
137
+ (e.src && possibleKeys.includes(e.src)) ||
138
+ (e.name && possibleKeys.includes(e.name))
139
+ );
140
+ if (entry) {
141
+ walkManifestEntry(value, pagePath);
142
+ } else {
143
+ console.warn(
144
+ `No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(
145
+ ", "
146
+ )})`
147
+ );
148
+ }
149
+ }
150
+
151
+ return { cssFiles, clientFiles };
152
+ }
@@ -1,14 +1,59 @@
1
- import { createElement } from 'react';
2
-
1
+ import React from "react";
3
2
  /**
4
3
  * A component that emits <link> tags for CSS files during streaming.
5
4
  * The high precedence ensures they bubble up to the document head.
6
5
  */
7
- export function CssCollector({ url, moduleBasePath }: { url: string, moduleBasePath: string }) {
8
- return createElement('link', {
9
- key: url,
10
- rel: 'stylesheet',
11
- href: url,
12
- precedence: 'high'
13
- });
14
- }
6
+ export function CssCollector({
7
+ children,
8
+ cssFiles,
9
+ moduleBaseUrl,
10
+ route = "/"
11
+ }: {
12
+ children?: React.ReactNode;
13
+ cssFiles: string[];
14
+ moduleBaseUrl?: string;
15
+ route?: string;
16
+ }) {
17
+ // Calculate depth and prefix based on route
18
+ const depth = route.split('/').filter(Boolean).length ;
19
+ const prefix = depth > 0 ? '../'.repeat(depth) : './';
20
+ const base = typeof moduleBaseUrl === 'string' && moduleBaseUrl !== '' ? moduleBaseUrl : prefix;
21
+
22
+ return React.createElement(
23
+ React.Fragment,
24
+ null,
25
+ ...cssFiles.map((css) => {
26
+ try {
27
+ if(moduleBaseUrl) {
28
+ new URL(css, moduleBaseUrl);
29
+ } else {
30
+ new URL(`file://${base}${css}`);
31
+ }
32
+ } catch (error) {
33
+ return React.createElement('style', {type: 'text/css'},
34
+ css
35
+ );
36
+ }
37
+ // Handle different types of paths
38
+ let url = css;
39
+ if (css.startsWith('http') || css.startsWith('data:')) {
40
+ // Keep absolute URLs as is
41
+ url = css;
42
+ } else if (css.startsWith('/')) {
43
+ // Convert absolute paths to relative
44
+ url = base + css.slice(1);
45
+ } else if (!css.startsWith('./') && !css.startsWith('../')) {
46
+ // Add prefix to relative paths that don't start with ./ or ../
47
+ url = base + css;
48
+ }
49
+
50
+ return React.createElement("link", {
51
+ key: css,
52
+ rel: "stylesheet",
53
+ href: url,
54
+ precedence: "high",
55
+ });
56
+ }),
57
+ children
58
+ );
59
+ }
@@ -0,0 +1,69 @@
1
+ import React from "react";
2
+ export const DEFAULT_CONFIG = {
3
+ FILE_REGEX: /\.(m|c)?(j|t)sx?$/,
4
+ CLIENT_ASSETS_DIR: "assets",
5
+ RSC_DIR: "rsc",
6
+ MODULE_BASE: "src",
7
+ MODULE_BASE_PATH: "",
8
+ MODULE_BASE_URL: "",
9
+ PAGE: "src/page/page.tsx",
10
+ PROPS: "src/page/props.ts",
11
+ CLIENT_ENTRY: "src/client.tsx",
12
+ SERVER_ENTRY: "src/server.tsx",
13
+ PAGE_EXPORT_NAME: "Page",
14
+ PROPS_EXPORT_NAME: "props",
15
+ HTML_WORKER_PATH: `worker/html/html-worker.${
16
+ process.env["NODE_ENV"] === "development" ? "development" : "production"
17
+ }.js`,
18
+ RSC_WORKER_PATH: `worker/rsc/rsc-worker.${
19
+ process.env["NODE_ENV"] === "development" ? "development" : "production"
20
+ }.js`,
21
+ LOADER_PATH: "worker/loader.js",
22
+ RSC_EXTENSION: ".rsc",
23
+ HTML: ({ children }: { children: any }) => (
24
+ <html>
25
+ <head></head>
26
+ <body>
27
+ <div id="root">{children}</div>
28
+ </body>
29
+ </html>
30
+ ),
31
+ COLLECT_CSS: true,
32
+ COLLECT_ASSETS: true,
33
+ DEV_PORT: 5173,
34
+ PREVIEW_PORT: 4173,
35
+ DEV_HOST: "localhost",
36
+ PREVIEW_HOST: "localhost",
37
+ ENV_PREFIX: "VITE_",
38
+ BUILD: {
39
+ pages: () => ["/"],
40
+ client: "client",
41
+ server: "server",
42
+ static: "static",
43
+ api: "api",
44
+ outDir: "dist",
45
+ assetsDir: "assets",
46
+ hash: "hash",
47
+ preserveModulesRoot: true,
48
+ },
49
+ MODULE_BASE_EXCEPTIONS: [] as string[],
50
+ AUTO_DISCOVER: {
51
+ modulePattern: (n: string) => DEFAULT_CONFIG.FILE_REGEX.test(n),
52
+ pagePattern: (n: string) =>
53
+ n.toLowerCase().endsWith("/page") || n.toLowerCase() === "page",
54
+ propsPattern: (n: string) =>
55
+ n.toLowerCase().endsWith("/props") || n.toLowerCase() === "props",
56
+ clientComponents: (n: string) =>
57
+ n.toLowerCase().endsWith(".client") || n.toLowerCase() === "client",
58
+ serverFunctions: (n: string) =>
59
+ n.toLowerCase().endsWith(".server") || n.toLowerCase() === "server",
60
+ cssPattern: (n: string) => n.toLowerCase().endsWith(".css"),
61
+ cssModulePattern: (n: string) => n.toLowerCase().endsWith(".css.js"),
62
+ vendorPattern: (n: string) =>
63
+ n.toLowerCase().startsWith("node_modules") ||
64
+ n.toLowerCase().startsWith("_virtual"),
65
+ htmlPattern: (n: string) => n.toLowerCase().endsWith(".html"),
66
+ jsonPattern: (n: string) => n.toLowerCase().endsWith(".json"),
67
+ },
68
+ MODULE_ID: (id: string) => id,
69
+ } as const;
@@ -1,15 +1,9 @@
1
- import { join, dirname } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
1
+ import { join } from 'node:path';
3
2
 
4
3
  export const getNodePath = (root: string = process.cwd()): string => {
5
4
  return process.env['module_root'] ?? join(root, "node_modules");
6
5
  }
7
6
 
8
- export const getPluginRoot = (): string => {
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
- return join(__dirname, '..');
11
- }
12
-
13
7
  export const getMode = (): "production" | "development" | "test" => {
14
8
  return process.env['NODE_ENV'] === "development"
15
9
  ? "development"
@@ -0,0 +1,17 @@
1
+
2
+ export const MIME_TYPES: Record<string, string> = {
3
+ '.html': 'text/html',
4
+ '.css': 'text/css',
5
+ '.js': 'application/javascript',
6
+ '.json': 'application/json',
7
+ '.png': 'image/png',
8
+ '.jpg': 'image/jpeg',
9
+ '.jpeg': 'image/jpeg',
10
+ '.gif': 'image/gif',
11
+ '.svg': 'image/svg+xml',
12
+ '.ico': 'image/x-icon',
13
+ '.woff': 'font/woff',
14
+ '.woff2': 'font/woff2',
15
+ '.ttf': 'font/ttf',
16
+ '.rsc': 'text/x-component'
17
+ };
@@ -2,8 +2,8 @@ import type { PreRenderedAsset } from "rollup";
2
2
  import type { PreRenderedChunk } from "rollup";
3
3
  import type { StreamPluginOptions, ResolvedUserOptions } from "../types.js";
4
4
  import { DEFAULT_CONFIG } from "./defaults.js";
5
- import { createModuleIdGenerator } from "./createModuleIdGenerator.js";
6
- import { normalizePath } from "vite";
5
+ import { join } from "node:path";
6
+ import { pluginRoot } from "../root.js";
7
7
 
8
8
  const resolveAutoDiscoverMatcher = (
9
9
  options: undefined | string | RegExp | ((path: string) => boolean),
@@ -45,8 +45,8 @@ const handleSearchQuery = (path: string) => {
45
45
 
46
46
  const applyPattern = (
47
47
  path: string,
48
- pattern?: string | RegExp | ((path: string) => boolean) | undefined,
49
- fallback?: string | undefined
48
+ _pattern?: string | RegExp | ((path: string) => boolean) | undefined,
49
+ _fallback?: string | undefined
50
50
  ) => {
51
51
  // TODO: What to actually do here? I guess we could replace the extension, but it's not needed since we map them from the manifest anyway.
52
52
  return path;
@@ -54,7 +54,7 @@ const applyPattern = (
54
54
 
55
55
  export const resolveOptions = (
56
56
  options: StreamPluginOptions,
57
- isClient: boolean = false
57
+ isClient: boolean
58
58
  ):
59
59
  | { type: "success"; userOptions: ResolvedUserOptions }
60
60
  | { type: "error"; error: Error } => {
@@ -149,7 +149,9 @@ export const resolveOptions = (
149
149
  const hashString = hashOption === "" ? "" : `-[${hashOption}]`;
150
150
  const hash = (n: string | null) => {
151
151
  if (!n) return "";
152
- if (hashString === "") return n;
152
+ if (hashString === "" || ( !isClient && !n.endsWith('.css') && !n.endsWith('.json') ) ) {
153
+ return n;
154
+ }
153
155
  const extensionIndex = n.lastIndexOf(".");
154
156
  if (extensionIndex !== -1) {
155
157
  // put hash between extension and filename
@@ -172,19 +174,27 @@ export const resolveOptions = (
172
174
  if (testVendor(path)) {
173
175
  return path;
174
176
  }
175
-
177
+
176
178
  if (testCssModule(path)) {
177
179
  // For CSS modules, keep the .css.js extension
178
- return applyPattern(path, options.autoDiscover?.cssModulePattern, ".css.js");
180
+ return applyPattern(
181
+ path,
182
+ options.autoDiscover?.cssModulePattern,
183
+ ".css.js"
184
+ );
179
185
  }
180
-
186
+
181
187
  if (testCss(path)) {
182
188
  // For regular CSS files, keep the .css extension
183
189
  return applyPattern(path, options.autoDiscover?.cssPattern, ".css");
184
190
  }
185
191
 
186
192
  if (testClientComponents(path)) {
187
- return applyPattern(path, options.autoDiscover?.clientComponents, "client");
193
+ return applyPattern(
194
+ path,
195
+ options.autoDiscover?.clientComponents,
196
+ "client"
197
+ );
188
198
  }
189
199
  if (testHtml(path)) {
190
200
  return applyPattern(path, options.autoDiscover?.htmlPattern, ".html");
@@ -209,7 +219,11 @@ export const resolveOptions = (
209
219
  );
210
220
  }
211
221
  if (testServerFunctions(path)) {
212
- return applyPattern(path, options.autoDiscover?.serverFunctions, "server");
222
+ return applyPattern(
223
+ path,
224
+ options.autoDiscover?.serverFunctions,
225
+ "server"
226
+ );
213
227
  }
214
228
  if (testModulePattern(path)) {
215
229
  return path;
@@ -220,23 +234,23 @@ export const resolveOptions = (
220
234
  const entryFile = (n: PreRenderedChunk) => {
221
235
  if (testVendor(n.name)) {
222
236
  const search = n.facadeModuleId?.split("?")[1];
223
- if(search) {
224
- return `${n.name}.${search}.js`;
237
+ if (search) {
238
+ return hash(`${n.name}.${search}.js`);
225
239
  } else {
226
- return n.name + ".js";
240
+ return hash(`${n.name}.js`);
227
241
  }
228
242
  }
229
- return addJS(getOutputPath(ensureModuleBase(ensureNoRoot(n.name))));
243
+ return hash(addJS(getOutputPath(ensureModuleBase(ensureNoRoot(n.name)))));
230
244
  };
231
245
 
232
246
  const chunkFile = (n: PreRenderedChunk) => {
233
247
  // For chunks, we always want .js
234
- return addJS(getOutputPath(ensureModuleBase(ensureNoRoot('_'+n.name))));
248
+ return hash(addJS(getOutputPath(ensureModuleBase(ensureNoRoot("_" + n.name)))));
235
249
  };
236
250
 
237
251
  const assetFile = (n: PreRenderedAsset) => {
238
252
  // For assets, keep the original extension
239
- return getOutputPath(ensureModuleBase(ensureNoRoot(n.names[0])));
253
+ return hash(getOutputPath(ensureModuleBase(ensureNoRoot(n.names[0]))));
240
254
  };
241
255
 
242
256
  const build =
@@ -286,13 +300,23 @@ export const resolveOptions = (
286
300
  const moduleBasePath =
287
301
  typeof options.moduleBasePath === "string"
288
302
  ? options.moduleBasePath
289
- : options.moduleBase.startsWith("/")
290
- ? options.moduleBase
291
- : "/" + options.moduleBase;
303
+ : DEFAULT_CONFIG.MODULE_BASE_PATH;
292
304
  const moduleBaseURL =
293
305
  typeof options.moduleBaseURL === "string"
294
306
  ? options.moduleBaseURL
295
- : moduleBasePath ?? DEFAULT_CONFIG.MODULE_BASE_URL;
307
+ : DEFAULT_CONFIG.MODULE_BASE_URL;
308
+ const rscWorkerPath =
309
+ typeof options.rscWorkerPath === "string"
310
+ ? join(projectRoot, options.rscWorkerPath)
311
+ : join(pluginRoot, DEFAULT_CONFIG.RSC_WORKER_PATH);
312
+ const htmlWorkerPath =
313
+ typeof options.htmlWorkerPath === "string"
314
+ ? join(projectRoot, options.htmlWorkerPath)
315
+ : join(pluginRoot, DEFAULT_CONFIG.HTML_WORKER_PATH);
316
+ const loaderPath =
317
+ typeof options.loaderPath === "string"
318
+ ? join(projectRoot, options.loaderPath)
319
+ : join(pluginRoot, DEFAULT_CONFIG.LOADER_PATH);
296
320
 
297
321
  const autoDiscover = {
298
322
  modulePattern: testModulePattern,
@@ -306,26 +330,11 @@ export const resolveOptions = (
306
330
  vendorPattern: testVendor,
307
331
  };
308
332
 
309
- const moduleId =
310
- typeof options.moduleId === "function"
311
- ? options.moduleId
312
- : createModuleIdGenerator({
313
- isProduction: process.env["NODE_ENV"] === "production",
314
- inputRoot: projectRoot,
315
- client: client,
316
- server: server,
317
- moduleBase: moduleBase,
318
- preserveModulesRoot: preserveModulesRoot,
319
- removeExtension: DEFAULT_CONFIG.FILE_REGEX,
320
- imports: {},
321
- });
322
-
323
333
  try {
324
334
  return {
325
335
  type: "success",
326
336
  userOptions: {
327
337
  projectRoot,
328
- moduleId: moduleId,
329
338
  moduleBase,
330
339
  moduleBasePath,
331
340
  moduleBaseURL,
@@ -337,10 +346,9 @@ export const resolveOptions = (
337
346
  propsExportName: propsExportName,
338
347
  collectCss: options.collectCss ?? DEFAULT_CONFIG.COLLECT_CSS,
339
348
  collectAssets: options.collectAssets ?? DEFAULT_CONFIG.COLLECT_ASSETS,
340
- htmlWorkerPath:
341
- options.htmlWorkerPath ?? DEFAULT_CONFIG.HTML_WORKER_PATH,
342
- rscWorkerPath: options.rscWorkerPath ?? DEFAULT_CONFIG.RSC_WORKER_PATH,
343
- loaderPath: options.loaderPath ?? DEFAULT_CONFIG.LOADER_PATH,
349
+ htmlWorkerPath: htmlWorkerPath,
350
+ rscWorkerPath: rscWorkerPath,
351
+ loaderPath: loaderPath,
344
352
  clientEntry: options.clientEntry ?? DEFAULT_CONFIG.CLIENT_ENTRY,
345
353
  serverEntry: options.serverEntry ?? DEFAULT_CONFIG.SERVER_ENTRY,
346
354
  moduleBaseExceptions: options.moduleBaseExceptions ?? [],
@@ -1,8 +1,12 @@
1
1
  import type { ResolvedUserOptions } from '../types.js';
2
2
 
3
+ export let stashedPages: string[] = [];
3
4
  export async function resolvePages(
4
5
  pages: ResolvedUserOptions["build"]["pages"]
5
6
  ): Promise<{ type: "success"; error?:never; pages: string[] } | { type: "error"; error: Error; pages?:never }> {
7
+ if(stashedPages.length > 0){
8
+ return { type: "success", pages: stashedPages };
9
+ }
6
10
  if (!pages) {
7
11
  return { type: "success", pages: [] };
8
12
  }
@@ -10,24 +14,24 @@ export async function resolvePages(
10
14
  try {
11
15
  // Handle function
12
16
  if (typeof pages === "function") {
13
- const result = await Promise.resolve(pages());
14
- return resolvePages(result);
17
+ return resolvePages(pages());
15
18
  }
16
19
 
17
20
  // Handle Promise
18
21
  if (pages instanceof Promise) {
19
- const result = await pages;
20
- return resolvePages(result);
22
+ return resolvePages(await pages);
21
23
  }
22
24
 
23
25
  // Handle string
24
26
  if (typeof pages === "string") {
27
+ stashedPages = [pages];
25
28
  return { type: "success", pages: [pages] };
26
29
  }
27
30
 
28
31
  // Handle array
29
32
  if (Array.isArray(pages)) {
30
33
  if (pages.every(page => typeof page === "string")) {
34
+ stashedPages = pages;
31
35
  return { type: "success", pages };
32
36
  }
33
37
  throw new Error('All pages must be strings');