vite-plugin-react-server 1.1.7 → 1.1.8

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 (143) hide show
  1. package/dist/package.json +10 -5
  2. package/dist/plugin/config/defaults.d.ts +1 -1
  3. package/dist/plugin/config/defaults.js +1 -1
  4. package/dist/plugin/config/defaults.js.map +1 -1
  5. package/dist/plugin/config/resolveAutoDiscover.d.ts +2 -0
  6. package/dist/plugin/config/resolveAutoDiscover.d.ts.map +1 -1
  7. package/dist/plugin/config/resolveAutoDiscover.js +15 -18
  8. package/dist/plugin/config/resolveAutoDiscover.js.map +1 -1
  9. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  10. package/dist/plugin/config/resolveOptions.js +4 -1
  11. package/dist/plugin/config/resolveOptions.js.map +1 -1
  12. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  13. package/dist/plugin/config/resolveUserConfig.js +56 -29
  14. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  15. package/dist/plugin/helpers/collectBundleManifestCss.d.ts +0 -6
  16. package/dist/plugin/helpers/collectBundleManifestCss.d.ts.map +1 -1
  17. package/dist/plugin/helpers/collectBundleManifestCss.js +2 -110
  18. package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts +2 -1
  19. package/dist/plugin/helpers/collectViteModuleGraphCss.d.ts.map +1 -1
  20. package/dist/plugin/helpers/collectViteModuleGraphCss.js +19 -18
  21. package/dist/plugin/helpers/collectViteModuleGraphCss.js.map +1 -1
  22. package/dist/plugin/helpers/createCssProps.d.ts +3 -2
  23. package/dist/plugin/helpers/createCssProps.d.ts.map +1 -1
  24. package/dist/plugin/helpers/createCssProps.js +10 -6
  25. package/dist/plugin/helpers/createCssProps.js.map +1 -1
  26. package/dist/plugin/helpers/createRscStream.d.ts.map +1 -1
  27. package/dist/plugin/helpers/createRscStream.js +37 -43
  28. package/dist/plugin/helpers/createRscStream.js.map +1 -1
  29. package/dist/plugin/helpers/formatMetrics.d.ts +4 -0
  30. package/dist/plugin/helpers/formatMetrics.d.ts.map +1 -0
  31. package/dist/plugin/helpers/formatMetrics.js +24 -0
  32. package/dist/plugin/helpers/tryManifest.d.ts.map +1 -1
  33. package/dist/plugin/helpers/tryManifest.js +0 -8
  34. package/dist/plugin/helpers/tryManifest.js.map +1 -1
  35. package/dist/plugin/html.js +1 -1
  36. package/dist/plugin/html.js.map +1 -1
  37. package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
  38. package/dist/plugin/loader/createBuildLoader.js +2 -0
  39. package/dist/plugin/loader/createBuildLoader.js.map +1 -1
  40. package/dist/plugin/metrics/formatMetrics.d.ts +4 -0
  41. package/dist/plugin/metrics/formatMetrics.d.ts.map +1 -0
  42. package/dist/plugin/metrics/formatMetrics.js +39 -0
  43. package/dist/plugin/metrics/formatMetrics.js.map +1 -0
  44. package/dist/plugin/metrics/index.d.ts +3 -0
  45. package/dist/plugin/metrics/index.d.ts.map +1 -0
  46. package/dist/plugin/metrics/index.js +1 -0
  47. package/dist/plugin/metrics.js +7 -0
  48. package/dist/plugin/metrics.js.map +1 -0
  49. package/dist/plugin/react-client/createWorkerStream.d.ts +16 -0
  50. package/dist/plugin/react-client/createWorkerStream.d.ts.map +1 -0
  51. package/dist/plugin/react-client/createWorkerStream.js +88 -0
  52. package/dist/plugin/react-client/createWorkerStream.js.map +1 -0
  53. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  54. package/dist/plugin/react-client/plugin.js +4 -1
  55. package/dist/plugin/react-client/plugin.js.map +1 -1
  56. package/dist/plugin/react-client/restartWorker.d.ts +6 -0
  57. package/dist/plugin/react-client/restartWorker.d.ts.map +1 -0
  58. package/dist/plugin/react-client/restartWorker.js +53 -0
  59. package/dist/plugin/react-client/restartWorker.js.map +1 -0
  60. package/dist/plugin/react-client/server.d.ts +5 -4
  61. package/dist/plugin/react-client/server.d.ts.map +1 -1
  62. package/dist/plugin/react-client/server.js +79 -110
  63. package/dist/plugin/react-client/server.js.map +1 -1
  64. package/dist/plugin/react-server/server.d.ts.map +1 -1
  65. package/dist/plugin/react-server/server.js +23 -28
  66. package/dist/plugin/react-server/server.js.map +1 -1
  67. package/dist/plugin/react-static/collectHtmlWorkerContent.js +1 -1
  68. package/dist/plugin/react-static/collectHtmlWorkerContent.js.map +1 -1
  69. package/dist/plugin/react-static/collectRscContent.js +1 -1
  70. package/dist/plugin/react-static/collectRscContent.js.map +1 -1
  71. package/dist/plugin/react-static/configurePreviewServer.d.ts.map +1 -1
  72. package/dist/plugin/react-static/configurePreviewServer.js +23 -4
  73. package/dist/plugin/react-static/configurePreviewServer.js.map +1 -1
  74. package/dist/plugin/react-static/fileWriter.d.ts.map +1 -1
  75. package/dist/plugin/react-static/fileWriter.js +5 -1
  76. package/dist/plugin/react-static/fileWriter.js.map +1 -1
  77. package/dist/plugin/react-static/plugin.d.ts.map +1 -1
  78. package/dist/plugin/react-static/plugin.js +50 -33
  79. package/dist/plugin/react-static/plugin.js.map +1 -1
  80. package/dist/plugin/types.d.ts +6 -7
  81. package/dist/plugin/types.d.ts.map +1 -1
  82. package/dist/plugin/utils/callServer.d.ts +2 -0
  83. package/dist/plugin/utils/callServer.d.ts.map +1 -0
  84. package/dist/plugin/utils/callServer.js +26 -0
  85. package/dist/plugin/utils/callServer.js.map +1 -0
  86. package/dist/plugin/utils/createReactFetcher.d.ts +7 -0
  87. package/dist/plugin/utils/createReactFetcher.d.ts.map +1 -0
  88. package/dist/plugin/utils/createReactFetcher.js +33 -0
  89. package/dist/plugin/utils/createReactFetcher.js.map +1 -0
  90. package/dist/plugin/utils/index.d.ts +4 -0
  91. package/dist/plugin/utils/index.d.ts.map +1 -0
  92. package/dist/plugin/utils/index.js +3 -0
  93. package/dist/plugin/utils/pageURL.d.ts +2 -0
  94. package/dist/plugin/utils/pageURL.d.ts.map +1 -0
  95. package/dist/plugin/utils/pageURL.js +21 -0
  96. package/dist/plugin/utils/pageURL.js.map +1 -0
  97. package/dist/plugin/utils.js +9 -0
  98. package/dist/plugin/utils.js.map +1 -0
  99. package/dist/plugin/worker/rsc/handleRender.d.ts +6 -2
  100. package/dist/plugin/worker/rsc/handleRender.d.ts.map +1 -1
  101. package/dist/plugin/worker/rsc/handleRender.js +26 -55
  102. package/dist/plugin/worker/rsc/handleRender.js.map +1 -1
  103. package/dist/plugin/worker/rsc/messageHandler.d.ts +1 -2
  104. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
  105. package/dist/plugin/worker/rsc/messageHandler.js +45 -2
  106. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
  107. package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
  108. package/dist/plugin/worker/rsc/state.js +1 -5
  109. package/dist/plugin/worker/rsc/state.js.map +1 -1
  110. package/dist/tsconfig.tsbuildinfo +1 -1
  111. package/package.json +10 -5
  112. package/plugin/config/defaults.tsx +1 -1
  113. package/plugin/config/resolveAutoDiscover.ts +17 -22
  114. package/plugin/config/resolveOptions.ts +5 -1
  115. package/plugin/config/resolveUserConfig.ts +64 -36
  116. package/plugin/helpers/collectBundleManifestCss.ts +1 -160
  117. package/plugin/helpers/collectViteModuleGraphCss.ts +31 -29
  118. package/plugin/helpers/createCssProps.tsx +22 -11
  119. package/plugin/helpers/createRscStream.tsx +42 -46
  120. package/plugin/helpers/formatMetrics.ts +37 -0
  121. package/plugin/helpers/tryManifest.ts +0 -9
  122. package/plugin/html.tsx +1 -1
  123. package/plugin/loader/createBuildLoader.ts +2 -0
  124. package/plugin/metrics/formatMetrics.ts +37 -0
  125. package/plugin/metrics/index.ts +2 -0
  126. package/plugin/react-client/createWorkerStream.ts +107 -0
  127. package/plugin/react-client/plugin.ts +3 -0
  128. package/plugin/react-client/restartWorker.ts +65 -0
  129. package/plugin/react-client/server.ts +97 -146
  130. package/plugin/react-server/server.ts +24 -29
  131. package/plugin/react-static/collectHtmlWorkerContent.ts +1 -1
  132. package/plugin/react-static/collectRscContent.ts +2 -2
  133. package/plugin/react-static/configurePreviewServer.ts +29 -6
  134. package/plugin/react-static/fileWriter.ts +5 -1
  135. package/plugin/react-static/plugin.ts +58 -38
  136. package/plugin/types.ts +11 -11
  137. package/plugin/utils/callServer.ts +25 -0
  138. package/plugin/utils/createReactFetcher.ts +31 -0
  139. package/plugin/utils/index.ts +3 -0
  140. package/plugin/utils/pageURL.ts +28 -0
  141. package/plugin/worker/rsc/handleRender.ts +33 -71
  142. package/plugin/worker/rsc/messageHandler.tsx +48 -6
  143. package/plugin/worker/rsc/state.ts +1 -5
