vite-plugin-react-server 0.3.18 → 0.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -118
- package/bin/patch.mjs +8 -2
- package/dist/package.json +3 -3
- 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 +117 -0
- package/dist/plugin/collect-manifest-client-files.js.map +1 -0
- package/dist/plugin/components.d.ts +9 -9
- package/dist/plugin/components.d.ts.map +1 -1
- package/dist/plugin/components.js +50 -9
- package/dist/plugin/components.js.map +1 -0
- package/dist/plugin/config/defaults.d.ts +7 -6
- package/dist/plugin/config/defaults.d.ts.map +1 -1
- package/dist/plugin/config/defaults.js +8 -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 +1 -1
- package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
- package/dist/plugin/config/resolveOptions.js +41 -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 +10 -5
- 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/helpers/createHandler.d.ts +22 -0
- package/dist/plugin/helpers/createHandler.d.ts.map +1 -0
- package/dist/plugin/{react-server → helpers}/createHandler.js +36 -48
- package/dist/plugin/helpers/createHandler.js.map +1 -0
- package/dist/plugin/{react-server → helpers}/createRscStream.d.ts +2 -1
- package/dist/plugin/helpers/createRscStream.d.ts.map +1 -0
- package/dist/plugin/helpers/createRscStream.js +71 -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/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 +18 -76
- 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 +53 -217
- 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 +199 -0
- package/dist/plugin/react-static/plugin.js.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 +24 -6
- 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 +8 -2
- package/dist/plugin/worker/html/messageHandler.js.map +1 -1
- package/dist/plugin/worker/html/plugin.d.ts.map +1 -1
- package/dist/plugin/worker/html/plugin.js +2 -3
- package/dist/plugin/worker/html/renderPages.d.ts +8 -4
- package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
- package/dist/plugin/worker/html/renderPages.js +118 -83
- 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 +89 -84
- package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
- package/dist/plugin/worker/rsc/plugin.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/plugin.js +1 -2
- 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/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/plugin/checkFilesExist.ts +7 -3
- package/plugin/collect-manifest-client-files.ts +152 -0
- package/plugin/components.tsx +55 -10
- package/plugin/config/defaults.tsx +69 -0
- package/plugin/config/getPaths.ts +1 -7
- package/plugin/config/mimeTypes.ts +17 -0
- package/plugin/config/resolveOptions.ts +48 -40
- package/plugin/config/resolvePages.ts +8 -4
- package/plugin/config/resolveUserConfig.ts +12 -9
- package/plugin/{react-server → helpers}/createHandler.ts +46 -63
- package/plugin/helpers/createRscStream.ts +81 -0
- package/plugin/helpers/getBundleManifest.ts +14 -5
- 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 +20 -91
- package/plugin/react-server/index.ts +2 -0
- package/plugin/react-server/plugin.ts +66 -293
- package/plugin/react-static/index.ts +1 -0
- package/plugin/react-static/plugin.ts +247 -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 +25 -6
- 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 +8 -2
- package/plugin/worker/html/plugin.ts +2 -3
- package/plugin/worker/html/renderPages.ts +150 -114
- package/plugin/worker/rsc/README.md +58 -0
- package/plugin/worker/rsc/messageHandler.tsx +95 -111
- package/plugin/worker/rsc/plugin.ts +1 -2
- 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/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/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/messageHandler.js +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/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.map +0 -1
- 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/plugin/collect-css-manifest.ts +0 -82
- package/plugin/config/createModuleIdGenerator.ts +0 -52
- package/plugin/config/defaults.ts +0 -51
- 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/react-server/createRscStream.ts +0 -86
- package/plugin/react-server/createSsrHandler.ts +0 -125
- package/plugin/utils/logger.ts +0 -52
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { join, dirname } from "node:path";
|
|
2
|
+
import { Worker } from "node:worker_threads";
|
|
3
|
+
import {
|
|
4
|
+
type ResolvedConfig,
|
|
5
|
+
type UserConfig,
|
|
6
|
+
type Manifest,
|
|
7
|
+
type IndexHtmlTransformHook,
|
|
8
|
+
type Plugin as VitePlugin,
|
|
9
|
+
} from "vite";
|
|
10
|
+
import { checkFilesExist } from "../checkFilesExist.js";
|
|
11
|
+
import { resolveOptions } from "../config/resolveOptions.js";
|
|
12
|
+
import { resolvePages } from "../config/resolvePages.js";
|
|
13
|
+
import { resolveUserConfig } from "../config/resolveUserConfig.js";
|
|
14
|
+
import { tryManifest } from "../helpers/tryManifest.js";
|
|
15
|
+
import { createBuildLoader } from "../loader/createBuildLoader.js";
|
|
16
|
+
import type {
|
|
17
|
+
BuildTiming,
|
|
18
|
+
CheckFilesExistReturn,
|
|
19
|
+
ReactStreamPluginMeta,
|
|
20
|
+
ResolvedUserConfig,
|
|
21
|
+
ResolvedUserOptions,
|
|
22
|
+
} from "../types.js";
|
|
23
|
+
import { type StreamPluginOptions } from "../types.js";
|
|
24
|
+
import { createWorker } from "../worker/createWorker.js";
|
|
25
|
+
import { renderPages } from "../worker/html/renderPages.js";
|
|
26
|
+
import { mkdir } from "node:fs/promises";
|
|
27
|
+
import { collectManifestClientFiles } from "../collect-manifest-client-files.js";
|
|
28
|
+
import { mkdirSync, copyFileSync } from "node:fs";
|
|
29
|
+
import { copyDir } from "../copy-dir.js";
|
|
30
|
+
|
|
31
|
+
let resolvedConfig: ResolvedConfig | null = null;
|
|
32
|
+
let loader: ((id: string) => Promise<Record<string, any>>) | null = null;
|
|
33
|
+
let worker: Worker;
|
|
34
|
+
let htmlTransform: IndexHtmlTransformHook | null = null;
|
|
35
|
+
let clientAssets = new Set<string>();
|
|
36
|
+
|
|
37
|
+
export function reactStaticPlugin(options: StreamPluginOptions): VitePlugin<{
|
|
38
|
+
meta: ReactStreamPluginMeta;
|
|
39
|
+
}> {
|
|
40
|
+
const timing: BuildTiming = {
|
|
41
|
+
start: Date.now(),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
let files: CheckFilesExistReturn;
|
|
45
|
+
let root: string = process.cwd();
|
|
46
|
+
let userConfig: ResolvedUserConfig;
|
|
47
|
+
let userOptions: ResolvedUserOptions;
|
|
48
|
+
let resolvedPages: string[];
|
|
49
|
+
let serverManifest: Manifest = {};
|
|
50
|
+
let clientManifest: Manifest = {};
|
|
51
|
+
|
|
52
|
+
const resolvedOptions = resolveOptions(options, false);
|
|
53
|
+
if (resolvedOptions.type === "error") {
|
|
54
|
+
throw resolvedOptions.error;
|
|
55
|
+
}
|
|
56
|
+
userOptions = resolvedOptions.userOptions;
|
|
57
|
+
if (
|
|
58
|
+
userOptions.projectRoot != root &&
|
|
59
|
+
typeof userOptions.projectRoot === "string" &&
|
|
60
|
+
userOptions.projectRoot !== process.cwd() &&
|
|
61
|
+
userOptions.projectRoot !== ""
|
|
62
|
+
) {
|
|
63
|
+
root = userOptions.projectRoot;
|
|
64
|
+
console.log(
|
|
65
|
+
"[vite:plugin-react-server] Root dir changed in plugin",
|
|
66
|
+
userOptions.projectRoot,
|
|
67
|
+
root
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
name: "vite:plugin-react-server/static",
|
|
73
|
+
enforce: "post",
|
|
74
|
+
api: {
|
|
75
|
+
meta: { timing },
|
|
76
|
+
},
|
|
77
|
+
async config(config, configEnv): Promise<UserConfig> {
|
|
78
|
+
if (
|
|
79
|
+
typeof config.root === "string" &&
|
|
80
|
+
config.root !== root &&
|
|
81
|
+
config.root !== process.cwd() &&
|
|
82
|
+
config.root !== ""
|
|
83
|
+
) {
|
|
84
|
+
root = config.root;
|
|
85
|
+
}
|
|
86
|
+
const resolvedPagesResult = await resolvePages(userOptions.build.pages);
|
|
87
|
+
if (resolvedPagesResult.type === "error") {
|
|
88
|
+
throw resolvedPagesResult.error;
|
|
89
|
+
}
|
|
90
|
+
resolvedPages = resolvedPagesResult.pages;
|
|
91
|
+
files = await checkFilesExist(resolvedPages, userOptions, root);
|
|
92
|
+
|
|
93
|
+
const resolvedConfig = resolveUserConfig({
|
|
94
|
+
isStatic: true,
|
|
95
|
+
config,
|
|
96
|
+
configEnv,
|
|
97
|
+
userOptions,
|
|
98
|
+
files,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (resolvedConfig.type === "error") {
|
|
102
|
+
throw resolvedConfig.error;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
userConfig = resolvedConfig.userConfig;
|
|
106
|
+
timing.configResolved = Date.now();
|
|
107
|
+
return {};
|
|
108
|
+
},
|
|
109
|
+
async buildStart() {
|
|
110
|
+
timing.buildStart = Date.now();
|
|
111
|
+
},
|
|
112
|
+
async closeBundle() {
|
|
113
|
+
timing.renderStart = Date.now();
|
|
114
|
+
|
|
115
|
+
// Create the loader
|
|
116
|
+
const serverManifestResult = tryManifest({
|
|
117
|
+
root: root,
|
|
118
|
+
outDir: join(userOptions.build.outDir, userOptions.build.server),
|
|
119
|
+
ssrManifest: false,
|
|
120
|
+
});
|
|
121
|
+
if (serverManifestResult.type === "error") {
|
|
122
|
+
throw serverManifestResult.error;
|
|
123
|
+
}
|
|
124
|
+
serverManifest = serverManifestResult.manifest;
|
|
125
|
+
|
|
126
|
+
// Get the client manifest
|
|
127
|
+
const clientManifestResult = tryManifest({
|
|
128
|
+
root: root,
|
|
129
|
+
outDir: join(userOptions.build.outDir, userOptions.build.client),
|
|
130
|
+
ssrManifest: false,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (clientManifestResult.type === "error") {
|
|
134
|
+
throw clientManifestResult.error;
|
|
135
|
+
}
|
|
136
|
+
clientManifest = clientManifestResult.manifest;
|
|
137
|
+
|
|
138
|
+
// Ensure static directory exists
|
|
139
|
+
const staticDir = join(root, userOptions.build.outDir, userOptions.build.static);
|
|
140
|
+
await mkdir(staticDir, { recursive: true });
|
|
141
|
+
|
|
142
|
+
worker = await createWorker({
|
|
143
|
+
projectRoot: root,
|
|
144
|
+
workerPath: userOptions.htmlWorkerPath,
|
|
145
|
+
condition: "react-server",
|
|
146
|
+
reverseCondition: true,
|
|
147
|
+
mode: (resolvedConfig?.mode ?? "production") as "production" | "development",
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
if (typeof loader !== "function") {
|
|
151
|
+
loader = createBuildLoader({
|
|
152
|
+
root: root,
|
|
153
|
+
userConfig,
|
|
154
|
+
userOptions,
|
|
155
|
+
pluginContext: this,
|
|
156
|
+
serverManifest,
|
|
157
|
+
clientManifest,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Collect CSS files per route
|
|
162
|
+
const routeCssMap = new Map<string, Set<string>>();
|
|
163
|
+
const globalCss = new Set<string>();
|
|
164
|
+
// copy whole client directory to static directory
|
|
165
|
+
await mkdir(staticDir, { recursive: true });
|
|
166
|
+
await copyDir(join(root, userOptions.build.outDir, userOptions.build.client), join(root, userOptions.build.outDir, userOptions.build.static));
|
|
167
|
+
// Add global CSS from index.html - use client manifest
|
|
168
|
+
const {cssFiles: indexCss} = collectManifestClientFiles({
|
|
169
|
+
manifest: clientManifest,
|
|
170
|
+
root: root,
|
|
171
|
+
pagePath: 'index.html',
|
|
172
|
+
moduleBase: userOptions.moduleBase,
|
|
173
|
+
preserveModulesRoot: userOptions.build.preserveModulesRoot,
|
|
174
|
+
testClient: ()=>true,
|
|
175
|
+
});
|
|
176
|
+
indexCss.forEach((css) => globalCss.add(css));
|
|
177
|
+
|
|
178
|
+
// Add CSS for each route's page component - use server manifest
|
|
179
|
+
for (const route of resolvedPages) {
|
|
180
|
+
const routeFiles = files.urlMap.get(route);
|
|
181
|
+
if (routeFiles) {
|
|
182
|
+
const pageCss = collectManifestClientFiles({
|
|
183
|
+
manifest: serverManifest,
|
|
184
|
+
root: root,
|
|
185
|
+
pagePath: routeFiles.page,
|
|
186
|
+
moduleBase: userOptions.moduleBase,
|
|
187
|
+
preserveModulesRoot: userOptions.build.preserveModulesRoot,
|
|
188
|
+
onClientModule(path) {
|
|
189
|
+
// copy the css file to the static directory
|
|
190
|
+
const targetPath = join(root, userOptions.build.outDir, userOptions.build.server, path);
|
|
191
|
+
const destinationPath = join(root, userOptions.build.outDir, userOptions.build.static, path);
|
|
192
|
+
mkdirSync(dirname(destinationPath), { recursive: true });
|
|
193
|
+
copyFileSync(targetPath, destinationPath);
|
|
194
|
+
},
|
|
195
|
+
testClient: userOptions.autoDiscover.cssPattern,
|
|
196
|
+
testJson: userOptions.autoDiscover.jsonPattern,
|
|
197
|
+
});
|
|
198
|
+
routeCssMap.set(route, new Set([...globalCss, ...pageCss.cssFiles.keys()]));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const bootstrapModules = clientManifest["index.html"]?.file
|
|
202
|
+
? [clientManifest["index.html"].file.startsWith("/")
|
|
203
|
+
? clientManifest["index.html"].file.slice(1)
|
|
204
|
+
: clientManifest["index.html"].file]
|
|
205
|
+
: [];
|
|
206
|
+
|
|
207
|
+
const { failedRoutes, completedRoutes} = await renderPages(
|
|
208
|
+
resolvedPages,
|
|
209
|
+
files,
|
|
210
|
+
{
|
|
211
|
+
outDir: userOptions.build.outDir,
|
|
212
|
+
htmlOutputPath: join( userOptions.build.outDir, userOptions.build.static, "index.html"),
|
|
213
|
+
pipableStreamOptions: {
|
|
214
|
+
bootstrapModules: bootstrapModules,
|
|
215
|
+
},
|
|
216
|
+
moduleBasePath: join(root, userOptions.build.outDir, userOptions.build.client),
|
|
217
|
+
moduleBaseURL: userOptions.moduleBaseURL,
|
|
218
|
+
userConfig,
|
|
219
|
+
pluginOptions: userOptions,
|
|
220
|
+
worker,
|
|
221
|
+
clientManifest,
|
|
222
|
+
serverManifest,
|
|
223
|
+
loader,
|
|
224
|
+
transformIndexHtml: htmlTransform!,
|
|
225
|
+
onClientJSFile: (url) => {
|
|
226
|
+
if (!clientAssets.has(url)) {
|
|
227
|
+
const clientPath = join(root, userOptions.build.outDir, userOptions.build.client, url);
|
|
228
|
+
const targetPath = join(root, userOptions.build.outDir, userOptions.build.static, url);
|
|
229
|
+
mkdirSync(dirname(targetPath), { recursive: true });
|
|
230
|
+
copyFileSync(clientPath, targetPath);
|
|
231
|
+
clientAssets.add(url);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
if (failedRoutes.size > 0) {
|
|
238
|
+
console.error(
|
|
239
|
+
"[vite-plugin-react-server] Failed to render routes:",
|
|
240
|
+
failedRoutes
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
console.log(`Rendered ${completedRoutes.size} unique routes to ${join(userOptions.build.outDir, userOptions.build.static)}`);
|
|
244
|
+
await worker.terminate();
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
}
|
package/plugin/resolvePage.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stashedPages } from "./config/resolvePages.js";
|
|
2
|
+
|
|
1
3
|
type ResolvePageOptions = {
|
|
2
4
|
pageModule: Record<string, any>;
|
|
3
5
|
path: string;
|
|
@@ -16,6 +18,13 @@ export async function resolvePage({
|
|
|
16
18
|
url,
|
|
17
19
|
exportName,
|
|
18
20
|
}: ResolvePageOptions): Promise<ResolvePageResult> {
|
|
21
|
+
if(stashedPages.length > 0 && stashedPages.includes(path)){
|
|
22
|
+
return {
|
|
23
|
+
type: "success",
|
|
24
|
+
key: path,
|
|
25
|
+
Page: pageModule,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
19
28
|
if (!pageModule) {
|
|
20
29
|
return {
|
|
21
30
|
type: "error",
|
package/plugin/root.ts
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveOptions } from "../config/resolveOptions.js";
|
|
2
|
-
import type { StreamPluginOptions } from "../types.js";
|
|
3
|
-
import { type Plugin } from "vite";
|
|
2
|
+
import type { InputNormalizer, ResolvedUserOptions, StreamPluginOptions } from "../types.js";
|
|
3
|
+
import { type Manifest, type Plugin } from "vite";
|
|
4
4
|
import { transformModuleIfNeeded } from "../loader/react-loader.js";
|
|
5
5
|
import { DEFAULT_CONFIG } from "../config/defaults.js";
|
|
6
6
|
import { createInputNormalizer } from "../helpers/inputNormalizer.js";
|
|
@@ -32,37 +32,47 @@ import { join } from "node:path";
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
export function reactTransformPlugin(options: StreamPluginOptions): Plugin {
|
|
35
|
-
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
root: resolvedOptions.userOptions.projectRoot,
|
|
40
|
-
preserveModulesRoot: undefined,
|
|
41
|
-
removeExtension: false,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Get the client manifest
|
|
45
|
-
const clientManifestResult = tryManifest({
|
|
46
|
-
root: resolvedOptions.userOptions.projectRoot,
|
|
47
|
-
outDir: join(
|
|
48
|
-
resolvedOptions.userOptions.build.outDir,
|
|
49
|
-
resolvedOptions.userOptions.build.client
|
|
50
|
-
),
|
|
51
|
-
ssrManifest: false,
|
|
52
|
-
});
|
|
53
|
-
|
|
35
|
+
let normalizer: InputNormalizer;
|
|
36
|
+
let clientManifest: Manifest;
|
|
37
|
+
let isDev:boolean;
|
|
38
|
+
let userOptions: ResolvedUserOptions
|
|
54
39
|
return {
|
|
55
40
|
name: "vite:react-transform",
|
|
56
41
|
enforce: "pre", // Run before Vite's transforms
|
|
57
42
|
config(config, configEnv) {
|
|
58
|
-
|
|
43
|
+
const resolvedOptionsResult = resolveOptions(
|
|
44
|
+
options,
|
|
45
|
+
config.build?.outDir?.startsWith(
|
|
46
|
+
join(options.build?.outDir ?? DEFAULT_CONFIG.BUILD.outDir, options.build?.client ?? DEFAULT_CONFIG.BUILD.client)
|
|
47
|
+
) ?? false
|
|
48
|
+
);
|
|
49
|
+
isDev = configEnv.mode === "development" && configEnv.command === "serve"
|
|
50
|
+
if (resolvedOptionsResult.type === "error") throw resolvedOptionsResult.error;
|
|
51
|
+
userOptions = resolvedOptionsResult.userOptions;
|
|
52
|
+
normalizer = createInputNormalizer({
|
|
53
|
+
root: resolvedOptionsResult.userOptions.projectRoot,
|
|
54
|
+
preserveModulesRoot: undefined,
|
|
55
|
+
removeExtension: false,
|
|
56
|
+
});
|
|
57
|
+
|
|
59
58
|
},
|
|
60
59
|
async transform(code, id, options) {
|
|
61
60
|
const ssr = options?.ssr ?? false;
|
|
62
61
|
if (!ssr) return null;
|
|
63
62
|
if (!id.match(DEFAULT_CONFIG.FILE_REGEX)) return null;
|
|
64
|
-
if (!code.match('"use client"'))
|
|
65
|
-
|
|
63
|
+
if (!code.match('"use client"')) return null;
|
|
64
|
+
|
|
65
|
+
// Get the client manifest
|
|
66
|
+
const clientManifestResult = tryManifest({
|
|
67
|
+
root: userOptions.projectRoot,
|
|
68
|
+
outDir: join(
|
|
69
|
+
userOptions.build.outDir,
|
|
70
|
+
userOptions.build.client
|
|
71
|
+
),
|
|
72
|
+
ssrManifest: false,
|
|
73
|
+
});
|
|
74
|
+
if (clientManifestResult.type === "error") throw clientManifestResult.error;
|
|
75
|
+
clientManifest = clientManifestResult.manifest;
|
|
66
76
|
const [key, value] = normalizer(id);
|
|
67
77
|
const transformed = await transformModuleIfNeeded(
|
|
68
78
|
code,
|
|
@@ -87,16 +97,15 @@ export function reactTransformPlugin(options: StreamPluginOptions): Plugin {
|
|
|
87
97
|
transformed,
|
|
88
98
|
}
|
|
89
99
|
);
|
|
90
|
-
return null
|
|
91
|
-
}
|
|
92
|
-
if (clientManifestResult.type === "error") {
|
|
93
|
-
throw clientManifestResult.error;
|
|
100
|
+
return null;
|
|
94
101
|
}
|
|
95
|
-
const clientPath =
|
|
102
|
+
const clientPath = clientManifest[key]?.file;
|
|
96
103
|
|
|
97
104
|
if (!clientPath) {
|
|
98
|
-
console.warn(
|
|
99
|
-
|
|
105
|
+
console.warn(
|
|
106
|
+
`[vite-plugin-react-server] Could not find client path for ${value}. Ignoring.`
|
|
107
|
+
);
|
|
108
|
+
return null;
|
|
100
109
|
}
|
|
101
110
|
return {
|
|
102
111
|
code: transformed.replace(key, clientPath),
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export interface ViteReactClientTransformOptions {
|
|
2
|
-
projectRoot?: string;
|
|
3
|
-
moduleId?: (path: string, ssr: boolean) => string;
|
|
4
|
-
validateModuleId?: (moduleId: string) => boolean;
|
|
5
|
-
include?: string | RegExp | (string | RegExp)[];
|
|
6
|
-
exclude?: string | RegExp | (string | RegExp)[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface TransformerOptions {
|
|
10
|
-
moduleId: (path: string, ssr: boolean) => string;
|
|
11
|
-
/**
|
|
12
|
-
* Optional validation function for module IDs
|
|
13
|
-
*/
|
|
14
|
-
validateModuleId?: (moduleId: string) => boolean;
|
|
15
|
-
/**
|
|
16
|
-
* The directory to use for the module IDs
|
|
17
|
-
*/
|
|
18
|
-
moduleBase: string;
|
|
19
|
-
}
|
package/plugin/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ComponentType } from "react";
|
|
2
|
-
import type { RenderToPipeableStreamOptions } from "react-dom/server";
|
|
3
1
|
import type { PreRenderedChunk } from "rollup";
|
|
4
2
|
import type { PreRenderedAsset } from "rollup";
|
|
5
3
|
import type {
|
|
@@ -25,7 +23,7 @@ export type ResolvedUserConfig = Required<
|
|
|
25
23
|
Pick<UserConfig, "root" | "mode" | "build" | "resolve">
|
|
26
24
|
> &
|
|
27
25
|
Omit<UserConfig, "root" | "mode" | "build" | "resolve"> & {
|
|
28
|
-
resolve:
|
|
26
|
+
resolve: ResolveOptions;
|
|
29
27
|
} & {
|
|
30
28
|
build: NonNullable<
|
|
31
29
|
Required<
|
|
@@ -89,7 +87,6 @@ export type ResolvedUserOptions = Required<
|
|
|
89
87
|
| "serverEntry"
|
|
90
88
|
| "moduleBaseExceptions"
|
|
91
89
|
| "pipableStreamOptions"
|
|
92
|
-
| "moduleId"
|
|
93
90
|
>
|
|
94
91
|
> & {
|
|
95
92
|
build: NonNullable<Required<StreamPluginOptions["build"]>>;
|
|
@@ -172,15 +169,17 @@ export interface StreamPluginOptions {
|
|
|
172
169
|
build?: BuildConfig;
|
|
173
170
|
moduleBaseExceptions?: string[];
|
|
174
171
|
pipableStreamOptions?: PipeableStreamOptions;
|
|
175
|
-
moduleId?: (id: string, ssr: boolean) => string;
|
|
176
172
|
}
|
|
177
173
|
|
|
178
174
|
export interface CreateHandlerOptions<T = any> {
|
|
179
175
|
loader: (id: string) => Promise<T>;
|
|
180
176
|
clientManifest?: import("vite").Manifest;
|
|
181
177
|
serverManifest?: import("vite").Manifest;
|
|
178
|
+
moduleBasePath: string;
|
|
179
|
+
moduleBaseURL: string;
|
|
182
180
|
moduleGraph?: import("vite").ModuleGraph;
|
|
183
181
|
cssFiles?: string[];
|
|
182
|
+
cssModules?: Set<string>;
|
|
184
183
|
onCssFile?: (path: string, parentUrl: string) => void;
|
|
185
184
|
logger?: import("vite").Logger;
|
|
186
185
|
pipableStreamOptions?: PipeableStreamOptions;
|
|
@@ -245,7 +244,7 @@ export interface BuildOutput {
|
|
|
245
244
|
}
|
|
246
245
|
|
|
247
246
|
export interface BuildConfig {
|
|
248
|
-
pages: string[] | (() => Promise<string[]> | string[])
|
|
247
|
+
pages: string[] | (() => Promise<string[]> | string[]) | Promise<string[]>;
|
|
249
248
|
assetsDir?: string;
|
|
250
249
|
client?: string; // Output directory for client files
|
|
251
250
|
server?: string; // Output directory for server files
|
|
@@ -359,3 +358,23 @@ export type HtmlProps = {
|
|
|
359
358
|
url: string;
|
|
360
359
|
cssFiles: string[];
|
|
361
360
|
};
|
|
361
|
+
|
|
362
|
+
export interface PageAsset {
|
|
363
|
+
type: 'css' | 'js';
|
|
364
|
+
path: string;
|
|
365
|
+
parentUrl: string;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface PageData {
|
|
369
|
+
route: string;
|
|
370
|
+
clientComponents?: string[];
|
|
371
|
+
html?: {
|
|
372
|
+
raw: string;
|
|
373
|
+
transformed?: string;
|
|
374
|
+
assets: PageAsset[];
|
|
375
|
+
};
|
|
376
|
+
rsc?: {
|
|
377
|
+
content: string;
|
|
378
|
+
modules: Array<[string, string]>; // [modulePath, exportName]
|
|
379
|
+
};
|
|
380
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Worker, type ResourceLimits } from "node:worker_threads";
|
|
2
2
|
import { getMode, getNodePath } from "../config/getPaths.js";
|
|
3
3
|
import { getCondition } from "../config/getCondition.js";
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
type CreateWorkerOptions = {
|
|
6
6
|
projectRoot?: string;
|
|
7
7
|
condition?: "react-server" | "react-client";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# HTML Worker
|
|
2
|
+
|
|
3
|
+
The HTML worker handles HTML generation and transformation as part of the server plugin (which runs under the `react-server` condition). Since the main thread is already in the correct condition for RSC, the HTML worker can work directly with RSC streams without needing a separate RSC worker.
|
|
4
|
+
|
|
5
|
+
The worker receives RSC streams directly from the main thread (which is running under `react-server` condition) and transforms them into HTML. This is different from the client plugin, which needs a separate RSC worker to handle server-condition tasks.
|
|
6
|
+
|
|
7
|
+
## Extending the Worker
|
|
8
|
+
|
|
9
|
+
Users can create their own HTML workers for application-level use. This allows for:
|
|
10
|
+
|
|
11
|
+
1. Custom HTML processing
|
|
12
|
+
2. Specialized asset handling
|
|
13
|
+
3. Custom build pipelines
|
|
14
|
+
|
|
15
|
+
Example of creating a custom HTML worker:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { messageHandler } from 'vite-plugin-react-server/worker/html/messageHandler'
|
|
19
|
+
import type { HtmlWorkerMessage } from 'vite-plugin-react-server/worker/types'
|
|
20
|
+
|
|
21
|
+
// Create your custom message handler
|
|
22
|
+
const customMessageHandler = async (msg: HtmlWorkerMessage) => {
|
|
23
|
+
// Add your custom logic here
|
|
24
|
+
return messageHandler(msg)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Initialize your worker
|
|
28
|
+
if (typeof WorkerGlobalScope !== 'undefined') {
|
|
29
|
+
parentPort.on('message', customMessageHandler)
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Messages
|
|
34
|
+
You have two options, either directly write the files from the worker or pass them back to the main thread through messages.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Client Dev Mode Integration
|
|
41
|
+
|
|
42
|
+
When running in client dev mode, you can use your custom HTML worker as part of your application:
|
|
43
|
+
|
|
44
|
+
1. The worker runs in the client environment
|
|
45
|
+
2. It can handle HTML transformations in real-time
|
|
46
|
+
3. Provides immediate feedback during development
|
|
47
|
+
4. Can be integrated with other development tools
|
|
48
|
+
|
|
49
|
+
## Future Possibilities
|
|
50
|
+
|
|
51
|
+
The HTML worker architecture supports various potential enhancements:
|
|
52
|
+
|
|
53
|
+
- Custom HTML transformation pipelines
|
|
54
|
+
- Advanced asset optimization strategies
|
|
55
|
+
- Integration with other build tools
|
|
56
|
+
- Real-time HTML processing in development
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- The worker must handle streaming HTML content
|
|
61
|
+
- Asset paths need to be properly resolved
|
|
62
|
+
- Consider memory usage when processing large HTML files
|
|
63
|
+
- Ensure proper coordination with the RSC worker
|
|
@@ -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
|
+
}
|