vite-plugin-react-server 0.1.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 (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +289 -0
  3. package/dist/build/createBuildConfig.d.ts +12 -0
  4. package/dist/build/createBuildConfig.d.ts.map +1 -0
  5. package/dist/build/createBuildConfig.js +55 -0
  6. package/dist/build/createBuildConfig.js.map +1 -0
  7. package/dist/checkFilesExist.d.ts +8 -0
  8. package/dist/checkFilesExist.d.ts.map +1 -0
  9. package/dist/checkFilesExist.js +61 -0
  10. package/dist/checkFilesExist.js.map +1 -0
  11. package/dist/collect-css-manifest.d.ts +4 -0
  12. package/dist/collect-css-manifest.d.ts.map +1 -0
  13. package/dist/collect-css-manifest.js +57 -0
  14. package/dist/collect-css-manifest.js.map +1 -0
  15. package/dist/components.d.ts +13 -0
  16. package/dist/components.d.ts.map +1 -0
  17. package/dist/components.js +13 -0
  18. package/dist/components.js.map +1 -0
  19. package/dist/copy-dir.d.ts +4 -0
  20. package/dist/copy-dir.d.ts.map +1 -0
  21. package/dist/getEnv.d.ts +19 -0
  22. package/dist/getEnv.d.ts.map +1 -0
  23. package/dist/getEnv.js +76 -0
  24. package/dist/getEnv.js.map +1 -0
  25. package/dist/helpers/normalizedRelativePath.d.ts +9 -0
  26. package/dist/helpers/normalizedRelativePath.d.ts.map +1 -0
  27. package/dist/helpers/normalizedRelativePath.js +31 -0
  28. package/dist/helpers/normalizedRelativePath.js.map +1 -0
  29. package/dist/helpers/tryManifest.d.ts +8 -0
  30. package/dist/helpers/tryManifest.d.ts.map +1 -0
  31. package/dist/html/createPageLoader.d.ts +26 -0
  32. package/dist/html/createPageLoader.d.ts.map +1 -0
  33. package/dist/html/createPageLoader.js +70 -0
  34. package/dist/html/createPageLoader.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +5 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/manifest.d.ts +6 -0
  40. package/dist/manifest.d.ts.map +1 -0
  41. package/dist/module-graph.d.ts +10 -0
  42. package/dist/module-graph.d.ts.map +1 -0
  43. package/dist/options.d.ts +86 -0
  44. package/dist/options.d.ts.map +1 -0
  45. package/dist/options.js +251 -0
  46. package/dist/options.js.map +1 -0
  47. package/dist/plugin.d.ts +8 -0
  48. package/dist/plugin.d.ts.map +1 -0
  49. package/dist/plugin.js +31 -0
  50. package/dist/plugin.js.map +1 -0
  51. package/dist/react-client/plugin.d.ts +4 -0
  52. package/dist/react-client/plugin.d.ts.map +1 -0
  53. package/dist/react-client/plugin.js +28 -0
  54. package/dist/react-client/plugin.js.map +1 -0
  55. package/dist/react-server/createDevMiddleware.d.ts +8 -0
  56. package/dist/react-server/createDevMiddleware.d.ts.map +1 -0
  57. package/dist/react-server/createDevServer.d.ts +4 -0
  58. package/dist/react-server/createDevServer.d.ts.map +1 -0
  59. package/dist/react-server/createHandler.d.ts +23 -0
  60. package/dist/react-server/createHandler.d.ts.map +1 -0
  61. package/dist/react-server/createHandler.js +110 -0
  62. package/dist/react-server/createHandler.js.map +1 -0
  63. package/dist/react-server/createReactNodeStreamer.d.ts +10 -0
  64. package/dist/react-server/createReactNodeStreamer.d.ts.map +1 -0
  65. package/dist/react-server/createRscStream.d.ts +4 -0
  66. package/dist/react-server/createRscStream.d.ts.map +1 -0
  67. package/dist/react-server/createRscStream.js +47 -0
  68. package/dist/react-server/createRscStream.js.map +1 -0
  69. package/dist/react-server/createSsrHandler.d.ts +4 -0
  70. package/dist/react-server/createSsrHandler.d.ts.map +1 -0
  71. package/dist/react-server/plugin.d.ts +8 -0
  72. package/dist/react-server/plugin.d.ts.map +1 -0
  73. package/dist/react-server/plugin.js +298 -0
  74. package/dist/react-server/plugin.js.map +1 -0
  75. package/dist/resolvePage.d.ts +19 -0
  76. package/dist/resolvePage.d.ts.map +1 -0
  77. package/dist/resolvePage.js +44 -0
  78. package/dist/resolvePage.js.map +1 -0
  79. package/dist/resolveProps.d.ts +19 -0
  80. package/dist/resolveProps.d.ts.map +1 -0
  81. package/dist/resolveProps.js +90 -0
  82. package/dist/resolveProps.js.map +1 -0
  83. package/dist/server.d.ts +2 -0
  84. package/dist/server.d.ts.map +1 -0
  85. package/dist/transformer/index.d.ts +28 -0
  86. package/dist/transformer/index.d.ts.map +1 -0
  87. package/dist/transformer/index.js +54 -0
  88. package/dist/transformer/index.js.map +1 -0
  89. package/dist/transformer/preserveDirectives.d.ts +4 -0
  90. package/dist/transformer/preserveDirectives.d.ts.map +1 -0
  91. package/dist/transformer/preserveDirectives.js +72 -0
  92. package/dist/transformer/preserveDirectives.js.map +1 -0
  93. package/dist/transformer/preserver.d.ts +2 -0
  94. package/dist/transformer/preserver.d.ts.map +1 -0
  95. package/dist/transformer/transformer.d.ts +30 -0
  96. package/dist/transformer/transformer.d.ts.map +1 -0
  97. package/dist/transformer/transformer.js +80 -0
  98. package/dist/transformer/transformer.js.map +1 -0
  99. package/dist/transformer/types.d.ts +15 -0
  100. package/dist/transformer/types.d.ts.map +1 -0
  101. package/dist/types.d.ts +197 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/worker/createHtmlStream.d.ts +7 -0
  104. package/dist/worker/createHtmlStream.d.ts.map +1 -0
  105. package/dist/worker/createWorker.d.ts +3 -0
  106. package/dist/worker/createWorker.d.ts.map +1 -0
  107. package/dist/worker/createWorker.js +33 -0
  108. package/dist/worker/createWorker.js.map +1 -0
  109. package/dist/worker/loader.d.ts +15 -0
  110. package/dist/worker/loader.d.ts.map +1 -0
  111. package/dist/worker/renderPages.d.ts +18 -0
  112. package/dist/worker/renderPages.d.ts.map +1 -0
  113. package/dist/worker/renderPages.js +99 -0
  114. package/dist/worker/renderPages.js.map +1 -0
  115. package/dist/worker/types.d.ts +31 -0
  116. package/dist/worker/types.d.ts.map +1 -0
  117. package/dist/worker/worker.d.ts +7 -0
  118. package/dist/worker/worker.d.ts.map +1 -0
  119. package/package.json +116 -0
  120. package/src/build/createBuildConfig.ts +74 -0
  121. package/src/checkFilesExist.ts +67 -0
  122. package/src/collect-css-manifest.ts +76 -0
  123. package/src/components.tsx +14 -0
  124. package/src/copy-dir.ts +27 -0
  125. package/src/getEnv.ts +135 -0
  126. package/src/helpers/normalizedRelativePath.ts +59 -0
  127. package/src/helpers/tryManifest.ts +23 -0
  128. package/src/html/createPageLoader.ts +99 -0
  129. package/src/index.ts +4 -0
  130. package/src/manifest.ts +24 -0
  131. package/src/module-graph.ts +48 -0
  132. package/src/options.ts +351 -0
  133. package/src/plugin.ts +31 -0
  134. package/src/react-client/plugin.ts +34 -0
  135. package/src/react-server/createDevMiddleware.ts +75 -0
  136. package/src/react-server/createDevServer.ts +10 -0
  137. package/src/react-server/createHandler.ts +144 -0
  138. package/src/react-server/createReactNodeStreamer.ts +25 -0
  139. package/src/react-server/createRscStream.ts +52 -0
  140. package/src/react-server/createSsrHandler.ts +147 -0
  141. package/src/react-server/plugin.ts +349 -0
  142. package/src/resolvePage.ts +65 -0
  143. package/src/resolveProps.ts +122 -0
  144. package/src/server.tsx +0 -0
  145. package/src/transformer/README.md +44 -0
  146. package/src/transformer/index.ts +112 -0
  147. package/src/transformer/preserveDirectives.ts +100 -0
  148. package/src/transformer/preserver.ts +47 -0
  149. package/src/transformer/transformer.ts +123 -0
  150. package/src/transformer/types.ts +15 -0
  151. package/src/types.ts +245 -0
  152. package/src/worker/createHtmlStream.ts +76 -0
  153. package/src/worker/createWorker.ts +39 -0
  154. package/src/worker/loader.ts +16 -0
  155. package/src/worker/renderPages.ts +144 -0
  156. package/src/worker/types.ts +38 -0
  157. package/src/worker/worker.tsx +136 -0
  158. package/tsconfig.json +79 -0
@@ -0,0 +1,75 @@
1
+ import { IncomingMessage, ServerResponse } from "http";
2
+ import type { ViteDevServer } from "vite";
3
+ import { type RequestHandler, type StreamPluginOptions } from "../types.js";
4
+ import { createHandler } from "./createHandler.js";
5
+
6
+ export type DevMiddlewareOptions = Required<
7
+ Pick<
8
+ StreamPluginOptions,
9
+ "moduleBase" | "moduleBasePath" | "moduleBaseURL" | "projectRoot"
10
+ >
11
+ > &
12
+ Pick<StreamPluginOptions, "Page" | "props" | "build" | "Html" | "pageExportName" | "propsExportName">;
13
+
14
+ /**
15
+ * Creates a request handler for development
16
+ */
17
+ export function createDevMiddleware(
18
+ server: ViteDevServer,
19
+ options: DevMiddlewareOptions
20
+ ): RequestHandler {
21
+ return async (req: IncomingMessage, res: ServerResponse, next: any) => {
22
+ // Skip non-page requests
23
+ if (
24
+ !req.url ||
25
+ (req.url.includes(".") && !req.url.endsWith("/index.rsc"))
26
+ ) {
27
+ return next();
28
+ }
29
+ const url = req.url.endsWith("/index.rsc")
30
+ ? req.url.replace("/index.rsc", "/")
31
+ : req.url;
32
+
33
+ try {
34
+ console.log("[stream] Handling RSC stream");
35
+
36
+ const result = await createHandler(url, options, {
37
+ loader: server.ssrLoadModule,
38
+ moduleGraph: server.moduleGraph,
39
+ });
40
+
41
+ if (result.type === "error") {
42
+ if (
43
+ (result.error as Error).message?.includes(
44
+ "module runner has been closed"
45
+ )
46
+ ) {
47
+ console.log("[RSC] Module runner closed, returning 503");
48
+ res.writeHead(503, { "Content-Type": "text/x-component" });
49
+ res.end('{"error":"Server restarting..."}');
50
+ return;
51
+ }
52
+ console.error("[RSC] Stream error:", result.error);
53
+ res.writeHead(500, { "Content-Type": "text/x-component" });
54
+ res.end('{"error":"Internal Server Error"}');
55
+ return;
56
+ }
57
+
58
+ if (result.type !== "success") {
59
+ res.end();
60
+ return;
61
+ }
62
+
63
+ res.setHeader("Content-Type", "text/x-component");
64
+ if (result.stream) result.stream.pipe(res);
65
+ } catch (error: any) {
66
+ if (error.message?.includes("module runner has been closed")) {
67
+ console.log("[RSC] Module runner closed, returning 503");
68
+ res.writeHead(503, { "Content-Type": "text/x-component" });
69
+ res.end('{"error":"Server restarting..."}');
70
+ return;
71
+ }
72
+ next(error);
73
+ }
74
+ };
75
+ }
@@ -0,0 +1,10 @@
1
+ import type { ViteDevServer } from "vite";
2
+ import type { StreamPluginOptions } from "../types.js";
3
+ import { createDevMiddleware, type DevMiddlewareOptions } from "./createDevMiddleware.js";
4
+
5
+ export function createDevServer(
6
+ server: ViteDevServer,
7
+ options: DevMiddlewareOptions
8
+ ) {
9
+ server.middlewares.use(createDevMiddleware(server, options));
10
+ }
@@ -0,0 +1,144 @@
1
+ import { createLogger } from "vite";
2
+ import {
3
+ collectManifestCss,
4
+ collectModuleGraphCss,
5
+ } from "../collect-css-manifest.js";
6
+ import { DEFAULT_CONFIG } from "../options.js";
7
+ import { resolvePage } from "../resolvePage.js";
8
+ import { resolveProps } from "../resolveProps.js";
9
+ import type { CreateHandlerOptions, StreamPluginOptions } from "../types.js";
10
+ import { createRscStream } from "./createRscStream.js";
11
+
12
+ export async function createHandler<T>(
13
+ url: string,
14
+ pluginOptions: Pick<
15
+ StreamPluginOptions,
16
+ "Page" | "props" | "build" | "Html" | "pageExportName" | "propsExportName"
17
+ > &
18
+ Required<
19
+ Pick<StreamPluginOptions, "moduleBase" | "moduleBasePath" | "projectRoot">
20
+ >,
21
+ streamOptions: CreateHandlerOptions<T>
22
+ ) {
23
+ const root = pluginOptions.projectRoot ?? process.cwd();
24
+
25
+ const Html = pluginOptions.Html ?? DEFAULT_CONFIG.HTML;
26
+ const pageExportName =
27
+ pluginOptions.pageExportName ?? DEFAULT_CONFIG.PAGE_EXPORT;
28
+ const propsExportName =
29
+ pluginOptions.propsExportName ?? DEFAULT_CONFIG.PROPS_EXPORT;
30
+ const controller = new AbortController();
31
+
32
+ const cssFiles = streamOptions.cssFiles;
33
+ const propsPath =
34
+ typeof pluginOptions.props === "function"
35
+ ? pluginOptions.props(url)
36
+ : pluginOptions.props;
37
+ const pagePath =
38
+ typeof pluginOptions.Page === "function"
39
+ ? pluginOptions.Page(url)
40
+ : pluginOptions.Page;
41
+
42
+ const cssModules = new Set<string>();
43
+
44
+ if (!(streamOptions.manifest || streamOptions.moduleGraph))
45
+ throw new Error("Missing manifest or moduleGraph, pass it to options.");
46
+
47
+ const getCss = streamOptions.manifest
48
+ ? (id: string) =>
49
+ collectManifestCss(
50
+ streamOptions.manifest!,
51
+ root,
52
+ id,
53
+ streamOptions.onCssFile
54
+ )
55
+ : (id: string) => collectModuleGraphCss(streamOptions.moduleGraph!, id);
56
+
57
+ const loadWithCss = async (id: string) => {
58
+ if (!id) return {};
59
+
60
+ try {
61
+ const mod = await streamOptions.loader(id);
62
+ const pageCss = await Promise.resolve(getCss(id));
63
+ Array.from(pageCss.keys()).forEach((css) => cssModules.add(css));
64
+ return mod as Record<string, any>;
65
+ } catch (e: any) {
66
+ if (e.message?.includes("module runner has been closed")) {
67
+ return { type: "skip" } as Record<string, any>;
68
+ } else {
69
+ return { type: "error", error: e } as Record<string, any>;
70
+ }
71
+ }
72
+ };
73
+
74
+ const PropsModule = await resolveProps({
75
+ propsModule: await loadWithCss(propsPath ?? pagePath),
76
+ path: String(propsPath ?? pagePath),
77
+ exportName: propsExportName,
78
+ url,
79
+ });
80
+ if (PropsModule.type === "error")
81
+ return { type: PropsModule.type, error: PropsModule?.error };
82
+ if (PropsModule.type === "skip") return { type: PropsModule.type };
83
+ const props = PropsModule[propsExportName as keyof typeof PropsModule] as any;
84
+ if (props?.type === "error") return { type: props.type, error: props.error };
85
+ if (props?.type === "skip") return { type: props.type };
86
+
87
+ const PageModule = await resolvePage({
88
+ pageModule: await loadWithCss(pagePath),
89
+ path: pagePath,
90
+ exportName: pageExportName,
91
+ url,
92
+ });
93
+ if (PageModule.type === "error")
94
+ return { type: PageModule.type, error: PageModule.error };
95
+ if (PageModule.type === "skip") return { type: PageModule.type };
96
+ const Page = PageModule[pageExportName as keyof typeof PageModule] as any;
97
+ if (Page?.type === "error") return { type: Page.type, error: Page.error };
98
+ if (Page?.type === "skip") return { type: Page.type };
99
+ if (!(typeof Page === "function")) {
100
+ return {
101
+ type: "error",
102
+ error: new Error("Invalid Page component: " + pagePath, {
103
+ cause: Page,
104
+ }),
105
+ };
106
+ }
107
+ if (!(typeof props === "object")) {
108
+ return {
109
+ type: "error",
110
+ error: new Error("Invalid props: " + propsPath, {
111
+ cause: props,
112
+ }),
113
+ };
114
+ }
115
+
116
+ // Add any additional CSS files
117
+ if (streamOptions.cssFiles) {
118
+ streamOptions.cssFiles.forEach((css) => cssModules.add(css));
119
+ }
120
+ const stream = createRscStream({
121
+ Html: Html,
122
+ Page: Page,
123
+ props: props,
124
+ moduleBasePath: pluginOptions.moduleBasePath, // eg /src
125
+ logger: streamOptions.logger ?? createLogger(),
126
+ cssFiles: Array.from(cssModules),
127
+ route: url,
128
+ url,
129
+ pipableStreamOptions: streamOptions.pipableStreamOptions,
130
+ });
131
+
132
+ if (!stream) {
133
+ return { type: "skip" as const };
134
+ }
135
+
136
+ return {
137
+ type: "success" as const,
138
+ controller,
139
+ stream,
140
+ assets: {
141
+ css: cssFiles,
142
+ },
143
+ };
144
+ }
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import {
3
+ createFromNodeStream,
4
+ type CreateFromNodeStreamOptions,
5
+ } from "react-server-dom-esm/client.node";
6
+ import type { Readable } from "stream";
7
+
8
+ export function createReactNodeStreamer({
9
+ stream,
10
+ moduleBasePath,
11
+ moduleBaseURL,
12
+ options,
13
+ }: {
14
+ stream: Readable;
15
+ moduleBasePath: string;
16
+ moduleBaseURL: string;
17
+ options?: CreateFromNodeStreamOptions;
18
+ }) {
19
+ return createFromNodeStream(
20
+ stream,
21
+ moduleBasePath,
22
+ moduleBaseURL,
23
+ options
24
+ ) as React.Usable<React.ReactNode>;
25
+ }
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import {
3
+ renderToPipeableStream,
4
+ type PipeableStream,
5
+ } from "react-server-dom-esm/server.node";
6
+ import { CssCollector } from "../components.js";
7
+ import type { RscStreamOptions } from "../types.js";
8
+
9
+ export function createRscStream(
10
+ streamOptions: RscStreamOptions
11
+ ): PipeableStream {
12
+ const {
13
+ Html,
14
+ Page,
15
+ props,
16
+ logger,
17
+ cssFiles,
18
+ route,
19
+ url,
20
+ moduleBasePath,
21
+ pipableStreamOptions,
22
+ } = streamOptions;
23
+ const css = Array.isArray(cssFiles)
24
+ ? cssFiles.map((css, index) =>
25
+ React.createElement(CssCollector, {
26
+ key: `css-${index}`,
27
+ url: css,
28
+ })
29
+ )
30
+ : [];
31
+ return renderToPipeableStream(
32
+ React.createElement(
33
+ Html,
34
+ {
35
+ key: "html",
36
+ pageProps: props,
37
+ moduleBasePath: moduleBasePath,
38
+ route,
39
+ url,
40
+ },
41
+ React.createElement(Page, { key: "page", ...props }),
42
+ ...css
43
+ ),
44
+ moduleBasePath,
45
+ {
46
+ onError: logger?.error ?? console.error,
47
+ onPostpone: logger?.info ?? console.info,
48
+ environmentName: "Server",
49
+ ...pipableStreamOptions,
50
+ }
51
+ );
52
+ }
@@ -0,0 +1,147 @@
1
+ import { dirname, join, resolve } from "node:path";
2
+ import { Writable } from "node:stream";
3
+ import { fileURLToPath } from "node:url";
4
+ import { Worker } from "node:worker_threads";
5
+ import { type ViteDevServer } from "vite";
6
+ import { DEFAULT_CONFIG } from "../options.js";
7
+ import type { RequestHandler, StreamPluginOptions } from "../types.js";
8
+ import type { WorkerRscChunkMessage } from "../worker/types.js";
9
+ import { createHandler } from "./createHandler.js";
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+
13
+ export function createSsrHandler(
14
+ options: Required<
15
+ Pick<
16
+ StreamPluginOptions,
17
+ "Page" | "props" | "build" | "Html" | "pageExportName" | "propsExportName"
18
+ >
19
+ > &
20
+ Required<
21
+ Pick<
22
+ StreamPluginOptions,
23
+ "moduleBase" | "moduleBasePath" | "moduleBaseURL" | "projectRoot"
24
+ >
25
+ > &
26
+ Pick<StreamPluginOptions, "workerPath">,
27
+ server: ViteDevServer,
28
+ clientComponents: Map<string, string>
29
+ ): RequestHandler {
30
+ const worker = new Worker(
31
+ options?.workerPath
32
+ ? resolve(server.config.root, options?.workerPath)
33
+ : resolve(__dirname, "..", DEFAULT_CONFIG.WORKER_PATH),
34
+ {
35
+ env: {
36
+ NODE_OPTIONS: "--conditions ''",
37
+ VITE_LOADER_PATH: resolve(
38
+ server.config.cacheDir,
39
+ "react-stream/worker/loader.js"
40
+ ),
41
+ },
42
+ }
43
+ );
44
+
45
+ return async function handleSsrRequest(req, res, next) {
46
+ if (
47
+ !req.url ||
48
+ req.url.startsWith("/@") ||
49
+ (req.url.includes(".") && !req.url.endsWith(".html"))
50
+ ) {
51
+ return next();
52
+ }
53
+
54
+ try {
55
+ const result = await createHandler(
56
+ req.url ?? "",
57
+ {
58
+ Page: options.Page,
59
+ props: options.props,
60
+ build: options.build,
61
+ Html: options.Html,
62
+ pageExportName: options.pageExportName,
63
+ propsExportName: options.propsExportName,
64
+ moduleBase: options.moduleBase,
65
+ moduleBasePath: options.moduleBasePath,
66
+ projectRoot: server.config.root,
67
+ },
68
+ {
69
+ loader: server.ssrLoadModule.bind(server),
70
+ moduleGraph: server.moduleGraph,
71
+ }
72
+ );
73
+ const moduleBasePath = join(
74
+ server.config.cacheDir,
75
+ options.moduleBasePath
76
+ );
77
+ const htmlOutputPath = join(
78
+ server.config.cacheDir,
79
+ server.config.build.outDir,
80
+ req.url,
81
+ "index.html"
82
+ );
83
+ if (result.type !== "success") {
84
+ throw new Error(
85
+ result.type === "error" ? String(result.error) : "Skipped"
86
+ );
87
+ }
88
+
89
+ // Collect RSC stream data
90
+ const rscData = await new Promise<string>((resolve, reject) => {
91
+ let data = "";
92
+ if (!result.stream) {
93
+ resolve(data);
94
+ return;
95
+ }
96
+ const writable = new Writable({
97
+ write(chunk, _, callback) {
98
+ data += chunk;
99
+ callback();
100
+ },
101
+ final(callback) {
102
+ resolve(data);
103
+ callback();
104
+ },
105
+ });
106
+
107
+ result.stream.pipe(writable);
108
+ writable.on("error", reject);
109
+ });
110
+
111
+ // Get HTML from worker
112
+ const html = await new Promise<string>((resolve, reject) => {
113
+ worker.postMessage({
114
+ type: "RSC_CHUNK",
115
+ id: req.url ?? "/",
116
+ chunk: rscData,
117
+ moduleBasePath,
118
+ moduleBaseURL: options.moduleBaseURL,
119
+ // Don't need file paths in dev mode
120
+ outDir: "",
121
+ htmlOutputPath: "",
122
+ pipableStreamOptions: {
123
+ bootstrapModules: ["/dist/client.js"],
124
+ },
125
+ } satisfies WorkerRscChunkMessage);
126
+
127
+ worker.once("message", (msg) => {
128
+ if (msg.type === "ERROR") {
129
+ const message =
130
+ msg.error instanceof Error
131
+ ? msg.error.message
132
+ : String(msg.error);
133
+ reject(new Error(message, { cause: msg }));
134
+ } else if (msg.type === "HTML") {
135
+ // In dev, content will be the HTML string
136
+ resolve(msg.content);
137
+ }
138
+ });
139
+ });
140
+
141
+ res.setHeader("Content-Type", "text/html");
142
+ res.end(html);
143
+ } catch (error) {
144
+ next(error);
145
+ }
146
+ };
147
+ }