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.
- package/README.md +220 -141
- package/bin/patch.mjs +8 -2
- package/dist/package.json +15 -8
- package/dist/plugin/checkFilesExist.d.ts.map +1 -1
- package/dist/plugin/checkFilesExist.js +6 -2
- package/dist/plugin/checkFilesExist.js.map +1 -1
- package/dist/plugin/collect-manifest-client-files.d.ts +23 -0
- package/dist/plugin/collect-manifest-client-files.d.ts.map +1 -0
- package/dist/plugin/collect-manifest-client-files.js +131 -0
- package/dist/plugin/collect-manifest-client-files.js.map +1 -0
- package/dist/plugin/components.d.ts +3 -13
- package/dist/plugin/components.d.ts.map +1 -1
- package/dist/plugin/components.js +3 -13
- package/dist/plugin/config/defaults.d.ts +14 -6
- package/dist/plugin/config/defaults.d.ts.map +1 -1
- package/dist/plugin/config/defaults.js +9 -5
- package/dist/plugin/config/defaults.js.map +1 -1
- package/dist/plugin/config/getPaths.d.ts +0 -1
- package/dist/plugin/config/getPaths.d.ts.map +1 -1
- package/dist/plugin/config/getPaths.js +2 -7
- package/dist/plugin/config/getPaths.js.map +1 -1
- package/dist/plugin/config/mimeTypes.d.ts +2 -0
- package/dist/plugin/config/mimeTypes.d.ts.map +1 -0
- package/dist/plugin/config/mimeTypes.js +24 -0
- package/dist/plugin/config/mimeTypes.js.map +1 -0
- package/dist/plugin/config/resolveOptions.d.ts +2 -2
- package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
- package/dist/plugin/config/resolveOptions.js +47 -28
- package/dist/plugin/config/resolveOptions.js.map +1 -1
- package/dist/plugin/config/resolvePages.d.ts +1 -0
- package/dist/plugin/config/resolvePages.d.ts.map +1 -1
- package/dist/plugin/config/resolvePages.js +9 -5
- package/dist/plugin/config/resolvePages.js.map +1 -1
- package/dist/plugin/config/resolveUserConfig.d.ts +2 -1
- package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
- package/dist/plugin/config/resolveUserConfig.js +181 -147
- package/dist/plugin/config/resolveUserConfig.js.map +1 -1
- package/dist/plugin/copy-dir.js +23 -18
- package/dist/plugin/copy-dir.js.map +1 -0
- package/dist/plugin/css-collector-inline.d.ts +10 -0
- package/dist/plugin/css-collector-inline.d.ts.map +1 -0
- package/dist/plugin/css-collector-inline.js +55 -0
- package/dist/plugin/css-collector-inline.js.map +1 -0
- package/dist/plugin/css-collector.d.ts +14 -0
- package/dist/plugin/css-collector.d.ts.map +1 -0
- package/dist/plugin/css-collector.js +49 -0
- package/dist/plugin/css-collector.js.map +1 -0
- package/dist/plugin/helpers/createHandler.d.ts +17 -0
- package/dist/plugin/helpers/createHandler.d.ts.map +1 -0
- package/dist/plugin/helpers/createHandler.js +111 -0
- package/dist/plugin/helpers/createHandler.js.map +1 -0
- package/dist/plugin/helpers/createRscStream.d.ts +27 -0
- package/dist/plugin/helpers/createRscStream.d.ts.map +1 -0
- package/dist/plugin/helpers/createRscStream.js +80 -0
- package/dist/plugin/helpers/createRscStream.js.map +1 -0
- package/dist/plugin/helpers/getBundleManifest.d.ts.map +1 -1
- package/dist/plugin/helpers/getBundleManifest.js +12 -4
- package/dist/plugin/helpers/getBundleManifest.js.map +1 -1
- package/dist/plugin/html.d.ts +5 -0
- package/dist/plugin/html.d.ts.map +1 -0
- package/dist/plugin/html.js +11 -0
- package/dist/plugin/html.js.map +1 -0
- package/dist/plugin/loader/createBuildLoader.d.ts +1 -1
- package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
- package/dist/plugin/loader/createBuildLoader.js +8 -5
- package/dist/plugin/loader/createBuildLoader.js.map +1 -1
- package/dist/plugin/loader/css-loader.d.ts.map +1 -1
- package/dist/plugin/loader/css-loader.js.map +1 -1
- package/dist/plugin/loader/react-loader.js +2 -2
- package/dist/plugin/loader/react-loader.js.map +1 -1
- package/dist/plugin/preserver/plugin.d.ts.map +1 -1
- package/dist/plugin/preserver/plugin.js +49 -14
- package/dist/plugin/preserver/plugin.js.map +1 -1
- package/dist/plugin/react-client/plugin.d.ts.map +1 -1
- package/dist/plugin/react-client/plugin.js +21 -78
- package/dist/plugin/react-client/plugin.js.map +1 -1
- package/dist/plugin/react-server/index.d.ts.map +1 -1
- package/dist/plugin/react-server/index.js +2 -0
- package/dist/plugin/react-server/index.js.map +1 -1
- package/dist/plugin/react-server/plugin.d.ts +2 -1
- package/dist/plugin/react-server/plugin.d.ts.map +1 -1
- package/dist/plugin/react-server/plugin.js +92 -225
- package/dist/plugin/react-server/plugin.js.map +1 -1
- package/dist/plugin/react-static/index.d.ts +2 -0
- package/dist/plugin/react-static/index.d.ts.map +1 -0
- package/dist/plugin/react-static/index.js +1 -0
- package/dist/plugin/react-static/plugin.d.ts +7 -0
- package/dist/plugin/react-static/plugin.d.ts.map +1 -0
- package/dist/plugin/react-static/plugin.js +207 -0
- package/dist/plugin/react-static/plugin.js.map +1 -0
- package/dist/plugin/react-static/types.d.ts +2 -0
- package/dist/plugin/react-static/types.d.ts.map +1 -0
- package/dist/plugin/resolvePage.d.ts.map +1 -1
- package/dist/plugin/resolvePage.js +9 -0
- package/dist/plugin/resolvePage.js.map +1 -1
- package/dist/plugin/root.d.ts +2 -0
- package/dist/plugin/root.d.ts.map +1 -0
- package/dist/plugin/root.js +12 -0
- package/dist/plugin/root.js.map +1 -0
- package/dist/plugin/transformer/plugin.d.ts.map +1 -1
- package/dist/plugin/transformer/plugin.js +32 -23
- package/dist/plugin/transformer/plugin.js.map +1 -1
- package/dist/plugin/transformer/types.d.ts +1 -18
- package/dist/plugin/transformer/types.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +70 -15
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/worker/createWorker.js +0 -1
- package/dist/plugin/worker/createWorker.js.map +1 -1
- package/dist/plugin/worker/html/html-worker.development.d.ts +30 -0
- package/dist/plugin/worker/html/html-worker.development.d.ts.map +1 -1
- package/dist/plugin/worker/html/html-worker.development.js +30 -2
- package/dist/plugin/worker/html/html-worker.development.js.map +1 -1
- package/dist/plugin/worker/html/html-worker.production.js +3 -5
- package/dist/plugin/worker/html/html-worker.production.js.map +1 -1
- package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
- package/dist/plugin/worker/html/messageHandler.js +12 -3
- package/dist/plugin/worker/html/messageHandler.js.map +1 -1
- package/dist/plugin/worker/html/renderPages.d.ts +13 -26
- package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
- package/dist/plugin/worker/html/renderPages.js +138 -86
- package/dist/plugin/worker/html/renderPages.js.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.js +104 -84
- package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
- package/dist/plugin/worker/rsc/rsc-worker.development.js +13 -18
- package/dist/plugin/worker/rsc/rsc-worker.development.js.map +1 -1
- package/dist/plugin/worker/rsc/rsc-worker.production.js +4 -1
- package/dist/plugin/worker/rsc/rsc-worker.production.js.map +1 -1
- package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/state.js.map +1 -1
- package/dist/plugin/worker/types.d.ts +3 -0
- package/dist/plugin/worker/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -6
- package/plugin/checkFilesExist.ts +7 -3
- package/plugin/collect-manifest-client-files.ts +167 -0
- package/plugin/components.ts +3 -0
- package/plugin/config/defaults.tsx +70 -0
- package/plugin/config/getPaths.ts +1 -7
- package/plugin/config/mimeTypes.ts +17 -0
- package/plugin/config/resolveOptions.ts +58 -45
- package/plugin/config/resolvePages.ts +8 -4
- package/plugin/config/resolveUserConfig.ts +220 -176
- package/plugin/css-collector-inline.tsx +60 -0
- package/plugin/css-collector.tsx +62 -0
- package/plugin/helpers/createHandler.ts +135 -0
- package/plugin/helpers/createRscStream.ts +109 -0
- package/plugin/helpers/getBundleManifest.ts +14 -5
- package/plugin/html.tsx +9 -0
- package/plugin/loader/createBuildLoader.ts +9 -6
- package/plugin/loader/css-loader.ts +0 -2
- package/plugin/loader/react-loader.ts +2 -2
- package/plugin/preserver/plugin.ts +64 -17
- package/plugin/react-client/plugin.ts +23 -93
- package/plugin/react-server/index.ts +2 -0
- package/plugin/react-server/plugin.ts +111 -302
- package/plugin/react-static/index.ts +1 -0
- package/plugin/react-static/plugin.ts +256 -0
- package/plugin/react-static/types.ts +3 -0
- package/plugin/resolvePage.ts +9 -0
- package/plugin/root.ts +4 -0
- package/plugin/transformer/plugin.ts +40 -31
- package/plugin/transformer/types.ts +0 -19
- package/plugin/types.ts +77 -16
- package/plugin/worker/createWorker.ts +1 -1
- package/plugin/worker/html/README.md +63 -0
- package/plugin/worker/html/html-worker.development.tsx +89 -2
- package/plugin/worker/html/html-worker.production.tsx +8 -10
- package/plugin/worker/html/messageHandler.ts +12 -3
- package/plugin/worker/html/renderPages.ts +178 -138
- package/plugin/worker/rsc/README.md +58 -0
- package/plugin/worker/rsc/messageHandler.tsx +112 -113
- package/plugin/worker/rsc/rsc-worker.development.ts +12 -22
- package/plugin/worker/rsc/rsc-worker.production.ts +5 -1
- package/plugin/worker/rsc/state.ts +0 -3
- package/plugin/worker/types.ts +3 -0
- package/scripts/react+0.0.0-experimental-eda36a1c-20250228.patch +114 -12
- package/scripts/react-dom+0.0.0-experimental-eda36a1c-20250228.patch +10571 -121
- package/tsconfig.json +2 -2
- package/dist/plugin/collect-css-manifest.d.ts +0 -4
- package/dist/plugin/collect-css-manifest.d.ts.map +0 -1
- package/dist/plugin/collect-css-manifest.js +0 -65
- package/dist/plugin/collect-css-manifest.js.map +0 -1
- package/dist/plugin/config/createModuleIdGenerator.d.ts +0 -11
- package/dist/plugin/config/createModuleIdGenerator.d.ts.map +0 -1
- package/dist/plugin/config/createModuleIdGenerator.js +0 -44
- package/dist/plugin/config/createModuleIdGenerator.js.map +0 -1
- package/dist/plugin/getEnv.d.ts +0 -19
- package/dist/plugin/getEnv.d.ts.map +0 -1
- package/dist/plugin/getEnv.js +0 -107
- package/dist/plugin/loader/createCssLoader.d.ts +0 -30
- package/dist/plugin/loader/createCssLoader.d.ts.map +0 -1
- package/dist/plugin/loader/createCssLoader.js +0 -35
- package/dist/plugin/loader/createPageLoader.d.ts +0 -24
- package/dist/plugin/loader/createPageLoader.d.ts.map +0 -1
- package/dist/plugin/loader/createPageLoader.js +0 -50
- package/dist/plugin/loader/rsc/messageHandler.d.ts +0 -2
- package/dist/plugin/loader/rsc/messageHandler.d.ts.map +0 -1
- package/dist/plugin/loader/rsc/rsc-worker.development.d.ts +0 -2
- package/dist/plugin/loader/rsc/rsc-worker.development.d.ts.map +0 -1
- package/dist/plugin/loader/rsc/rsc-worker.development.js +0 -1
- package/dist/plugin/module-graph.d.ts +0 -10
- package/dist/plugin/module-graph.d.ts.map +0 -1
- package/dist/plugin/module-graph.js +0 -35
- package/dist/plugin/react-server/createHandler.d.ts +0 -17
- package/dist/plugin/react-server/createHandler.d.ts.map +0 -1
- package/dist/plugin/react-server/createHandler.js +0 -126
- package/dist/plugin/react-server/createHandler.js.map +0 -1
- package/dist/plugin/react-server/createRscStream.d.ts +0 -16
- package/dist/plugin/react-server/createRscStream.d.ts.map +0 -1
- package/dist/plugin/react-server/createRscStream.js +0 -70
- package/dist/plugin/react-server/createRscStream.js.map +0 -1
- package/dist/plugin/react-server/createSsrHandler.d.ts +0 -4
- package/dist/plugin/react-server/createSsrHandler.d.ts.map +0 -1
- package/dist/plugin/react-server/createSsrHandler.js +0 -95
- package/dist/plugin/utils/logger.d.ts +0 -9
- package/dist/plugin/utils/logger.d.ts.map +0 -1
- package/dist/plugin/utils/logger.js +0 -68
- package/dist/plugin/utils/logger.js.map +0 -1
- package/dist/plugin/worker/html/plugin.d.ts +0 -4
- package/dist/plugin/worker/html/plugin.d.ts.map +0 -1
- package/dist/plugin/worker/html/plugin.js +0 -94
- package/dist/plugin/worker/plugin.d.ts +0 -19
- package/dist/plugin/worker/plugin.d.ts.map +0 -1
- package/dist/plugin/worker/plugin.js +0 -23
- package/dist/plugin/worker/rsc/plugin.d.ts +0 -4
- package/dist/plugin/worker/rsc/plugin.d.ts.map +0 -1
- package/dist/plugin/worker/rsc/plugin.js +0 -76
- package/plugin/collect-css-manifest.ts +0 -82
- package/plugin/components.tsx +0 -14
- package/plugin/config/createModuleIdGenerator.ts +0 -52
- package/plugin/config/defaults.ts +0 -51
- package/plugin/getEnv.ts +0 -135
- package/plugin/loader/createCssLoader.ts +0 -73
- package/plugin/loader/createPageLoader.ts +0 -103
- package/plugin/loader/rsc/messageHandler.tsx +0 -1
- package/plugin/loader/rsc/rsc-worker.development.ts +0 -1
- package/plugin/module-graph.ts +0 -48
- package/plugin/react-server/createHandler.ts +0 -162
- package/plugin/react-server/createRscStream.ts +0 -86
- package/plugin/react-server/createSsrHandler.ts +0 -125
- package/plugin/utils/logger.ts +0 -52
- package/plugin/worker/html/plugin.ts +0 -101
- package/plugin/worker/plugin.ts +0 -26
- package/plugin/worker/rsc/plugin.ts +0 -84
- /package/dist/plugin/{loader/rsc/messageHandler.js → react-static/types.js} +0 -0
|
@@ -1,8 +1,95 @@
|
|
|
1
|
+
// no offical types for node:module available yet (23.7.0)
|
|
2
|
+
declare module "node:module" {
|
|
3
|
+
export interface ImportAttributes {
|
|
4
|
+
[key: string]: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ResolveHookContext {
|
|
8
|
+
conditions: string[];
|
|
9
|
+
parentURL: string | undefined;
|
|
10
|
+
importAttributes: ImportAttributes;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LoadHookContext {
|
|
14
|
+
conditions: string[];
|
|
15
|
+
format: ModuleFormat | null | undefined;
|
|
16
|
+
importAttributes: ImportAttributes;
|
|
17
|
+
shortCircuit?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ResolveResult {
|
|
21
|
+
url: string;
|
|
22
|
+
shortCircuit: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LoadResult {
|
|
26
|
+
format: string;
|
|
27
|
+
source: string | SharedArrayBuffer | Uint8Array;
|
|
28
|
+
shortCircuit: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface HooksAPI {
|
|
32
|
+
resolve?: (
|
|
33
|
+
specifier: string,
|
|
34
|
+
context: ResolveHookContext,
|
|
35
|
+
nextResolve: (
|
|
36
|
+
specifier: string,
|
|
37
|
+
context: ResolveHookContext
|
|
38
|
+
) => ResolveResult
|
|
39
|
+
) => ResolveResult;
|
|
40
|
+
|
|
41
|
+
load?: (
|
|
42
|
+
url: string,
|
|
43
|
+
context: LoadHookContext,
|
|
44
|
+
nextLoad: (url: string, context: LoadHookContext) => LoadResult
|
|
45
|
+
) => LoadResult;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function registerHooks(hooks: HooksAPI): void;
|
|
49
|
+
}
|
|
50
|
+
import { join } from "node:path";
|
|
51
|
+
import { pluginRoot } from "../../root.js";
|
|
1
52
|
import { messageHandler } from "./messageHandler.js";
|
|
2
53
|
import { parentPort } from "node:worker_threads";
|
|
54
|
+
import { register } from "node:module";
|
|
55
|
+
import { register as registerTsx } from "tsx/esm/api";
|
|
56
|
+
import { MessageChannel } from "node:worker_threads";
|
|
3
57
|
|
|
4
58
|
if (!parentPort) throw new Error("This module must be run as a worker");
|
|
5
|
-
parentPort?.on("message", messageHandler);
|
|
6
59
|
|
|
60
|
+
// Create channels for each loader
|
|
61
|
+
const reactLoaderChannel = new MessageChannel();
|
|
62
|
+
const cssLoaderChannel = new MessageChannel();
|
|
63
|
+
|
|
64
|
+
// Listen for messages from loaders
|
|
65
|
+
reactLoaderChannel.port2.on("message", messageHandler);
|
|
66
|
+
cssLoaderChannel.port2.on("message", messageHandler);
|
|
67
|
+
|
|
68
|
+
const loaderPath = "file://" + join(pluginRoot, "loader/react-loader.js");
|
|
69
|
+
const cssLoaderPath = "file://" + join(pluginRoot, "loader/css-loader.js");
|
|
70
|
+
|
|
71
|
+
// Register react-loader
|
|
72
|
+
register(loaderPath, {
|
|
73
|
+
parentURL: pluginRoot,
|
|
74
|
+
data: { port: reactLoaderChannel.port1 },
|
|
75
|
+
transferList: [reactLoaderChannel.port1],
|
|
76
|
+
});
|
|
77
|
+
register(cssLoaderPath, {
|
|
78
|
+
parentURL: pluginRoot,
|
|
79
|
+
data: { port: cssLoaderChannel.port1 },
|
|
80
|
+
transferList: [cssLoaderChannel.port1],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Register loaders
|
|
84
|
+
registerTsx();
|
|
7
85
|
// Signal ready with environment
|
|
8
|
-
parentPort?.
|
|
86
|
+
parentPort?.on("message", messageHandler);
|
|
87
|
+
parentPort?.postMessage({
|
|
88
|
+
type: "READY",
|
|
89
|
+
env: process.env["NODE_ENV"],
|
|
90
|
+
pid: process.pid,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (process.env["NODE_ENV"] !== "development") {
|
|
94
|
+
throw new Error("This module must be run in development mode");
|
|
95
|
+
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { messageHandler } from "./messageHandler.js";
|
|
2
2
|
import { parentPort } from "node:worker_threads";
|
|
3
|
-
import { Window } from 'happy-dom';
|
|
4
|
-
const window = new Window({ url: 'https://localhost:8080' });
|
|
5
|
-
const document = window.document;
|
|
6
|
-
globalThis.window = window as any;
|
|
7
|
-
globalThis.document = document as any;
|
|
8
3
|
|
|
9
|
-
let ready = false;
|
|
10
4
|
if (!parentPort) throw new Error("This module must be run as a worker");
|
|
11
5
|
|
|
12
6
|
// Signal ready with environment
|
|
13
7
|
parentPort?.on("message", messageHandler);
|
|
14
|
-
parentPort?.postMessage({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
parentPort?.postMessage({
|
|
9
|
+
type: "READY",
|
|
10
|
+
env: process.env["NODE_ENV"],
|
|
11
|
+
pid: process.pid,
|
|
18
12
|
});
|
|
13
|
+
|
|
14
|
+
if (process.env["NODE_ENV"] !== "production") {
|
|
15
|
+
throw new Error("This module must be run in development mode");
|
|
16
|
+
}
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
createFromNodeStream,
|
|
8
8
|
// @ts-ignore
|
|
9
9
|
} from "react-server-dom-esm/client.node";
|
|
10
|
-
import { join } from "path";
|
|
11
10
|
|
|
12
11
|
// Track active renders and streams
|
|
13
12
|
const activeRenders = new Map<string, HtmlRenderState>();
|
|
@@ -29,7 +28,7 @@ export const messageHandler = async (message: HtmlWorkerMessage) => {
|
|
|
29
28
|
moduleRootPath,
|
|
30
29
|
moduleBaseURL,
|
|
31
30
|
outDir: '',
|
|
32
|
-
htmlOutputPath: htmlOutputPath
|
|
31
|
+
htmlOutputPath: htmlOutputPath,
|
|
33
32
|
pipableStreamOptions: pipableStreamOptions,
|
|
34
33
|
});
|
|
35
34
|
} else {
|
|
@@ -61,7 +60,7 @@ export const messageHandler = async (message: HtmlWorkerMessage) => {
|
|
|
61
60
|
const reactElements = await createFromNodeStream(
|
|
62
61
|
rscStream,
|
|
63
62
|
render.moduleRootPath,
|
|
64
|
-
|
|
63
|
+
render.moduleBaseURL
|
|
65
64
|
);
|
|
66
65
|
|
|
67
66
|
// Create a promise that resolves when HTML is complete
|
|
@@ -88,6 +87,16 @@ export const messageHandler = async (message: HtmlWorkerMessage) => {
|
|
|
88
87
|
reactElements as React.ReactNode,
|
|
89
88
|
{
|
|
90
89
|
...render.pipableStreamOptions,
|
|
90
|
+
// Calculate relative paths based on route depth
|
|
91
|
+
bootstrapModules: render.pipableStreamOptions?.bootstrapModules?.map(path => {
|
|
92
|
+
if (!path) return path;
|
|
93
|
+
if(render.moduleBaseURL && render.moduleBaseURL !== '') {
|
|
94
|
+
return new URL(path, render.moduleBaseURL).toString();
|
|
95
|
+
}
|
|
96
|
+
const depth = id.split('/').filter(Boolean).length;
|
|
97
|
+
const prefix = depth > 0 ? '../'.repeat(depth) : '/';
|
|
98
|
+
return path.startsWith('/') ? prefix + path.slice(1) : prefix + path;
|
|
99
|
+
}),
|
|
91
100
|
onShellReady() {
|
|
92
101
|
parentPort?.postMessage({ type: "SHELL_READY", id });
|
|
93
102
|
}
|
|
@@ -1,89 +1,116 @@
|
|
|
1
|
-
import { mkdirSync } from "node:fs";
|
|
2
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
import { dirname, join
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
4
3
|
import { Transform } from "node:stream";
|
|
5
4
|
import type { Worker } from "node:worker_threads";
|
|
6
|
-
import { createHandler } from "../../
|
|
7
|
-
import type { CheckFilesExistReturn, ResolvedUserConfig, ResolvedUserOptions } from "../../types.js";
|
|
5
|
+
import { createHandler } from "../../helpers/createHandler.js";
|
|
8
6
|
import type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
} from "rollup";
|
|
7
|
+
CheckFilesExistReturn,
|
|
8
|
+
CreateHandlerOptions,
|
|
9
|
+
PageData,
|
|
10
|
+
} from "../../types.js";
|
|
11
|
+
import type { HtmlWorkerResponse } from "../types.js";
|
|
12
|
+
import { type Manifest, type IndexHtmlTransformHook, createLogger } from "vite";
|
|
16
13
|
import React from "react";
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
interface PipeableStreamOptions {
|
|
20
|
-
bootstrapModules?: string[];
|
|
21
|
-
bootstrapScripts?: string[];
|
|
22
|
-
bootstrapScriptContent?: string;
|
|
23
|
-
signal?: AbortSignal;
|
|
24
|
-
identifierPrefix?: string;
|
|
25
|
-
namespaceURI?: string;
|
|
26
|
-
nonce?: string;
|
|
27
|
-
progressiveChunkSize?: number;
|
|
28
|
-
onShellReady?: () => void;
|
|
29
|
-
onAllReady?: () => void;
|
|
30
|
-
onError?: (error: unknown) => void;
|
|
31
|
-
importMap?: {
|
|
32
|
-
imports?: Record<string, string>;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
14
|
+
import { collectManifestClientFiles } from "../../collect-manifest-client-files.js";
|
|
35
15
|
|
|
36
|
-
type RenderPagesOptions = {
|
|
37
|
-
pluginOptions: ResolvedUserOptions;
|
|
38
|
-
userConfig: ResolvedUserConfig;
|
|
16
|
+
type RenderPagesOptions<T = any> = Omit<CreateHandlerOptions<T>, "url" | "route" | "getCss" | "propsPath" | "pagePath"> & {
|
|
39
17
|
clientManifest: Manifest;
|
|
40
18
|
serverManifest: Manifest;
|
|
41
19
|
worker: Worker;
|
|
42
|
-
pipableStreamOptions?: PipeableStreamOptions;
|
|
43
20
|
loader: (id: string) => Promise<Record<string, any>>;
|
|
44
21
|
onCssFile?: (url: string, parentUrl: string) => void;
|
|
22
|
+
onClientJSFile?: (url: string, parentUrl: string) => void;
|
|
23
|
+
onPage?: (pageData: PageData) => Promise<void>;
|
|
45
24
|
clientCss?: string[];
|
|
46
|
-
|
|
47
|
-
|
|
25
|
+
transformIndexHtml: IndexHtmlTransformHook;
|
|
26
|
+
outDir: string;
|
|
27
|
+
htmlOutputPath: string;
|
|
28
|
+
server?: any;
|
|
29
|
+
bundle?: any;
|
|
30
|
+
chunk?: any;
|
|
31
|
+
originalUrl?: string;
|
|
48
32
|
};
|
|
49
33
|
|
|
50
|
-
export async function renderPages(
|
|
51
|
-
pluginContext: PluginContext,
|
|
34
|
+
export async function renderPages<T = any>(
|
|
52
35
|
routes: string[],
|
|
53
36
|
files: CheckFilesExistReturn,
|
|
54
|
-
options: RenderPagesOptions
|
|
37
|
+
options: RenderPagesOptions<T>
|
|
55
38
|
) {
|
|
56
|
-
const root = pluginContext.environment.config.root;
|
|
57
|
-
const outDir = pluginContext.environment.config.build.outDir;
|
|
58
39
|
const failedRoutes = new Map<string, Error>();
|
|
59
40
|
const completedRoutes = new Set<string>();
|
|
60
|
-
const writePromises = new Map<string, Promise<void>>();
|
|
61
41
|
const clientCss = options.clientCss ?? [];
|
|
42
|
+
const partialPageData = new Map<string, Partial<PageData>>();
|
|
43
|
+
const moduleRootPath =
|
|
44
|
+
options.moduleBasePath !== "" &&
|
|
45
|
+
!options.moduleRootPath.endsWith(options.moduleBasePath)
|
|
46
|
+
? join(options.moduleRootPath, options.moduleBasePath)
|
|
47
|
+
: options.moduleRootPath;
|
|
48
|
+
const mergeAndSendPageData = async (route: string, resolve: () => void) => {
|
|
49
|
+
const partial = partialPageData.get(route);
|
|
50
|
+
if (!partial?.html || !partial.rsc) {
|
|
51
|
+
return; // Wait for both parts
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const pageData: PageData = {
|
|
55
|
+
route,
|
|
56
|
+
html: partial.html,
|
|
57
|
+
rsc: partial.rsc,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Write HTML file
|
|
61
|
+
let routeHtmlPath =
|
|
62
|
+
route === "/"
|
|
63
|
+
? options.htmlOutputPath
|
|
64
|
+
: options.htmlOutputPath.replace(
|
|
65
|
+
"index.html",
|
|
66
|
+
join(route, "index.html")
|
|
67
|
+
);
|
|
68
|
+
if (routeHtmlPath.startsWith("/")) {
|
|
69
|
+
routeHtmlPath = routeHtmlPath.slice(1);
|
|
70
|
+
}
|
|
71
|
+
const routeRscPath = routeHtmlPath.slice(0, -5) + ".rsc";
|
|
72
|
+
await mkdir(dirname(routeHtmlPath), { recursive: true });
|
|
73
|
+
await writeFile(routeRscPath, partial.rsc.content);
|
|
74
|
+
await writeFile(routeHtmlPath, partial.html.raw);
|
|
75
|
+
|
|
76
|
+
await options.onPage?.(pageData);
|
|
77
|
+
completedRoutes.add(route);
|
|
78
|
+
if (completedRoutes.size === routes.length) {
|
|
79
|
+
resolve();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
62
83
|
try {
|
|
63
84
|
// Set up worker message handling
|
|
64
85
|
const allRoutesComplete = new Promise<void>((resolve, reject) => {
|
|
65
|
-
options.worker.on("message", (msg: HtmlWorkerResponse) => {
|
|
86
|
+
options.worker.on("message", async (msg: HtmlWorkerResponse) => {
|
|
66
87
|
switch (msg.type) {
|
|
67
88
|
case "ALL_READY": {
|
|
68
|
-
const { id, html
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
89
|
+
const { id, html } = msg;
|
|
90
|
+
try {
|
|
91
|
+
const partial = partialPageData.get(id) || { route: id };
|
|
92
|
+
|
|
93
|
+
partial.html = {
|
|
94
|
+
raw: html,
|
|
95
|
+
transformed:
|
|
96
|
+
typeof options.transformIndexHtml === "function"
|
|
97
|
+
? String(await options.transformIndexHtml(id, {
|
|
98
|
+
path: id,
|
|
99
|
+
filename: join(id, "index.html"),
|
|
100
|
+
}) || "")
|
|
101
|
+
: "", // Will be set by main thread transform
|
|
102
|
+
assets: [],
|
|
103
|
+
};
|
|
104
|
+
partialPageData.set(id, partial);
|
|
105
|
+
await mergeAndSendPageData(id, resolve);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
failedRoutes.set(id, error as Error);
|
|
108
|
+
reject(error);
|
|
109
|
+
}
|
|
83
110
|
break;
|
|
84
111
|
}
|
|
85
112
|
case "ERROR": {
|
|
86
|
-
console.error(
|
|
113
|
+
console.error("Worker error for route:", msg.id, msg.error);
|
|
87
114
|
failedRoutes.set(msg.id, new Error(msg.error));
|
|
88
115
|
reject(new Error(msg.error));
|
|
89
116
|
break;
|
|
@@ -92,124 +119,138 @@ export async function renderPages(
|
|
|
92
119
|
});
|
|
93
120
|
});
|
|
94
121
|
|
|
95
|
-
const newCssFiles = collectManifestCss(
|
|
96
|
-
options.clientManifest,
|
|
97
|
-
options.moduleBasePath,
|
|
98
|
-
'index.html',
|
|
99
|
-
(url, parentUrl)=>{
|
|
100
|
-
options?.onCssFile?.(url, parentUrl);
|
|
101
|
-
if(!clientCss.includes(url)){
|
|
102
|
-
clientCss.push(url);
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
join(root, options.pluginOptions.build.outDir, options.pluginOptions.build.client)
|
|
106
|
-
);
|
|
107
|
-
|
|
108
122
|
// Process routes sequentially
|
|
109
123
|
for (const route of routes) {
|
|
110
124
|
const routeFiles = files.urlMap.get(route);
|
|
111
125
|
if (!routeFiles) {
|
|
112
|
-
console.error(
|
|
126
|
+
console.error("No files found for route:", route);
|
|
113
127
|
failedRoutes.set(route, new Error(`No files found for ${route}`));
|
|
114
128
|
continue;
|
|
115
129
|
}
|
|
116
130
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
options.onCssFile?.(url, parentUrl);
|
|
123
|
-
if(!clientCss.includes(url)){
|
|
124
|
-
clientCss.push(url);
|
|
125
|
-
}
|
|
131
|
+
if (options.pipableStreamOptions?.importMap?.imports) {
|
|
132
|
+
for (let [, value] of Object.entries(
|
|
133
|
+
options.pipableStreamOptions?.importMap?.imports
|
|
134
|
+
)) {
|
|
135
|
+
options.onClientJSFile?.(value, route);
|
|
126
136
|
}
|
|
127
|
-
|
|
137
|
+
}
|
|
138
|
+
const getCss = async (id: string) => {
|
|
139
|
+
const cssFiles = collectManifestClientFiles({
|
|
140
|
+
manifest: options.serverManifest,
|
|
141
|
+
root: options.root,
|
|
142
|
+
pagePath: id,
|
|
143
|
+
}).cssFiles;
|
|
144
|
+
return cssFiles;
|
|
145
|
+
}
|
|
146
|
+
const pagePath = files.urlMap.get(route)?.page;
|
|
147
|
+
const propsPath = files.urlMap.get(route)?.props;
|
|
148
|
+
if(!pagePath){
|
|
149
|
+
throw new Error(`No page path found for ${route}`);
|
|
150
|
+
}
|
|
128
151
|
// Create handler for pure RSC output
|
|
129
|
-
const rscResult = await createHandler(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
152
|
+
const rscResult = await createHandler({
|
|
153
|
+
root: options.root,
|
|
154
|
+
url: route,
|
|
155
|
+
route: route,
|
|
156
|
+
getCss: getCss,
|
|
133
157
|
loader: options.loader,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
cssFiles: clientCss,
|
|
159
|
+
moduleBase: options.moduleBase,
|
|
160
|
+
moduleBasePath: options.moduleBasePath,
|
|
161
|
+
moduleRootPath: moduleRootPath,
|
|
162
|
+
moduleBaseURL: options.moduleBaseURL,
|
|
163
|
+
pipableStreamOptions: options.pipableStreamOptions ?? {},
|
|
164
|
+
inlineCss: options.inlineCss,
|
|
165
|
+
Html: React.Fragment,
|
|
166
|
+
CssCollector: options.CssCollector,
|
|
167
|
+
pagePath: pagePath,
|
|
168
|
+
propsPath: propsPath,
|
|
169
|
+
pageExportName: options.pageExportName,
|
|
170
|
+
propsExportName: options.propsExportName,
|
|
171
|
+
logger: createLogger(),
|
|
145
172
|
});
|
|
146
|
-
|
|
147
173
|
// Create handler for HTML output
|
|
148
|
-
const htmlResult = await createHandler(
|
|
174
|
+
const htmlResult = await createHandler({
|
|
175
|
+
root: options.root,
|
|
176
|
+
url: route,
|
|
177
|
+
route: route,
|
|
178
|
+
getCss: getCss,
|
|
149
179
|
loader: options.loader,
|
|
150
|
-
clientManifest: options.clientManifest,
|
|
151
|
-
serverManifest: options.serverManifest,
|
|
152
180
|
cssFiles: clientCss,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
181
|
+
moduleBase: options.moduleBase,
|
|
182
|
+
moduleBasePath: options.moduleBasePath,
|
|
183
|
+
moduleRootPath: moduleRootPath,
|
|
184
|
+
moduleBaseURL: options.moduleBaseURL,
|
|
185
|
+
pipableStreamOptions: options.pipableStreamOptions,
|
|
186
|
+
inlineCss: options.inlineCss,
|
|
187
|
+
Html: options.Html,
|
|
188
|
+
CssCollector: options.CssCollector,
|
|
189
|
+
pagePath: pagePath,
|
|
190
|
+
propsPath: propsPath,
|
|
191
|
+
pageExportName: options.pageExportName,
|
|
192
|
+
propsExportName: options.propsExportName,
|
|
193
|
+
logger: createLogger(),
|
|
161
194
|
});
|
|
162
195
|
|
|
163
196
|
if (rscResult.type !== "success" || htmlResult.type !== "success") {
|
|
164
|
-
|
|
197
|
+
if (rscResult.type !== "success") {
|
|
198
|
+
if (rscResult.type !== "skip") {
|
|
199
|
+
console.error("Handler failed for route:", route, rscResult.error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (htmlResult.type !== "success") {
|
|
203
|
+
if (htmlResult.type !== "skip") {
|
|
204
|
+
console.error("Handler failed for route:", route, htmlResult.error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
165
207
|
failedRoutes.set(route, new Error(`Handler failed for ${route}`));
|
|
166
208
|
continue;
|
|
167
209
|
}
|
|
168
210
|
|
|
169
211
|
// Process both streams
|
|
170
212
|
await Promise.all([
|
|
171
|
-
//
|
|
213
|
+
// Handle RSC stream
|
|
172
214
|
new Promise<void>((resolve, reject) => {
|
|
173
215
|
const chunks: Buffer[] = [];
|
|
174
216
|
const rscTransform = new Transform({
|
|
175
217
|
transform(chunk, _encoding, callback) {
|
|
176
218
|
try {
|
|
177
|
-
|
|
178
|
-
|
|
219
|
+
if (chunk) {
|
|
220
|
+
chunks.push(Buffer.from(chunk));
|
|
221
|
+
callback(null, chunk);
|
|
222
|
+
}
|
|
179
223
|
} catch (error) {
|
|
180
224
|
callback(error as Error);
|
|
181
225
|
}
|
|
182
226
|
},
|
|
183
|
-
flush(callback) {
|
|
227
|
+
async flush(callback) {
|
|
184
228
|
try {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
callback(error as Error);
|
|
199
|
-
reject(error);
|
|
200
|
-
});
|
|
229
|
+
const rscContent = Buffer.concat(chunks).toString("utf-8");
|
|
230
|
+
|
|
231
|
+
// Update partial page data with raw RSC content
|
|
232
|
+
const partial = partialPageData.get(route) || { route };
|
|
233
|
+
partial.rsc = {
|
|
234
|
+
modules: [], // Will be parsed by the client
|
|
235
|
+
content: rscContent,
|
|
236
|
+
};
|
|
237
|
+
partialPageData.set(route, partial);
|
|
238
|
+
await mergeAndSendPageData(route, resolve);
|
|
239
|
+
|
|
240
|
+
callback();
|
|
241
|
+
resolve();
|
|
201
242
|
} catch (error) {
|
|
202
243
|
callback(error as Error);
|
|
203
244
|
reject(error);
|
|
204
245
|
}
|
|
205
|
-
}
|
|
246
|
+
},
|
|
206
247
|
});
|
|
207
248
|
|
|
208
249
|
rscResult.stream.pipe(rscTransform);
|
|
209
250
|
}),
|
|
210
251
|
|
|
211
252
|
// Send HTML stream to worker
|
|
212
|
-
new Promise<void>((resolve
|
|
253
|
+
new Promise<void>((resolve) => {
|
|
213
254
|
const htmlTransform = new Transform({
|
|
214
255
|
transform(chunk, _encoding, callback) {
|
|
215
256
|
try {
|
|
@@ -217,9 +258,9 @@ export async function renderPages(
|
|
|
217
258
|
type: "RSC_CHUNK",
|
|
218
259
|
id: route,
|
|
219
260
|
chunk: chunk.toString(),
|
|
220
|
-
moduleRootPath:
|
|
261
|
+
moduleRootPath: moduleRootPath,
|
|
221
262
|
moduleBaseURL: options.moduleBaseURL,
|
|
222
|
-
htmlOutputPath:
|
|
263
|
+
htmlOutputPath: options.htmlOutputPath,
|
|
223
264
|
pipableStreamOptions: options.pipableStreamOptions,
|
|
224
265
|
});
|
|
225
266
|
callback(null, chunk);
|
|
@@ -234,18 +275,17 @@ export async function renderPages(
|
|
|
234
275
|
});
|
|
235
276
|
callback();
|
|
236
277
|
resolve();
|
|
237
|
-
}
|
|
278
|
+
},
|
|
238
279
|
});
|
|
239
280
|
|
|
240
281
|
htmlResult.stream.pipe(htmlTransform);
|
|
241
|
-
})
|
|
282
|
+
}),
|
|
242
283
|
]);
|
|
243
284
|
}
|
|
244
285
|
|
|
245
286
|
await allRoutesComplete;
|
|
246
|
-
|
|
247
287
|
} catch (error) {
|
|
248
|
-
console.error(
|
|
288
|
+
console.error("Render error:", error);
|
|
249
289
|
throw error;
|
|
250
290
|
}
|
|
251
291
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# RSC Worker
|
|
2
|
+
|
|
3
|
+
The RSC worker is used by the client plugin to handle React Server Components when the main thread is running without the `react-server` condition. It provides the server-condition capabilities that the client plugin needs but can't access directly.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
The RSC worker serves several key functions:
|
|
8
|
+
|
|
9
|
+
1. **Server Condition Access**: Enables RSC processing in a client-focused environment
|
|
10
|
+
2. **Message-Based Communication**: Handles RSC streaming through a message passing interface
|
|
11
|
+
|
|
12
|
+
## Implementation Details
|
|
13
|
+
|
|
14
|
+
The worker comes in two variants:
|
|
15
|
+
|
|
16
|
+
- `rsc-worker.development.ts`: Full implementation with detailed logging and error handling
|
|
17
|
+
- `rsc-worker.production.ts`: Optimized implementation for production builds
|
|
18
|
+
|
|
19
|
+
## Extending the Worker
|
|
20
|
+
|
|
21
|
+
Users can create their own RSC workers for application-level use. This allows for:
|
|
22
|
+
|
|
23
|
+
1. Custom RSC processing logic
|
|
24
|
+
2. Application-specific message handling
|
|
25
|
+
3. Specialized worker architectures
|
|
26
|
+
|
|
27
|
+
Example of creating a custom RSC worker:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { messageHandler } from 'vite-plugin-react-server/worker/rsc/messageHandler'
|
|
31
|
+
import type { RscWorkerMessage } from 'vite-plugin-react-server/worker/types'
|
|
32
|
+
|
|
33
|
+
// Create your custom message handler
|
|
34
|
+
const customMessageHandler = async (msg: RscWorkerMessage) => {
|
|
35
|
+
// Add your custom logic here
|
|
36
|
+
return messageHandler(msg)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Initialize your worker
|
|
40
|
+
if (typeof WorkerGlobalScope !== 'undefined') {
|
|
41
|
+
parentPort.on('message', customMessageHandler)
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Future Possibilities
|
|
46
|
+
|
|
47
|
+
The RSC worker architecture is designed to be extensible. Future enhancements could include:
|
|
48
|
+
|
|
49
|
+
- Custom streaming strategies
|
|
50
|
+
- Advanced caching mechanisms
|
|
51
|
+
- Specialized RSC processing pipelines
|
|
52
|
+
- Integration with other build tools
|
|
53
|
+
|
|
54
|
+
## Notes
|
|
55
|
+
|
|
56
|
+
- The worker must be initialized with appropriate Node conditions
|
|
57
|
+
- Message handling must account for streaming data
|
|
58
|
+
- Consider memory usage when processing large RSC payloads
|