@@ -5,7 +5,7 @@ import type {
5
5
  AutoDiscoveredFiles,
6
6
  } from "../types.js";
7
7
  import { join } from "node:path";
8
- import type { OutputOptions } from "rollup";
8
+ import type { OutputOptions, PreRenderedAsset, PreRenderedChunk } from "rollup";
9
9
 
10
10
  let stashedUserConfig: Record<string, ResolvedUserConfig | null> = {};
11
11
 
@@ -49,30 +49,49 @@ export function resolveUserConfig({
49
49
 
50
50
  // Get existing inputs
51
51
  const root = config.root ?? userOptions.projectRoot ?? process.cwd();
52
- const staticEntries =
53
- ssr && autoDiscoveredFiles.staticManifest
54
- ? Object.entries(autoDiscoveredFiles.staticManifest)
55
- : [];
52
+
53
+ const handleSsrName = <T extends PreRenderedChunk | PreRenderedAsset>(
54
+ info: T,
55
+ input: string | null,
56
+ fallback: (info: T, ssr: boolean) => string,
57
+ ssr: boolean
58
+ ) => {
59
+ if (!ssr || !input) {
60
+ return fallback(info, false);
61
+ }
62
+ const [, value] = userOptions.normalizer(
63
+ input
64
+ );
65
+ const entry = autoDiscoveredFiles.staticManifest[value];
66
+ if(entry?.name && info.type === 'asset' && userOptions.autoDiscover.cssPattern(value)) {
67
+ const withoutExt = entry.name?.split('.')[0]
68
+ const found = entry.css?.find(css => css.startsWith(withoutExt as string))
69
+ if(found) {
70
+ return found
71
+ } else {
72
+ return entry.file
73
+ }
74
+ }
75
+ if (entry) {
76
+ return entry.file
77
+ }
78
+ return fallback(info, true);
79
+ };
56
80
  const pluginOutput = {
57
81
  preserveModulesRoot: userOptions.build.preserveModulesRoot
58
82
  ? userOptions.moduleBase
59
83
  : undefined,
60
84
  entryFileNames: (info) => {
61
- if (ssr) {
62
- const entry = staticEntries.find(([, { file }]) =>
63
- file.startsWith(info.name)
64
- );
65
- if (entry) {
66
- return entry[1].file;
67
- }
68
- }
69
- return userOptions.build.entryFile(info, ssr);
85
+ const input = info.facadeModuleId
86
+ return handleSsrName(info, input, userOptions.build.entryFile, ssr);
70
87
  },
71
88
  assetFileNames: (i) => {
72
- return userOptions.build.assetFile(i, false);
89
+ const input = i.originalFileNames[0]
90
+ return handleSsrName(i, input, userOptions.build.assetFile, ssr);
73
91
  },
74
92
  chunkFileNames: (i) => {
75
- return userOptions.build.chunkFile(i, ssr);
93
+ const input = i.facadeModuleId
94
+ return handleSsrName(i, input, userOptions.build.chunkFile, ssr);
76
95
  },
77
96
  format: "esm",
78
97
  exports: "named",
@@ -84,6 +103,7 @@ export function resolveUserConfig({
84
103
  config.build?.rollupOptions?.output !== null
85
104
  ? [config.build?.rollupOptions?.output, pluginOutput]
86
105
  : pluginOutput;
106
+ const vitePrefix = config.envPrefix ?? "VITE_";
87
107
  const mode =
88
108
  process.env["NODE_ENV"] === "development"
89
109
  ? "development"
@@ -97,11 +117,12 @@ export function resolveUserConfig({
97
117
  const minify = config.build?.minify;
98
118
  if (condition === "react-client") {
99
119
  // client plugin build options (client plugin still outputs server files)
100
- stashedUserConfig[envId] = {
120
+ const clientConfig = {
101
121
  ...config,
102
122
  root: root,
103
123
  mode: mode,
104
124
  base: userOptions.moduleBasePath,
125
+ envPrefix: vitePrefix,
105
126
  resolve: {
106
127
  ...config.resolve,
107
128
  external: config.resolve?.external ?? [
@@ -134,7 +155,7 @@ export function resolveUserConfig({
134
155
  emptyOutDir: config.build?.emptyOutDir ?? true,
135
156
  outDir: config.build?.outDir ?? join(userOptions.build.outDir, envDir),
136
157
  assetsDir: config.build?.assetsDir ?? userOptions.build.assetsDir,
137
- copyPublicDir: config.build?.copyPublicDir ?? true,
158
+ copyPublicDir: typeof config.build?.copyPublicDir === "boolean" ? config.build?.copyPublicDir : !ssr,
138
159
  // modern browsers
139
160
  target: config.build?.target ?? ["esnext"],
140
161
  minify: minify,
@@ -155,13 +176,19 @@ export function resolveUserConfig({
155
176
  ? config.build?.cssCodeSplit
156
177
  : true,
157
178
  },
179
+ } satisfies ResolvedUserConfig;
180
+ stashedUserConfig[envId] = clientConfig;
181
+ return {
182
+ type: "success",
183
+ userConfig: clientConfig,
158
184
  };
159
185
  } else {
160
- stashedUserConfig[envId] = {
186
+ const serverConfig = {
161
187
  ...config,
162
188
  root: root,
163
189
  mode: mode,
164
190
  base: userOptions.moduleBasePath,
191
+ envPrefix: vitePrefix,
165
192
  resolve: {
166
193
  ...config.resolve,
167
194
  externalConditions: config.resolve?.externalConditions ?? [
@@ -170,11 +197,11 @@ export function resolveUserConfig({
170
197
  },
171
198
  define: {
172
199
  ...config.define,
173
- "process.env.VITE_SSR": `"1"`,
174
- "process.env.VITE_DEV": `"${mode === "development" ? "1" : "0"}"`,
175
- "process.env.VITE_PROD": `"${mode === "production" ? "1" : "0"}"`,
176
- "process.env.VITE_MODE": `"${mode}"`,
177
- "process.env.VITE_BASE_URL": `"${
200
+ [`process.env.${vitePrefix}SSR`]: `"1"`,
201
+ [`process.env.${vitePrefix}DEV`]: `"${mode === "development" ? "1" : "0"}"`,
202
+ [`process.env.${vitePrefix}PROD`]: `"${mode === "production" ? "1" : "0"}"`,
203
+ [`process.env.${vitePrefix}MODE`]: `"${mode}"`,
204
+ [`process.env.${vitePrefix}BASE_URL`]: `"${
178
205
  userOptions.moduleBasePath === "" ||
179
206
  userOptions.moduleBasePath === "/"
180
207
  ? "/"
@@ -186,7 +213,14 @@ export function resolveUserConfig({
186
213
  ssr: {
187
214
  ...config.ssr,
188
215
  target: config.ssr?.target ?? "node",
189
-
216
+ optimizeDeps: {
217
+ ...config.ssr?.optimizeDeps,
218
+ include: config.ssr?.optimizeDeps?.include ?? [
219
+ "react",
220
+ "react-dom",
221
+ "react-server-dom-esm/client",
222
+ ],
223
+ },
190
224
  resolve: {
191
225
  ...config.ssr?.resolve,
192
226
  externalConditions: config.ssr?.resolve?.externalConditions ?? [
@@ -211,7 +245,7 @@ export function resolveUserConfig({
211
245
  copyPublicDir:
212
246
  typeof config.build?.copyPublicDir === "boolean"
213
247
  ? config.build?.copyPublicDir
214
- : true,
248
+ : false,
215
249
  assetsDir: config.build?.assetsDir ?? userOptions.build.assetsDir,
216
250
  // Ensure CSS files are output to static directory
217
251
  cssCodeSplit:
@@ -226,17 +260,11 @@ export function resolveUserConfig({
226
260
  output: newOutput,
227
261
  },
228
262
  },
229
- };
230
- }
231
- if (!stashedUserConfig[envId]) {
263
+ } satisfies ResolvedUserConfig;
264
+ stashedUserConfig[envId] = serverConfig;
232
265
  return {
233
- type: "error",
234
- error: new Error("Failed to resolve config"),
266
+ type: "success",
267
+ userConfig: serverConfig,
235
268
  };
236
269
  }
237
-
238
- return {
239
- type: "success",
240
- userConfig: stashedUserConfig[envId],
241
- };
242
270
  }
@@ -1,160 +1 @@
1
- import type { CreateHandlerOptions, CssContent } from "../types.js";
2
- import { createCssProps } from "./createCssProps.js";
3
- import { join } from "node:path";
4
- import { readFile } from "node:fs/promises";
5
-
6
- type CssCollectionOptions = Pick<
7
- CreateHandlerOptions<unknown, React.ComponentType<unknown>>,
8
- | "projectRoot"
9
- | "build"
10
- | "moduleBaseURL"
11
- | "moduleBasePath"
12
- | "moduleRootPath"
13
- | "css"
14
- | "cssFiles"
15
- | "manifest"
16
- >
17
-
18
- /**
19
- * Recursively collects CSS files from a bundle manifest
20
- */
21
- async function collectCssFromModule(
22
- moduleKey: string,
23
- manifest: Record<string, any>,
24
- cssMap: Map<string, CssContent>,
25
- options: CssCollectionOptions
26
- ): Promise<void> {
27
- const mod = manifest[moduleKey];
28
- if (!mod) return;
29
-
30
- // Handle CSS imports
31
- if (mod.imports) {
32
- for (const importPath of mod.imports) {
33
- if (importPath === moduleKey) continue;
34
- if (importPath) {
35
- const cssEntry = manifest[importPath];
36
- // Handle CSS array
37
- if (Array.isArray(cssEntry.css)) {
38
- for (const cssFile of cssEntry.css) {
39
- if (cssMap.has(cssFile)) continue;
40
- const file = join(
41
- options.projectRoot,
42
- options.build.outDir,
43
- options.build.static,
44
- cssFile
45
- );
46
- const code =
47
- "source" in cssEntry && typeof cssEntry.source === "string"
48
- ? cssEntry.source
49
- : await readFile(file, "utf-8");
50
- cssMap.set(
51
- importPath,
52
- createCssProps({
53
- id: cssFile,
54
- css: options.css,
55
- code,
56
- moduleBaseURL: options.moduleBaseURL,
57
- moduleBasePath: options.moduleBasePath,
58
- moduleRootPath: options.moduleRootPath,
59
- projectRoot: options.projectRoot,
60
- })
61
- );
62
- }
63
- }
64
- }
65
- // Recursively process non-CSS imports
66
- await collectCssFromModule(importPath, manifest, cssMap, options);
67
- }
68
- }
69
-
70
- // Handle direct CSS files
71
- if (mod.css) {
72
- for (const cssFile of mod.css) {
73
- if (cssMap.has(cssFile)) {
74
- continue
75
- }
76
- try {
77
- const file = join(
78
- options.projectRoot,
79
- options.build.outDir,
80
- options.build.server,
81
- cssFile
82
- );
83
- const code =
84
- "code" in manifest[cssFile] &&
85
- typeof manifest[cssFile].code === "string"
86
- ? manifest[cssFile].code
87
- : await readFile(file, "utf-8");
88
- cssMap.set(
89
- moduleKey,
90
- createCssProps({
91
- id: cssFile,
92
- css: options.css,
93
- code,
94
- moduleBaseURL: options.moduleBaseURL,
95
- moduleBasePath: options.moduleBasePath,
96
- moduleRootPath: options.moduleRootPath,
97
- projectRoot: options.projectRoot,
98
- })
99
- );
100
- } catch {
101
- continue;
102
- }
103
- }
104
- }
105
- }
106
-
107
- /**
108
- * Collects CSS files from a bundle manifest using async generators
109
- */
110
- export async function collectBundleManifestCss(
111
- pages: string[] | string,
112
- options: CssCollectionOptions,
113
- _bundleManifest: Record<string, any>
114
- ): Promise<Map<string, CssContent>> {
115
- const cssMap = new Map<string, CssContent>();
116
- if (options.cssFiles) {
117
- for (const [key, value] of options.cssFiles.entries()) {
118
- if (typeof value !== "string") {
119
- cssMap.set(key, value);
120
- continue;
121
- }
122
- const file = join(
123
- options.projectRoot,
124
- options.build.outDir,
125
- options.build.server,
126
- value
127
- );
128
- const code =
129
- options.manifest != null &&
130
- value in options.manifest &&
131
- "code" in options.manifest[value] &&
132
- typeof options.manifest[value].code === "string"
133
- ? options.manifest[value].code
134
- : await readFile(file, "utf-8");
135
- cssMap.set(
136
- file,
137
- createCssProps({
138
- id: file,
139
- code: code,
140
- css: options.css,
141
- moduleBaseURL: options.moduleBaseURL,
142
- moduleBasePath: options.moduleBasePath,
143
- moduleRootPath: options.moduleRootPath,
144
- projectRoot: options.projectRoot,
145
- })
146
- );
147
- }
148
- }
149
-
150
- // Process page and props modules
151
- if (typeof pages === "string") {
152
- await collectCssFromModule(pages, options.manifest, cssMap, options);
153
- } else if (Array.isArray(pages)) {
154
- for (const _id of pages) {
155
- await collectCssFromModule(_id, options.manifest, cssMap, options);
156
- }
157
- }
158
-
159
- return cssMap;
160
- }
1
+ // deprecated
@@ -32,29 +32,33 @@ export async function collectViteModuleGraphCss<
32
32
  InlineCSS extends boolean | undefined = undefined
33
33
  >({
34
34
  moduleGraph,
35
- pagePath,
36
35
  onCss,
37
- loader,
38
36
  parentUrl,
39
- moduleBaseURL,
40
- moduleBasePath,
41
- moduleRootPath,
42
- projectRoot,
43
- css,
44
- }: Pick<
45
- CreateHandlerOptions<InlineCSS>,
46
- | "pagePath"
47
- | "moduleBaseURL"
48
- | "moduleBasePath"
49
- | "moduleRootPath"
50
- | "projectRoot"
51
- | "css"
52
- | "loader"
53
- > & {
37
+ handlerOptions,
38
+ }: {
54
39
  moduleGraph: ModuleGraph | EnvironmentModuleGraph;
55
40
  onCss?: (cssContent: CssContent, parentUrl: string) => void;
56
41
  parentUrl?: string;
42
+ handlerOptions: Pick<
43
+ CreateHandlerOptions<InlineCSS>,
44
+ | "pagePath"
45
+ | "moduleBaseURL"
46
+ | "moduleBasePath"
47
+ | "moduleRootPath"
48
+ | "projectRoot"
49
+ | "css"
50
+ | "loader"
51
+ >;
57
52
  }): Promise<CollectViteModuleGraphCssResult> {
53
+ const {
54
+ pagePath,
55
+ moduleBaseURL,
56
+ moduleBasePath,
57
+ moduleRootPath,
58
+ projectRoot,
59
+ css,
60
+ loader,
61
+ } = handlerOptions;
58
62
  if (!pagePath) return { type: "skip" };
59
63
 
60
64
  const cssFiles = new Map<string, CssContent>();
@@ -86,7 +90,7 @@ export async function collectViteModuleGraphCss<
86
90
  // Processing module
87
91
  if (mod.id.endsWith(".css")) {
88
92
  const string = await loader(mod.id + "?inline").then(
89
- (m) => m?.['default'] ?? ""
93
+ (m) => m?.["default"] ?? ""
90
94
  );
91
95
  if (typeof string !== "string") {
92
96
  throw new Error(`CSS module ${mod.id}?inline did not return a string`);
@@ -96,11 +100,13 @@ export async function collectViteModuleGraphCss<
96
100
  const cssContent = createCssProps({
97
101
  id: mod?.url,
98
102
  code: string,
99
- moduleBaseURL: moduleBaseURL,
100
- moduleBasePath: moduleBasePath,
101
- moduleRootPath: moduleRootPath,
102
- projectRoot: projectRoot,
103
- css: css,
103
+ userOptions: {
104
+ moduleBaseURL: moduleBaseURL,
105
+ moduleBasePath: moduleBasePath,
106
+ moduleRootPath: moduleRootPath,
107
+ projectRoot: projectRoot,
108
+ css: css,
109
+ },
104
110
  });
105
111
  cssFiles.set(mod?.url, cssContent);
106
112
  onCss?.(cssContent, parentUrl ?? pagePath);
@@ -119,14 +125,10 @@ export async function collectViteModuleGraphCss<
119
125
  ) {
120
126
  await walkModule(importedMod);
121
127
  } else {
122
- throw new Error(
123
- `Imported module has no id`
124
- );
128
+ throw new Error(`Imported module has no id`);
125
129
  }
126
130
  } else {
127
- throw new Error(
128
- `Imported module is not an object`
129
- );
131
+ throw new Error(`Imported module is not an object`);
130
132
  }
131
133
  }
132
134
  }
@@ -23,19 +23,22 @@ import { deserializeRegExp } from "./serializeUserOptions.js";
23
23
  */
24
24
  export const createCssProps = ({
25
25
  id,
26
- css,
27
26
  code,
28
- projectRoot,
29
- moduleBaseURL,
30
- moduleBasePath,
31
- moduleRootPath,
27
+ userOptions,
32
28
  }: {
33
29
  id: string;
34
30
  code: string;
35
- } & Pick<
36
- ResolvedUserOptions,
37
- "css" | "moduleBaseURL" | "moduleBasePath" | "moduleRootPath" | "projectRoot"
38
- >): CssContent => {
31
+ userOptions: Pick<
32
+ ResolvedUserOptions,
33
+ | "css"
34
+ | "moduleBaseURL"
35
+ | "moduleBasePath"
36
+ | "moduleRootPath"
37
+ | "projectRoot"
38
+ >;
39
+ }): CssContent => {
40
+ const { css, moduleBaseURL, moduleBasePath, moduleRootPath, projectRoot } =
41
+ userOptions;
39
42
  // If we don't have a bundle entry, create a linked CSS file
40
43
  let inline = typeof code === "string" && code.length > css.inlineThreshold;
41
44
  // Normalize the ID to be relative to src/
@@ -73,13 +76,21 @@ export const createCssProps = ({
73
76
  : {}),
74
77
  } as CssContent<true>;
75
78
  }
76
-
79
+ const safeParseURL = (() => {
80
+ try {
81
+ return new URL(join(moduleBasePath, normalizedId), moduleBaseURL).href;
82
+ } catch (error) {
83
+ // if the url is not valid, we return the moduleBaseURL + the normalizedId
84
+ // dont make it a argument of join or it will mangle something like http:// into http:/
85
+ return moduleBaseURL + join(moduleBasePath, normalizedId);
86
+ }
87
+ })();
77
88
  // Default case
78
89
  return {
79
90
  id: normalizedId,
80
91
  as: "link",
81
92
  rel: "stylesheet",
82
- href: join(moduleBaseURL, moduleBasePath, normalizedId),
93
+ href: safeParseURL,
83
94
  precedence: "high",
84
95
  } as CssContent<false>;
85
96
  };
@@ -1,6 +1,6 @@
1
1
  import { React, ReactDOMServer } from "../vendor.server.js";
2
2
  import type { CreateHandlerOptions, StreamMetrics } from "../types.js";
3
- import { join } from "node:path";
3
+ import { performance } from "node:perf_hooks";
4
4
  export function createRscStream<
5
5
  T,
6
6
  C extends React.ComponentType<T>,
@@ -42,53 +42,50 @@ export function createRscStream<
42
42
  }):
43
43
  | { type: "success"; stream: any; metrics: StreamMetrics }
44
44
  | { type: "error"; error: Error; metrics: StreamMetrics } {
45
- const startTime = performance.now()
46
- const htmlIsFragment = Html == React.Fragment;
47
- const url =
48
- moduleBaseURL !== "" ? new URL(join(route, moduleBasePath), moduleBaseURL).toString() : route;
49
45
  let errorCount = 0;
50
46
  let streamError: Error | null = null;
51
-
52
- if (!PageComponent) {
53
- return {
54
- type: "error",
55
- error: new Error("PageComponent is required"),
56
- metrics: {
57
- chunks: 0,
58
- bytes: 0,
59
- backpressureCount: 0,
60
- drainCount: 0,
61
- errorCount: 0,
62
- duration: 0,
63
- startTime: 0,
64
- },
65
- };
66
- }
67
- const elements = htmlIsFragment ? (
68
- <CssCollector
69
- cssFiles={cssFiles}
70
- >
71
- <PageComponent {...(pageProps as any)} />
72
- </CssCollector>
73
- ) : (
74
- <Html
75
- moduleBase={moduleBase}
76
- moduleBaseURL={moduleBaseURL}
77
- moduleBasePath={moduleBasePath}
78
- moduleRootPath={moduleRootPath}
79
- projectRoot={projectRoot}
80
- url={url}
81
- route={route}
82
- pageProps={pageProps}
83
- cssFiles={cssFiles}
84
- globalCss={globalCss}
85
- CssCollector={CssCollector}
86
- manifest={manifest}
87
- >
88
- <PageComponent {...(pageProps as any)} />
89
- </Html>
90
- );
47
+ const startTime = performance.now();
91
48
  try {
49
+ const htmlIsFragment = Html == React.Fragment;
50
+ const url = route.startsWith(moduleBaseURL) ? route : moduleBaseURL + route;
51
+
52
+ if (!PageComponent) {
53
+ return {
54
+ type: "error",
55
+ error: new Error("PageComponent is required"),
56
+ metrics: {
57
+ chunks: 0,
58
+ bytes: 0,
59
+ backpressureCount: 0,
60
+ drainCount: 0,
61
+ errorCount: 0,
62
+ duration: 0,
63
+ startTime: 0,
64
+ },
65
+ };
66
+ }
67
+ const elements = htmlIsFragment ? (
68
+ <CssCollector cssFiles={cssFiles}>
69
+ <PageComponent {...(pageProps as any)} />
70
+ </CssCollector>
71
+ ) : (
72
+ <Html
73
+ moduleBase={moduleBase}
74
+ moduleBaseURL={moduleBaseURL}
75
+ moduleBasePath={moduleBasePath}
76
+ moduleRootPath={moduleRootPath}
77
+ projectRoot={projectRoot}
78
+ url={url}
79
+ route={route}
80
+ pageProps={pageProps}
81
+ cssFiles={cssFiles}
82
+ globalCss={globalCss}
83
+ CssCollector={CssCollector}
84
+ manifest={manifest}
85
+ >
86
+ <PageComponent {...(pageProps as any)} />
87
+ </Html>
88
+ );
92
89
  const stream = ReactDOMServer.renderToPipeableStream(
93
90
  elements,
94
91
  moduleBasePath,
@@ -105,7 +102,6 @@ export function createRscStream<
105
102
  },
106
103
  }
107
104
  );
108
-
109
105
  // If we have a stream error, return it immediately
110
106
  if (streamError) {
111
107
  return {
@@ -0,0 +1,37 @@
1
+ import type { RenderMetrics } from "../types.js";
2
+
3
+ export function formatMetrics(metrics: RenderMetrics): string {
4
+ const {
5
+ route,
6
+ rscSize,
7
+ chunks,
8
+ chunkRate,
9
+ processingTime,
10
+ memoryUsage,
11
+ streamMetrics,
12
+ } = metrics;
13
+
14
+ // Format memory usage in MB
15
+ const formatMemory = (bytes: number) => `${(bytes / 1024 / 1024).toFixed(2)}MB`;
16
+
17
+ return `
18
+ Route: ${route}
19
+ Size: ${(rscSize / 1024).toFixed(2)}KB
20
+ Chunks: ${chunks} (${chunkRate.toFixed(2)} chunks/s)
21
+ Processing Time: ${processingTime.toFixed(2)}ms
22
+ Memory:
23
+ RSS: ${formatMemory(memoryUsage.rss)}
24
+ Heap Total: ${formatMemory(memoryUsage.heapTotal)}
25
+ Heap Used: ${formatMemory(memoryUsage.heapUsed)}
26
+ External: ${formatMemory(memoryUsage.external)}
27
+ Stream:
28
+ Duration: ${streamMetrics.duration.toFixed(2)}ms
29
+ Backpressure: ${streamMetrics.backpressureCount}
30
+ Drain: ${streamMetrics.drainCount}
31
+ Errors: ${streamMetrics.errorCount}
32
+ `.trim();
33
+ }
34
+
35
+ export function logMetrics(metrics: RenderMetrics) {
36
+ console.log(formatMetrics(metrics));
37
+ }
@@ -11,8 +11,6 @@ type TryManifestOptions<SSR extends boolean = false> = {
11
11
  manifestPath?: string | undefined;
12
12
  };
13
13
 
14
- const stashedManifests: Map<string, any> = new Map();
15
-
16
14
  export async function tryManifest<SSR extends boolean>(
17
15
  options: TryManifestOptions<SSR>
18
16
  ): Promise<
@@ -26,12 +24,6 @@ export async function tryManifest<SSR extends boolean>(
26
24
  error: Error;
27
25
  manifest?: never;
28
26
  }> {
29
- if (stashedManifests.has(options.outDir)) {
30
- return {
31
- type: "success",
32
- manifest: stashedManifests.get(options.outDir),
33
- };
34
- }
35
27
  const localSsrManifestPath = !options.ssrManifest ? undefined : options.manifestPath ? options.manifestPath : join('.vite', 'ssr-manifest.json');
36
28
  const localManifestPath = options.ssrManifest ? undefined : options.manifestPath ? options.manifestPath : join('.vite', 'manifest.json');
37
29
  const manifestPath = resolve(
@@ -41,7 +33,6 @@ export async function tryManifest<SSR extends boolean>(
41
33
  );
42
34
  try {
43
35
  const result = JSON.parse(await readFile(manifestPath, "utf-8"));
44
- stashedManifests.set(options.outDir, result);
45
36
  return {
46
37
  type: "success",
47
38
  manifest: result,
package/plugin/html.tsx CHANGED
@@ -10,7 +10,7 @@ export const Html = ({
10
10
  }: React.PropsWithChildren<HtmlProps>) => (
11
11
  <html>
12
12
  <head>
13
- {moduleBasePath !== "" && <base href={moduleBasePath} />}
13
+ {moduleBasePath !== ""}
14
14
  <CssCollectorElements cssFiles={globalCss} />
15
15
  </head>
16
16
  <body>
@@ -78,6 +78,8 @@ export async function createBuildLoader(
78
78
  return { default: serverChunk.source };
79
79
  } else if ("code" in serverChunk) {
80
80
  return { default: serverChunk.code };
81
+ } else {
82
+ console.warn("Could not find inline module for: " + normalizedValue);
81
83
  }
82
84
  }
83
85