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.
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/dist/build/createBuildConfig.d.ts +12 -0
- package/dist/build/createBuildConfig.d.ts.map +1 -0
- package/dist/build/createBuildConfig.js +55 -0
- package/dist/build/createBuildConfig.js.map +1 -0
- package/dist/checkFilesExist.d.ts +8 -0
- package/dist/checkFilesExist.d.ts.map +1 -0
- package/dist/checkFilesExist.js +61 -0
- package/dist/checkFilesExist.js.map +1 -0
- package/dist/collect-css-manifest.d.ts +4 -0
- package/dist/collect-css-manifest.d.ts.map +1 -0
- package/dist/collect-css-manifest.js +57 -0
- package/dist/collect-css-manifest.js.map +1 -0
- package/dist/components.d.ts +13 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +13 -0
- package/dist/components.js.map +1 -0
- package/dist/copy-dir.d.ts +4 -0
- package/dist/copy-dir.d.ts.map +1 -0
- package/dist/getEnv.d.ts +19 -0
- package/dist/getEnv.d.ts.map +1 -0
- package/dist/getEnv.js +76 -0
- package/dist/getEnv.js.map +1 -0
- package/dist/helpers/normalizedRelativePath.d.ts +9 -0
- package/dist/helpers/normalizedRelativePath.d.ts.map +1 -0
- package/dist/helpers/normalizedRelativePath.js +31 -0
- package/dist/helpers/normalizedRelativePath.js.map +1 -0
- package/dist/helpers/tryManifest.d.ts +8 -0
- package/dist/helpers/tryManifest.d.ts.map +1 -0
- package/dist/html/createPageLoader.d.ts +26 -0
- package/dist/html/createPageLoader.d.ts.map +1 -0
- package/dist/html/createPageLoader.js +70 -0
- package/dist/html/createPageLoader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +6 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/module-graph.d.ts +10 -0
- package/dist/module-graph.d.ts.map +1 -0
- package/dist/options.d.ts +86 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +251 -0
- package/dist/options.js.map +1 -0
- package/dist/plugin.d.ts +8 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +31 -0
- package/dist/plugin.js.map +1 -0
- package/dist/react-client/plugin.d.ts +4 -0
- package/dist/react-client/plugin.d.ts.map +1 -0
- package/dist/react-client/plugin.js +28 -0
- package/dist/react-client/plugin.js.map +1 -0
- package/dist/react-server/createDevMiddleware.d.ts +8 -0
- package/dist/react-server/createDevMiddleware.d.ts.map +1 -0
- package/dist/react-server/createDevServer.d.ts +4 -0
- package/dist/react-server/createDevServer.d.ts.map +1 -0
- package/dist/react-server/createHandler.d.ts +23 -0
- package/dist/react-server/createHandler.d.ts.map +1 -0
- package/dist/react-server/createHandler.js +110 -0
- package/dist/react-server/createHandler.js.map +1 -0
- package/dist/react-server/createReactNodeStreamer.d.ts +10 -0
- package/dist/react-server/createReactNodeStreamer.d.ts.map +1 -0
- package/dist/react-server/createRscStream.d.ts +4 -0
- package/dist/react-server/createRscStream.d.ts.map +1 -0
- package/dist/react-server/createRscStream.js +47 -0
- package/dist/react-server/createRscStream.js.map +1 -0
- package/dist/react-server/createSsrHandler.d.ts +4 -0
- package/dist/react-server/createSsrHandler.d.ts.map +1 -0
- package/dist/react-server/plugin.d.ts +8 -0
- package/dist/react-server/plugin.d.ts.map +1 -0
- package/dist/react-server/plugin.js +298 -0
- package/dist/react-server/plugin.js.map +1 -0
- package/dist/resolvePage.d.ts +19 -0
- package/dist/resolvePage.d.ts.map +1 -0
- package/dist/resolvePage.js +44 -0
- package/dist/resolvePage.js.map +1 -0
- package/dist/resolveProps.d.ts +19 -0
- package/dist/resolveProps.d.ts.map +1 -0
- package/dist/resolveProps.js +90 -0
- package/dist/resolveProps.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/transformer/index.d.ts +28 -0
- package/dist/transformer/index.d.ts.map +1 -0
- package/dist/transformer/index.js +54 -0
- package/dist/transformer/index.js.map +1 -0
- package/dist/transformer/preserveDirectives.d.ts +4 -0
- package/dist/transformer/preserveDirectives.d.ts.map +1 -0
- package/dist/transformer/preserveDirectives.js +72 -0
- package/dist/transformer/preserveDirectives.js.map +1 -0
- package/dist/transformer/preserver.d.ts +2 -0
- package/dist/transformer/preserver.d.ts.map +1 -0
- package/dist/transformer/transformer.d.ts +30 -0
- package/dist/transformer/transformer.d.ts.map +1 -0
- package/dist/transformer/transformer.js +80 -0
- package/dist/transformer/transformer.js.map +1 -0
- package/dist/transformer/types.d.ts +15 -0
- package/dist/transformer/types.d.ts.map +1 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/worker/createHtmlStream.d.ts +7 -0
- package/dist/worker/createHtmlStream.d.ts.map +1 -0
- package/dist/worker/createWorker.d.ts +3 -0
- package/dist/worker/createWorker.d.ts.map +1 -0
- package/dist/worker/createWorker.js +33 -0
- package/dist/worker/createWorker.js.map +1 -0
- package/dist/worker/loader.d.ts +15 -0
- package/dist/worker/loader.d.ts.map +1 -0
- package/dist/worker/renderPages.d.ts +18 -0
- package/dist/worker/renderPages.d.ts.map +1 -0
- package/dist/worker/renderPages.js +99 -0
- package/dist/worker/renderPages.js.map +1 -0
- package/dist/worker/types.d.ts +31 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/worker.d.ts +7 -0
- package/dist/worker/worker.d.ts.map +1 -0
- package/package.json +116 -0
- package/src/build/createBuildConfig.ts +74 -0
- package/src/checkFilesExist.ts +67 -0
- package/src/collect-css-manifest.ts +76 -0
- package/src/components.tsx +14 -0
- package/src/copy-dir.ts +27 -0
- package/src/getEnv.ts +135 -0
- package/src/helpers/normalizedRelativePath.ts +59 -0
- package/src/helpers/tryManifest.ts +23 -0
- package/src/html/createPageLoader.ts +99 -0
- package/src/index.ts +4 -0
- package/src/manifest.ts +24 -0
- package/src/module-graph.ts +48 -0
- package/src/options.ts +351 -0
- package/src/plugin.ts +31 -0
- package/src/react-client/plugin.ts +34 -0
- package/src/react-server/createDevMiddleware.ts +75 -0
- package/src/react-server/createDevServer.ts +10 -0
- package/src/react-server/createHandler.ts +144 -0
- package/src/react-server/createReactNodeStreamer.ts +25 -0
- package/src/react-server/createRscStream.ts +52 -0
- package/src/react-server/createSsrHandler.ts +147 -0
- package/src/react-server/plugin.ts +349 -0
- package/src/resolvePage.ts +65 -0
- package/src/resolveProps.ts +122 -0
- package/src/server.tsx +0 -0
- package/src/transformer/README.md +44 -0
- package/src/transformer/index.ts +112 -0
- package/src/transformer/preserveDirectives.ts +100 -0
- package/src/transformer/preserver.ts +47 -0
- package/src/transformer/transformer.ts +123 -0
- package/src/transformer/types.ts +15 -0
- package/src/types.ts +245 -0
- package/src/worker/createHtmlStream.ts +76 -0
- package/src/worker/createWorker.ts +39 -0
- package/src/worker/loader.ts +16 -0
- package/src/worker/renderPages.ts +144 -0
- package/src/worker/types.ts +38 -0
- package/src/worker/worker.tsx +136 -0
- package/tsconfig.json +79 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { resolve, join } from "node:path";
|
|
2
|
+
import { Transform } from "node:stream";
|
|
3
|
+
import { createHandler } from "../react-server/createHandler.js";
|
|
4
|
+
async function renderPages(routes, options) {
|
|
5
|
+
const destinationRoot = resolve(
|
|
6
|
+
options.pluginOptions.projectRoot,
|
|
7
|
+
options.outDir
|
|
8
|
+
);
|
|
9
|
+
const failedRoutes = /* @__PURE__ */ new Map();
|
|
10
|
+
const moduleBasePath = join(
|
|
11
|
+
destinationRoot,
|
|
12
|
+
options.pluginOptions.moduleBasePath
|
|
13
|
+
);
|
|
14
|
+
const moduleBaseURL = options.pluginOptions.moduleBaseURL;
|
|
15
|
+
const htmlRoot = resolve(
|
|
16
|
+
options.pluginOptions.projectRoot,
|
|
17
|
+
options.pluginOptions.build?.client ?? options.outDir
|
|
18
|
+
);
|
|
19
|
+
const filesOutputted = [];
|
|
20
|
+
options.worker.on("message", (msg) => {
|
|
21
|
+
switch (msg.type) {
|
|
22
|
+
case "ERROR":
|
|
23
|
+
console.error("[RenderPages] Worker error:", msg.error);
|
|
24
|
+
break;
|
|
25
|
+
case "HTML":
|
|
26
|
+
filesOutputted.push(msg.outputPath);
|
|
27
|
+
if (filesOutputted.length === routes.length) {
|
|
28
|
+
renderPromises.push(
|
|
29
|
+
new Promise((resolve2) => {
|
|
30
|
+
options.worker.removeAllListeners();
|
|
31
|
+
options.worker.terminate();
|
|
32
|
+
resolve2();
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const pipableStreamOptions = options.pipableStreamOptions ?? {};
|
|
40
|
+
const renderPromises = routes.map(async (route) => {
|
|
41
|
+
try {
|
|
42
|
+
const result = await createHandler(route, options.pluginOptions, {
|
|
43
|
+
loader: options.loader,
|
|
44
|
+
manifest: options.manifest
|
|
45
|
+
});
|
|
46
|
+
if (result.type !== "success") {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const htmlOutputPath = join(htmlRoot, route, "index.html");
|
|
50
|
+
await new Promise((resolve2, reject) => {
|
|
51
|
+
const transform = new Transform({
|
|
52
|
+
transform(chunk, _encoding, callback) {
|
|
53
|
+
options.worker.postMessage({
|
|
54
|
+
type: "RSC_CHUNK",
|
|
55
|
+
id: route,
|
|
56
|
+
chunk,
|
|
57
|
+
moduleBasePath,
|
|
58
|
+
moduleBaseURL,
|
|
59
|
+
htmlOutputPath,
|
|
60
|
+
outDir: options.outDir,
|
|
61
|
+
pipableStreamOptions
|
|
62
|
+
});
|
|
63
|
+
callback();
|
|
64
|
+
},
|
|
65
|
+
flush(callback) {
|
|
66
|
+
options.worker.postMessage({
|
|
67
|
+
type: "RSC_END",
|
|
68
|
+
id: route
|
|
69
|
+
});
|
|
70
|
+
callback();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const messageHandler = (msg) => {
|
|
74
|
+
if (msg.route === route) {
|
|
75
|
+
if (msg.type === "ERROR") {
|
|
76
|
+
options.worker.removeListener("message", messageHandler);
|
|
77
|
+
reject(new Error(msg.error));
|
|
78
|
+
} else if (msg.type === "HTML") {
|
|
79
|
+
options.worker.removeListener("message", messageHandler);
|
|
80
|
+
resolve2();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
options.worker.on("message", messageHandler);
|
|
85
|
+
result.stream?.pipe(transform);
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
failedRoutes.set(route, error);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
await Promise.all(renderPromises);
|
|
92
|
+
if (failedRoutes.size > 0) {
|
|
93
|
+
console.error("[vite-react-stream] Failed routes:", failedRoutes);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export {
|
|
97
|
+
renderPages
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=renderPages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderPages.js","sources":["../../src/worker/renderPages.ts"],"sourcesContent":["import { join, resolve as resolvePath } from \"node:path\";\nimport { Transform } from \"node:stream\";\nimport type { Worker } from \"node:worker_threads\";\nimport type { PipeableStreamOptions } from \"react-dom/server.node\";\nimport { createHandler } from \"../react-server/createHandler.js\";\nimport type { StreamPluginOptions } from \"../types.js\";\nimport type {\n WorkerRscChunkMessage,\n WorkerRscEndMessage,\n} from \"./types.js\";\n\ntype RenderPagesOptions = {\n pluginOptions: Required<\n Pick<\n StreamPluginOptions,\n \"moduleBase\" | \"moduleBasePath\" | \"moduleBaseURL\" | \"projectRoot\"\n >\n > &\n Pick<\n StreamPluginOptions,\n \"Page\" | \"props\" | \"build\" | \"Html\" | \"pageExportName\" | \"propsExportName\"\n >;\n outDir: string;\n manifest: Record<string, { file: string }>;\n worker: Worker;\n pipableStreamOptions?: PipeableStreamOptions;\n loader: (id: string) => Promise<Record<string, any>>;\n onCssFile?: (path: string) => void;\n clientCss?: string[];\n};\n\nexport async function renderPages(\n routes: string[],\n options: RenderPagesOptions\n) {\n const destinationRoot = resolvePath(\n options.pluginOptions.projectRoot,\n options.outDir\n );\n const failedRoutes = new Map<string, Error>();\n const moduleBasePath = join(\n destinationRoot,\n options.pluginOptions.moduleBasePath\n );\n const moduleBaseURL = options.pluginOptions.moduleBaseURL;\n\n const htmlRoot = resolvePath(\n options.pluginOptions.projectRoot,\n options.pluginOptions.build?.client ?? options.outDir\n );\n const filesOutputted: string[] = [];\n\n options.worker.on(\"message\", (msg) => {\n switch (msg.type) {\n case \"ERROR\":\n console.error(\"[RenderPages] Worker error:\", msg.error);\n break;\n case \"HTML\":\n filesOutputted.push(msg.outputPath);\n if (filesOutputted.length === routes.length) {\n renderPromises.push(\n new Promise<void>((resolve) => {\n options.worker.removeAllListeners();\n options.worker.terminate();\n resolve();\n })\n );\n }\n break;\n default:\n break;\n }\n });\n const pipableStreamOptions = options.pipableStreamOptions ?? {};\n\n // Create promises for each route in the batch\n const renderPromises = routes.map(async (route) => {\n try {\n // Wait for handler creation\n const result = await createHandler(route, options.pluginOptions, {\n loader: options.loader,\n manifest: options.manifest,\n });\n\n if (result.type !== \"success\") {\n return;\n }\n const htmlOutputPath = join(htmlRoot, route, \"index.html\");\n\n // Create a promise that resolves when the worker completes\n await new Promise<void>((resolve, reject) => {\n // Pipe RSC stream to worker\n const transform = new Transform({\n transform(chunk, _encoding, callback) {\n // Send raw chunk\n options.worker.postMessage({\n type: \"RSC_CHUNK\",\n id: route,\n chunk: chunk,\n moduleBasePath,\n moduleBaseURL,\n htmlOutputPath: htmlOutputPath,\n outDir: options.outDir,\n pipableStreamOptions,\n } satisfies WorkerRscChunkMessage);\n callback();\n },\n flush(callback) {\n options.worker.postMessage({\n type: \"RSC_END\",\n id: route,\n } satisfies WorkerRscEndMessage);\n callback();\n },\n });\n\n // Listen for worker response for this route\n const messageHandler = (msg: any) => {\n if (msg.route === route) {\n if (msg.type === \"ERROR\") {\n options.worker.removeListener(\"message\", messageHandler);\n reject(new Error(msg.error));\n } else if (msg.type === \"HTML\") {\n options.worker.removeListener(\"message\", messageHandler);\n resolve();\n }\n }\n };\n\n options.worker.on(\"message\", messageHandler);\n result.stream?.pipe(transform);\n });\n } catch (error) {\n failedRoutes.set(route, error as Error);\n }\n });\n\n // Wait for all routes to complete\n await Promise.all(renderPromises);\n\n if (failedRoutes.size > 0) {\n console.error(\"[vite-react-stream] Failed routes:\", failedRoutes);\n }\n}\n"],"names":["resolvePath","resolve"],"mappings":";;;AA+BsB,eAAA,YACpB,QACA,SACA;AACA,QAAM,kBAAkBA;AAAAA,IACtB,QAAQ,cAAc;AAAA,IACtB,QAAQ;AAAA,EACV;AACM,QAAA,mCAAmB,IAAmB;AAC5C,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,QAAQ,cAAc;AAAA,EACxB;AACM,QAAA,gBAAgB,QAAQ,cAAc;AAE5C,QAAM,WAAWA;AAAAA,IACf,QAAQ,cAAc;AAAA,IACtB,QAAQ,cAAc,OAAO,UAAU,QAAQ;AAAA,EACjD;AACA,QAAM,iBAA2B,CAAC;AAElC,UAAQ,OAAO,GAAG,WAAW,CAAC,QAAQ;AACpC,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAK;AACK,gBAAA,MAAM,+BAA+B,IAAI,KAAK;AACtD;AAAA,MACF,KAAK;AACY,uBAAA,KAAK,IAAI,UAAU;AAC9B,YAAA,eAAe,WAAW,OAAO,QAAQ;AAC5B,yBAAA;AAAA,YACb,IAAI,QAAc,CAACC,aAAY;AAC7B,sBAAQ,OAAO,mBAAmB;AAClC,sBAAQ,OAAO,UAAU;AACjB,cAAAA,SAAA;AAAA,YACT,CAAA;AAAA,UACH;AAAA,QAAA;AAEF;AAAA,IAEA;AAAA,EACJ,CACD;AACK,QAAA,uBAAuB,QAAQ,wBAAwB,CAAC;AAG9D,QAAM,iBAAiB,OAAO,IAAI,OAAO,UAAU;AAC7C,QAAA;AAEF,YAAM,SAAS,MAAM,cAAc,OAAO,QAAQ,eAAe;AAAA,QAC/D,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,MAAA,CACnB;AAEG,UAAA,OAAO,SAAS,WAAW;AAC7B;AAAA,MAAA;AAEF,YAAM,iBAAiB,KAAK,UAAU,OAAO,YAAY;AAGzD,YAAM,IAAI,QAAc,CAACA,UAAS,WAAW;AAErC,cAAA,YAAY,IAAI,UAAU;AAAA,UAC9B,UAAU,OAAO,WAAW,UAAU;AAEpC,oBAAQ,OAAO,YAAY;AAAA,cACzB,MAAM;AAAA,cACN,IAAI;AAAA,cACJ;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ,QAAQ;AAAA,cAChB;AAAA,YAAA,CAC+B;AACxB,qBAAA;AAAA,UACX;AAAA,UACA,MAAM,UAAU;AACd,oBAAQ,OAAO,YAAY;AAAA,cACzB,MAAM;AAAA,cACN,IAAI;AAAA,YAAA,CACyB;AACtB,qBAAA;AAAA,UAAA;AAAA,QACX,CACD;AAGK,cAAA,iBAAiB,CAAC,QAAa;AAC/B,cAAA,IAAI,UAAU,OAAO;AACnB,gBAAA,IAAI,SAAS,SAAS;AAChB,sBAAA,OAAO,eAAe,WAAW,cAAc;AACvD,qBAAO,IAAI,MAAM,IAAI,KAAK,CAAC;AAAA,YAAA,WAClB,IAAI,SAAS,QAAQ;AACtB,sBAAA,OAAO,eAAe,WAAW,cAAc;AAC/C,cAAAA,SAAA;AAAA,YAAA;AAAA,UACV;AAAA,QAEJ;AAEQ,gBAAA,OAAO,GAAG,WAAW,cAAc;AACpC,eAAA,QAAQ,KAAK,SAAS;AAAA,MAAA,CAC9B;AAAA,aACM,OAAO;AACD,mBAAA,IAAI,OAAO,KAAc;AAAA,IAAA;AAAA,EACxC,CACD;AAGK,QAAA,QAAQ,IAAI,cAAc;AAE5B,MAAA,aAAa,OAAO,GAAG;AACjB,YAAA,MAAM,sCAAsC,YAAY;AAAA,EAAA;AAEpE;"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PipeableStreamOptions } from "react-dom/server.node";
|
|
2
|
+
export interface RenderState {
|
|
3
|
+
chunks: string[];
|
|
4
|
+
complete: boolean;
|
|
5
|
+
rendered: boolean;
|
|
6
|
+
outDir: string;
|
|
7
|
+
moduleBasePath: string;
|
|
8
|
+
moduleBaseURL: string;
|
|
9
|
+
htmlOutputPath: string;
|
|
10
|
+
id: string;
|
|
11
|
+
pipableStreamOptions: PipeableStreamOptions;
|
|
12
|
+
}
|
|
13
|
+
export interface WorkerRscChunkMessage {
|
|
14
|
+
type: "RSC_CHUNK";
|
|
15
|
+
id: string;
|
|
16
|
+
chunk: string;
|
|
17
|
+
moduleBasePath: string;
|
|
18
|
+
moduleBaseURL: string;
|
|
19
|
+
outDir: string;
|
|
20
|
+
htmlOutputPath: string;
|
|
21
|
+
pipableStreamOptions: PipeableStreamOptions;
|
|
22
|
+
}
|
|
23
|
+
export interface WorkerRscEndMessage {
|
|
24
|
+
type: "RSC_END";
|
|
25
|
+
id: string;
|
|
26
|
+
}
|
|
27
|
+
export interface WorkerShutdownMessage {
|
|
28
|
+
type: "SHUTDOWN";
|
|
29
|
+
}
|
|
30
|
+
export type WorkerMessage = WorkerRscChunkMessage | WorkerRscEndMessage | WorkerShutdownMessage;
|
|
31
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/worker/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB,EAAE,qBAAqB,CAAC;CAC7C;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,qBAAqB,CAAC;CAC7C;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GACrB,qBAAqB,GACrB,mBAAmB,GACnB,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker/worker.tsx"],"names":[],"mappings":"AAaA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,IAAI,EAAE,MAAM,CAAC;KACd;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vite-plugin-react-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vite plugin for React Server Components (RSC)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"tsconfig.json"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"react-server": "./dist/react-server/plugin.js",
|
|
21
|
+
"default": "./dist/react-client/plugin.js"
|
|
22
|
+
},
|
|
23
|
+
"./client": {
|
|
24
|
+
"types": "./dist/react-client/plugin.d.ts",
|
|
25
|
+
"import": "./dist/react-client/plugin.js",
|
|
26
|
+
"default": "./dist/react-client/plugin.js"
|
|
27
|
+
},
|
|
28
|
+
"./server": {
|
|
29
|
+
"types": "./dist/react-server/plugin.d.ts",
|
|
30
|
+
"import": "./dist/react-server/plugin.js",
|
|
31
|
+
"react-server": "./dist/react-server/plugin.js",
|
|
32
|
+
"default": "./dist/react-server/plugin.js"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"typesVersions": {
|
|
37
|
+
"*": {
|
|
38
|
+
".": [
|
|
39
|
+
"./dist/index.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"client": [
|
|
42
|
+
"./dist/react-client/plugin.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"server": [
|
|
45
|
+
"./dist/react-server/plugin.d.ts"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"sideEffects": false,
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "npm run clean && npm run build:types && npm run build:vite",
|
|
52
|
+
"build:types": "tsc --build --force",
|
|
53
|
+
"build:vite": "vite build",
|
|
54
|
+
"clean": "rm -rf dist",
|
|
55
|
+
"prepublishOnly": "npm run build",
|
|
56
|
+
"lint": "eslint ./src --fix",
|
|
57
|
+
"test:server": "NODE_OPTIONS='--conditions react-server' vitest run",
|
|
58
|
+
"test:client": "vitest run",
|
|
59
|
+
"test": "npm run test:client && npm run test:server",
|
|
60
|
+
"test:coverage": "vitest run --coverage",
|
|
61
|
+
"test:ui": "vitest --ui",
|
|
62
|
+
"copy-oss": "cp -r ./oss-experimental/* ./node_modules/",
|
|
63
|
+
"patch-oss": "npx patch-package react-server-dom-esm --exclude 'nothing' && npx patch-package react react-dom",
|
|
64
|
+
"apply-patch": "npm run copy-oss && npm run patch-oss",
|
|
65
|
+
"postinstall": "patch-package",
|
|
66
|
+
"publish": "npm run postinstall && npm run build && npm publish"
|
|
67
|
+
},
|
|
68
|
+
"keywords": [
|
|
69
|
+
"vite",
|
|
70
|
+
"vite-plugin",
|
|
71
|
+
"react",
|
|
72
|
+
"rsc",
|
|
73
|
+
"server-components"
|
|
74
|
+
],
|
|
75
|
+
"author": "Nico Brinkkemper",
|
|
76
|
+
"license": "MIT",
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": "^20.0.0 || >=21.0.0"
|
|
79
|
+
},
|
|
80
|
+
"repository": {
|
|
81
|
+
"type": "git",
|
|
82
|
+
"url": "git+https://github.com/nicobrinkkemper/vite-plugin-react-server.git"
|
|
83
|
+
},
|
|
84
|
+
"bugs": {
|
|
85
|
+
"url": "https://github.com/nicobrinkkemper/vite-plugin-react-server/issues"
|
|
86
|
+
},
|
|
87
|
+
"homepage": "https://github.com/nicobrinkkemper/vite-plugin-react-server#readme",
|
|
88
|
+
"peerDependencies": {
|
|
89
|
+
"react": "^19.0.0",
|
|
90
|
+
"react-dom": "^19.0.0",
|
|
91
|
+
"vite": "^5.0.0"
|
|
92
|
+
},
|
|
93
|
+
"peerDependenciesMeta": {
|
|
94
|
+
"react": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"react-dom": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"devDependencies": {
|
|
102
|
+
"@types/node": "^20.17.16",
|
|
103
|
+
"@types/react": "^19.0.8",
|
|
104
|
+
"@types/react-dom": "^19.0.3",
|
|
105
|
+
"acorn-loose": "^8.3.0",
|
|
106
|
+
"patch-package": "^8.0.0",
|
|
107
|
+
"react": "^19.0.0",
|
|
108
|
+
"react-dom": "^19.0.0",
|
|
109
|
+
"react-server-dom-esm": "^0.0.1",
|
|
110
|
+
"source-map": "^0.7.4",
|
|
111
|
+
"typescript": "^5.7.3",
|
|
112
|
+
"vite": "^5.4.14",
|
|
113
|
+
"vitest": "^3.0.4",
|
|
114
|
+
"webpack-sources": "^3.2.0"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import type { InlineConfig } from "vite";
|
|
4
|
+
import { DEFAULT_CONFIG } from "../options.js";
|
|
5
|
+
import type { StreamPluginOptions } from "../types.js";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
type CreateBuildConfigOptions = {
|
|
9
|
+
root: string;
|
|
10
|
+
base: string;
|
|
11
|
+
outDir: string;
|
|
12
|
+
entries: string[];
|
|
13
|
+
options?: StreamPluginOptions;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function createBuildConfig({
|
|
17
|
+
root,
|
|
18
|
+
base,
|
|
19
|
+
outDir,
|
|
20
|
+
entries,
|
|
21
|
+
options,
|
|
22
|
+
}: CreateBuildConfigOptions) {
|
|
23
|
+
// Transform entries into proper input format with unique keys
|
|
24
|
+
const entryInputs = Object.fromEntries(
|
|
25
|
+
entries.map((entry) => {
|
|
26
|
+
// Get the path relative to root
|
|
27
|
+
const relativePath = entry.replace(root + "/", "");
|
|
28
|
+
// Create a unique key based on the full path
|
|
29
|
+
const key = relativePath.replace(/\.[^/.]+$/, ""); // Remove extension
|
|
30
|
+
|
|
31
|
+
return [key, entry];
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const workerPath = options?.workerPath
|
|
36
|
+
? resolve(root, options.workerPath)
|
|
37
|
+
: resolve(__dirname, "..", DEFAULT_CONFIG.WORKER_PATH);
|
|
38
|
+
|
|
39
|
+
const loaderPath = options?.loaderPath
|
|
40
|
+
? resolve(root, options.loaderPath)
|
|
41
|
+
: resolve(__dirname, "..", DEFAULT_CONFIG.LOADER_PATH);
|
|
42
|
+
|
|
43
|
+
const config: InlineConfig = {
|
|
44
|
+
configFile: false,
|
|
45
|
+
root,
|
|
46
|
+
base,
|
|
47
|
+
build: {
|
|
48
|
+
target: "node18",
|
|
49
|
+
ssr: true,
|
|
50
|
+
ssrEmitAssets: false,
|
|
51
|
+
manifest: true,
|
|
52
|
+
ssrManifest: true,
|
|
53
|
+
outDir,
|
|
54
|
+
rollupOptions: {
|
|
55
|
+
input: {
|
|
56
|
+
...entryInputs,
|
|
57
|
+
worker: workerPath,
|
|
58
|
+
loader: loaderPath,
|
|
59
|
+
},
|
|
60
|
+
output: {
|
|
61
|
+
format: "esm",
|
|
62
|
+
preserveModules: true,
|
|
63
|
+
hoistTransitiveImports: false,
|
|
64
|
+
esModule: true,
|
|
65
|
+
entryFileNames: "[name].js",
|
|
66
|
+
chunkFileNames: "[name].js",
|
|
67
|
+
assetFileNames: "[name][extname]",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return config;
|
|
74
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import type { StreamPluginOptions } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export async function checkFilesExist(
|
|
6
|
+
pages: string[],
|
|
7
|
+
options: Pick<StreamPluginOptions, "Page" | "props">,
|
|
8
|
+
root: string
|
|
9
|
+
) {
|
|
10
|
+
const errors: string[] = [];
|
|
11
|
+
const pageSet = new Set<string>();
|
|
12
|
+
const pageMap = new Map<string, string>();
|
|
13
|
+
// Check if files exist when string paths are provided
|
|
14
|
+
if (typeof options.Page === "string") {
|
|
15
|
+
const pagePath = resolve(root, options.Page);
|
|
16
|
+
pageMap.set(options.Page, pagePath);
|
|
17
|
+
if (!pageSet.has(pagePath)) {
|
|
18
|
+
if (!existsSync(pagePath)) {
|
|
19
|
+
errors.push(`Page file not found: ${pagePath}`);
|
|
20
|
+
}
|
|
21
|
+
pageSet.add(pagePath);
|
|
22
|
+
}
|
|
23
|
+
} else if (typeof options.Page === "function" && pages) {
|
|
24
|
+
for (const page of pages) {
|
|
25
|
+
const pagePath = options.Page(resolve(root, page));
|
|
26
|
+
pageMap.set(page, pagePath);
|
|
27
|
+
if (pageSet.has(pagePath)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (!existsSync(pagePath)) {
|
|
31
|
+
errors.push(`Page file not found: ${pagePath}`);
|
|
32
|
+
}
|
|
33
|
+
pageSet.add(pagePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const propsSet = new Set<string>();
|
|
38
|
+
const propsMap = new Map<string, string>();
|
|
39
|
+
if (typeof options.props === "string") {
|
|
40
|
+
const propsPath = resolve(root, options.props);
|
|
41
|
+
propsMap.set(options.props, propsPath);
|
|
42
|
+
if (!propsSet.has(propsPath)) {
|
|
43
|
+
if (!existsSync(propsPath)) {
|
|
44
|
+
errors.push(`Props file not found: ${propsPath}`);
|
|
45
|
+
}
|
|
46
|
+
propsSet.add(propsPath);
|
|
47
|
+
}
|
|
48
|
+
} else if (typeof options.props === "function" && pages) {
|
|
49
|
+
for (const page of pages) {
|
|
50
|
+
const propsPath = options.props(resolve(root, page));
|
|
51
|
+
propsMap.set(page, propsPath);
|
|
52
|
+
if (propsSet.has(propsPath)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (!existsSync(propsPath)) {
|
|
56
|
+
errors.push(`Props file not found: ${propsPath}`);
|
|
57
|
+
}
|
|
58
|
+
propsSet.add(propsPath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (errors.length) {
|
|
63
|
+
throw new Error("React Stream Plugin Validation:\n" + errors.join("\n"));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { pageMap, pageSet, propsMap, propsSet };
|
|
67
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Manifest, ModuleGraph } from "vite";
|
|
2
|
+
|
|
3
|
+
export async function collectModuleGraphCss(
|
|
4
|
+
moduleGraph: ModuleGraph,
|
|
5
|
+
pagePath: string
|
|
6
|
+
) {
|
|
7
|
+
if (!pagePath) return new Map<string, string>();
|
|
8
|
+
|
|
9
|
+
const cssFiles = new Map<string, string>();
|
|
10
|
+
const pageModule = await moduleGraph.getModuleByUrl(pagePath, true);
|
|
11
|
+
if (!pageModule) {
|
|
12
|
+
return new Map<string, string>();
|
|
13
|
+
}
|
|
14
|
+
const seen = new Set<string>();
|
|
15
|
+
const walkModule = (mod: any) => {
|
|
16
|
+
if (!mod?.id || seen.has(mod.id)) return;
|
|
17
|
+
seen.add(mod.id);
|
|
18
|
+
if (mod?.id?.endsWith(".css")) {
|
|
19
|
+
cssFiles.set(mod?.url, mod?.id);
|
|
20
|
+
}
|
|
21
|
+
mod?.importedModules?.forEach((imp: any) => walkModule(imp));
|
|
22
|
+
};
|
|
23
|
+
walkModule(pageModule);
|
|
24
|
+
return cssFiles;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function collectManifestCss(
|
|
28
|
+
manifest: Manifest,
|
|
29
|
+
root: string,
|
|
30
|
+
pagePath: string,
|
|
31
|
+
onCss?: (path: string) => void
|
|
32
|
+
) {
|
|
33
|
+
const relativePagePath = pagePath.startsWith(root + "/")
|
|
34
|
+
? pagePath.slice(root.length + 1)
|
|
35
|
+
: pagePath;
|
|
36
|
+
if (!relativePagePath) return new Map<string, string>();
|
|
37
|
+
const cssFiles = new Map<string, string>();
|
|
38
|
+
const seen = new Set<string>();
|
|
39
|
+
|
|
40
|
+
const walkManifestEntry = (id: string) => {
|
|
41
|
+
if (seen.has(id)) return;
|
|
42
|
+
seen.add(id);
|
|
43
|
+
if (id.endsWith(".css")) {
|
|
44
|
+
cssFiles.set(id, id);
|
|
45
|
+
onCss?.(id);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Get the manifest entry
|
|
49
|
+
const entry = manifest[id];
|
|
50
|
+
if (!entry) return;
|
|
51
|
+
|
|
52
|
+
// Add direct CSS
|
|
53
|
+
if (entry.css) {
|
|
54
|
+
entry.css.forEach((css: string) => {
|
|
55
|
+
cssFiles.set(entry.file, css);
|
|
56
|
+
onCss?.(css);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Walk imports recursively
|
|
61
|
+
if (entry.imports) {
|
|
62
|
+
entry.imports.forEach((imp: string) => walkManifestEntry(imp));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Also check dynamicImports
|
|
66
|
+
if (entry.dynamicImports) {
|
|
67
|
+
entry.dynamicImports.forEach((imp: string) => walkManifestEntry(imp));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (manifest[relativePagePath]) {
|
|
72
|
+
walkManifestEntry(relativePagePath);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return cssFiles;
|
|
76
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A component that emits <link> tags for CSS files during streaming.
|
|
5
|
+
* The high precedence ensures they bubble up to the document head.
|
|
6
|
+
*/
|
|
7
|
+
export function CssCollector({ url }: { url: string }) {
|
|
8
|
+
return createElement('link', {
|
|
9
|
+
key: url,
|
|
10
|
+
rel: 'stylesheet',
|
|
11
|
+
href: url,
|
|
12
|
+
precedence: 'high'
|
|
13
|
+
});
|
|
14
|
+
}
|
package/src/copy-dir.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { copyFileSync, mkdirSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
export async function copyDir(src: string, dest: string, options?: {
|
|
5
|
+
filter?: (file: string) => boolean
|
|
6
|
+
}) {
|
|
7
|
+
const entries = readdirSync(src);
|
|
8
|
+
|
|
9
|
+
mkdirSync(dest, { recursive: true });
|
|
10
|
+
|
|
11
|
+
for (const entry of entries) {
|
|
12
|
+
const srcPath = join(src, entry);
|
|
13
|
+
const destPath = join(dest, entry);
|
|
14
|
+
|
|
15
|
+
const stat = statSync(srcPath);
|
|
16
|
+
|
|
17
|
+
if (options?.filter && !options.filter(srcPath)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (stat.isDirectory()) {
|
|
22
|
+
await copyDir(srcPath, destPath, options);
|
|
23
|
+
} else {
|
|
24
|
+
copyFileSync(srcPath, destPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/getEnv.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import type { ConfigEnv, UserConfig } from "vite";
|
|
4
|
+
import { loadEnv } from "vite";
|
|
5
|
+
import { DEFAULT_CONFIG } from "./options.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get environment variables for Vite, sets defaults to ensure the server can start with BASE_URL and PUBLIC_URL
|
|
9
|
+
*
|
|
10
|
+
* @param config - Vite configuration object
|
|
11
|
+
* @param { isPreview: boolean } - Object containing a boolean indicating if the environment is for preview
|
|
12
|
+
* @returns An object containing the environment variables
|
|
13
|
+
*/
|
|
14
|
+
export function getEnv(config: UserConfig, configEnv: ConfigEnv) {
|
|
15
|
+
const isLocal =
|
|
16
|
+
config.mode === "development"
|
|
17
|
+
|
|
18
|
+
const envName = isLocal
|
|
19
|
+
? `${config.mode}.local`
|
|
20
|
+
: config.mode
|
|
21
|
+
? config.mode
|
|
22
|
+
: "production";
|
|
23
|
+
const environmentName = config.mode ?? envName ?? "production";
|
|
24
|
+
|
|
25
|
+
const env = loadEnv(
|
|
26
|
+
environmentName,
|
|
27
|
+
config.envDir ?? config.root ?? process.cwd(),
|
|
28
|
+
config.envPrefix ?? DEFAULT_CONFIG.ENV_PREFIX ?? "VITE_"
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// Get server config
|
|
32
|
+
const serverConfig = config.server || {};
|
|
33
|
+
const previewConfig = config.preview || {};
|
|
34
|
+
const host = configEnv.isPreview
|
|
35
|
+
? previewConfig.host ?? DEFAULT_CONFIG.PREVIEW_HOST
|
|
36
|
+
: serverConfig.host ?? DEFAULT_CONFIG.DEV_HOST;
|
|
37
|
+
let previewPort = previewConfig.port ?? DEFAULT_CONFIG.PREVIEW_PORT;
|
|
38
|
+
let devPort = serverConfig.port ?? DEFAULT_CONFIG.DEV_PORT;
|
|
39
|
+
|
|
40
|
+
let homepage = env["VITE_BASE_URL"]
|
|
41
|
+
if (configEnv.command === "build" && (!homepage || homepage === "")) {
|
|
42
|
+
try {
|
|
43
|
+
const packageJson = JSON.parse(
|
|
44
|
+
readFileSync(resolve(config.root ?? "", "package.json"), "utf-8")
|
|
45
|
+
);
|
|
46
|
+
homepage = packageJson.homepage ?? "";
|
|
47
|
+
if (!homepage || homepage === "") {
|
|
48
|
+
console.warn(
|
|
49
|
+
"[RSC] 🔧 For production builds, please set 'homepage' in package.json, or set VITE_BASE_URL in your environment"
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error(e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let baseUrl =
|
|
58
|
+
env["VITE_BASE_URL"] && env["VITE_PUBLIC_URL"] !== ""
|
|
59
|
+
? env["VITE_BASE_URL"]
|
|
60
|
+
: configEnv.isPreview
|
|
61
|
+
? `http://${host}:${previewPort}`
|
|
62
|
+
: configEnv.command === "serve"
|
|
63
|
+
? `http://${host}:${devPort}`
|
|
64
|
+
: homepage;
|
|
65
|
+
|
|
66
|
+
let publicUrl =
|
|
67
|
+
env["VITE_PUBLIC_URL"] && env["VITE_PUBLIC_URL"] !== ""
|
|
68
|
+
? env["VITE_PUBLIC_URL"]
|
|
69
|
+
: "";
|
|
70
|
+
|
|
71
|
+
// Determine port and host based on mode
|
|
72
|
+
const port = configEnv.isPreview
|
|
73
|
+
? previewConfig.port || DEFAULT_CONFIG.PREVIEW_PORT // Preview server
|
|
74
|
+
: serverConfig.port || DEFAULT_CONFIG.DEV_PORT; // Dev server
|
|
75
|
+
|
|
76
|
+
// Build base URL
|
|
77
|
+
if (configEnv.isPreview && `http://${host}:${port}` !== baseUrl) {
|
|
78
|
+
console.log(
|
|
79
|
+
`VITE_BASE_URL: \"${baseUrl}\" wasn't configured correctly for this server, overriding to: \"http://${host}:${port}\"`
|
|
80
|
+
);
|
|
81
|
+
baseUrl = `http://${host}:${port}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const envPrefix =
|
|
85
|
+
typeof config.envPrefix === "string"
|
|
86
|
+
? config.envPrefix
|
|
87
|
+
: Array.isArray(config.envPrefix)
|
|
88
|
+
? config.envPrefix[0]
|
|
89
|
+
: DEFAULT_CONFIG.ENV_PREFIX;
|
|
90
|
+
|
|
91
|
+
const nodeProcessEnv = {
|
|
92
|
+
NODE_ENV: configEnv.command === "build" ? "production" : "development",
|
|
93
|
+
};
|
|
94
|
+
const defineProcess = Object.entries(nodeProcessEnv)
|
|
95
|
+
.map(([key, value]) => {
|
|
96
|
+
switch (key) {
|
|
97
|
+
case "NODE_ENV":
|
|
98
|
+
const isDev =
|
|
99
|
+
value === ""
|
|
100
|
+
? configEnv.command === "build"
|
|
101
|
+
? false
|
|
102
|
+
: true
|
|
103
|
+
: value === "development";
|
|
104
|
+
return [`import.meta.env.DEV`, JSON.stringify(isDev)];
|
|
105
|
+
default:
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
.filter(Array.isArray);
|
|
110
|
+
|
|
111
|
+
const defineImportMeta = Object.entries(env).map(([key, value]) => [
|
|
112
|
+
`import.meta.env.${key}`,
|
|
113
|
+
key === "VITE_BASE_URL"
|
|
114
|
+
? value
|
|
115
|
+
? JSON.stringify(value)
|
|
116
|
+
: JSON.stringify(baseUrl)
|
|
117
|
+
: key === "VITE_PUBLIC_URL"
|
|
118
|
+
? value
|
|
119
|
+
? JSON.stringify(value)
|
|
120
|
+
: JSON.stringify(publicUrl)
|
|
121
|
+
: JSON.stringify(value),
|
|
122
|
+
]);
|
|
123
|
+
const define = Object.fromEntries([...defineProcess, ...defineImportMeta]);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
baseUrl,
|
|
127
|
+
publicUrl,
|
|
128
|
+
port,
|
|
129
|
+
host,
|
|
130
|
+
envPrefix,
|
|
131
|
+
environmentName,
|
|
132
|
+
env,
|
|
133
|
+
define,
|
|
134
|
+
};
|
|
135
|
+
}
|