vite-plugin-react-server 1.2.1 → 1.2.3
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 +2 -1
- package/dist/package.json +1 -1
- package/dist/plugin/helpers/createSharedLoader.d.ts +1 -1
- package/dist/plugin/helpers/createSharedLoader.d.ts.map +1 -1
- package/dist/plugin/helpers/createSharedLoader.js +14 -56
- package/dist/plugin/loader/react-loader.d.ts.map +1 -1
- package/dist/plugin/loader/react-loader.js +4 -70
- package/dist/plugin/react-static/plugin.client.js +4 -4
- package/dist/plugin/react-static/plugin.server.js +3 -3
- package/dist/plugin/stream/createRenderToPipeableStreamHandler.client.js +2 -2
- package/dist/plugin/worker/rsc/createRscWorkerLoader.d.ts +2 -6
- package/dist/plugin/worker/rsc/createRscWorkerLoader.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/createRscWorkerLoader.js +1 -34
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/plugin/helpers/createSharedLoader.ts +17 -70
- package/plugin/loader/react-loader.ts +5 -79
- package/plugin/react-static/plugin.client.ts +4 -4
- package/plugin/react-static/plugin.server.ts +3 -3
- package/plugin/stream/createRenderToPipeableStreamHandler.client.ts +2 -2
- package/plugin/worker/rsc/createRscWorkerLoader.ts +4 -51
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ export async function createSharedLoader({
|
|
|
38
38
|
buildServerDir,
|
|
39
39
|
// Direct import options
|
|
40
40
|
isBuildMode = false,
|
|
41
|
-
isServeMode = false,
|
|
41
|
+
isServeMode: _isServeMode = false,
|
|
42
42
|
effectiveProjectRoot,
|
|
43
43
|
build,
|
|
44
44
|
}: {
|
|
@@ -99,66 +99,32 @@ export async function createSharedLoader({
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
if (manifestResolution.manifestEntry && manifestResolution.resolvedPath) {
|
|
102
|
-
// Found in manifest - use the resolved path (it's already a full absolute path)
|
|
103
102
|
resolvedModuleID = manifestResolution.resolvedPath;
|
|
104
|
-
if (verbose) {
|
|
105
|
-
logger?.info(
|
|
106
|
-
`[createSharedLoader] Build mode: resolved via manifest to: ${resolvedModuleID}`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
103
|
} else {
|
|
110
|
-
// Not in manifest - use the builtModuleId from resolution
|
|
111
104
|
resolvedModuleID = manifestResolution.builtModuleId;
|
|
112
|
-
if (verbose) {
|
|
113
|
-
logger?.info(
|
|
114
|
-
`[createSharedLoader] Build mode: not in manifest, using builtModuleId: ${resolvedModuleID}`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
105
|
|
|
118
|
-
//
|
|
119
|
-
// A source path starts with moduleBase (e.g., "src/"), a built path doesn't
|
|
120
|
-
// Also check if it's already an absolute path or starts with file://
|
|
106
|
+
// Prefix non-source, non-absolute paths with server build directory
|
|
121
107
|
const isSourcePath = moduleId.startsWith(moduleBase + "/") ||
|
|
122
108
|
moduleId.startsWith("./" + moduleBase + "/") ||
|
|
123
109
|
(isAbsolute(moduleId) && moduleId.includes(moduleBase));
|
|
124
110
|
|
|
125
|
-
// If it's not a source path and not already absolute, prefix with server build directory
|
|
126
111
|
if (!isSourcePath && !isAbsolute(resolvedModuleID) && effectiveProjectRoot && build) {
|
|
127
|
-
|
|
112
|
+
resolvedModuleID = join(
|
|
128
113
|
effectiveProjectRoot,
|
|
129
114
|
build.outDir || "dist",
|
|
130
|
-
build.server || "server"
|
|
131
|
-
|
|
132
|
-
resolvedModuleID = join(serverBuildPath, resolvedModuleID);
|
|
133
|
-
if (verbose) {
|
|
134
|
-
logger?.info(
|
|
135
|
-
`[createSharedLoader] Build mode: prefixing with ${serverBuildPath}: ${resolvedModuleID}`
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
} else if (isServeMode) {
|
|
141
|
-
// Dev mode: load directly from source files, no build path prefixing
|
|
142
|
-
if (verbose) {
|
|
143
|
-
logger?.info(
|
|
144
|
-
`[createSharedLoader] Dev mode: loading directly from source`
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
} else if (isBuildMode && effectiveProjectRoot && build) {
|
|
148
|
-
// Build mode fallback: prefix with server build directory even without manifest/normalizer
|
|
149
|
-
if (!isAbsolute(resolvedModuleID)) {
|
|
150
|
-
const serverBuildPath = join(
|
|
151
|
-
effectiveProjectRoot,
|
|
152
|
-
build.outDir || "dist",
|
|
153
|
-
build.server || "server"
|
|
154
|
-
);
|
|
155
|
-
resolvedModuleID = join(serverBuildPath, resolvedModuleID);
|
|
156
|
-
if (verbose) {
|
|
157
|
-
logger?.info(
|
|
158
|
-
`[createSharedLoader] Build mode fallback: prefixing with ${serverBuildPath}: ${resolvedModuleID}`
|
|
115
|
+
build.server || "server",
|
|
116
|
+
resolvedModuleID
|
|
159
117
|
);
|
|
160
118
|
}
|
|
161
119
|
}
|
|
120
|
+
} else if (isBuildMode && effectiveProjectRoot && build && !isAbsolute(resolvedModuleID)) {
|
|
121
|
+
// Build mode fallback without manifest
|
|
122
|
+
resolvedModuleID = join(
|
|
123
|
+
effectiveProjectRoot,
|
|
124
|
+
build.outDir || "dist",
|
|
125
|
+
build.server || "server",
|
|
126
|
+
resolvedModuleID
|
|
127
|
+
);
|
|
162
128
|
}
|
|
163
129
|
|
|
164
130
|
// Step 3: Construct the full path and import
|
|
@@ -168,40 +134,21 @@ export async function createSharedLoader({
|
|
|
168
134
|
? join(effectiveProjectRoot, resolvedModuleID)
|
|
169
135
|
: resolvedModuleID;
|
|
170
136
|
|
|
171
|
-
|
|
172
|
-
logger?.info(`[createSharedLoader] Importing from: ${fullPath}`);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Step 4: Import the module
|
|
137
|
+
// Import the module
|
|
176
138
|
const fileUrl = isAbsolute(fullPath) ? pathToFileURL(fullPath).href : fullPath;
|
|
177
139
|
const result = await import(fileUrl);
|
|
178
140
|
|
|
179
|
-
//
|
|
141
|
+
// Validate exports
|
|
180
142
|
if (result == null) {
|
|
181
143
|
throw new Error(`Module "${moduleId}" does not have any exports`);
|
|
182
144
|
}
|
|
183
|
-
|
|
184
145
|
if (!Object.keys(result).length && exportName?.length) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`Module "${moduleId}" is a module, but does not have any exports so it can't find ${exportName}`
|
|
187
|
-
);
|
|
146
|
+
throw new Error(`Module "${moduleId}" has no exports, can't find ${exportName}`);
|
|
188
147
|
}
|
|
189
|
-
|
|
190
148
|
if (exportName && !(exportName in result)) {
|
|
191
|
-
throw new Error(
|
|
192
|
-
`Module "${moduleId}" exists, but does not export "${exportName}"`
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (verbose) {
|
|
197
|
-
logger?.info(
|
|
198
|
-
`[createSharedLoader] Module loaded successfully, exports: ${Object.keys(
|
|
199
|
-
result
|
|
200
|
-
).join(", ")}`
|
|
201
|
-
);
|
|
149
|
+
throw new Error(`Module "${moduleId}" does not export "${exportName}"`);
|
|
202
150
|
}
|
|
203
151
|
|
|
204
|
-
// Import always returns a module object (not a Promise), so return it directly
|
|
205
152
|
return result;
|
|
206
153
|
}
|
|
207
154
|
|
|
@@ -119,30 +119,11 @@ export const load: LoadHook = async (url, context, nextLoad) => {
|
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
121
|
const verbose = userOptions?.verbose ?? false;
|
|
122
|
-
if (verbose) {
|
|
123
|
-
logger.info(`Attempting to load: ${url}`);
|
|
124
|
-
logger.info(`Context: ${JSON.stringify({
|
|
125
|
-
format: context.format,
|
|
126
|
-
conditions: context.conditions,
|
|
127
|
-
})}`);
|
|
128
|
-
}
|
|
129
122
|
|
|
130
123
|
const { format } = context;
|
|
131
124
|
if (format === "module" || format === "module-typescript") {
|
|
132
|
-
if (verbose) {
|
|
133
|
-
logger.info(`Loading module: ${url}`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
125
|
// Load the URL normally
|
|
137
126
|
const result = await nextLoad(url, context);
|
|
138
|
-
|
|
139
|
-
if (verbose) {
|
|
140
|
-
logger.info(`Next load result: ${JSON.stringify({
|
|
141
|
-
format: result.format,
|
|
142
|
-
shortCircuit: result.shortCircuit,
|
|
143
|
-
source: typeof result.source,
|
|
144
|
-
})}`);
|
|
145
|
-
}
|
|
146
127
|
|
|
147
128
|
let source =
|
|
148
129
|
typeof result.source === "string"
|
|
@@ -187,45 +168,18 @@ export const load: LoadHook = async (url, context, nextLoad) => {
|
|
|
187
168
|
? isClientComponent(source, url)
|
|
188
169
|
: false);
|
|
189
170
|
|
|
190
|
-
if (verbose) {
|
|
191
|
-
let startPreviewIndex = 0;
|
|
192
|
-
let startLine = 0;
|
|
193
|
-
const lines = source.split("\n");
|
|
194
|
-
while (
|
|
195
|
-
lines[startLine].trim() === "" || lines[startLine].trim() === "\r" ||
|
|
196
|
-
// comment lines
|
|
197
|
-
lines[startLine].trim().startsWith("//")
|
|
198
|
-
|| lines[startLine].trim().startsWith("/**")
|
|
199
|
-
|| lines[startLine].trim().startsWith("*")
|
|
200
|
-
) {
|
|
201
|
-
startPreviewIndex += lines[startLine].length;
|
|
202
|
-
startLine++;
|
|
203
|
-
}
|
|
204
|
-
logger.info(`Module analysis: ${JSON.stringify({
|
|
205
|
-
url,
|
|
206
|
-
isServer,
|
|
207
|
-
isClient,
|
|
208
|
-
hasFileLevelServerDirective,
|
|
209
|
-
hasFileLevelClientDirective,
|
|
210
|
-
sourceLength: source.length,
|
|
211
|
-
sourcePreview: source.slice(startPreviewIndex, startPreviewIndex + 100) + "...",
|
|
212
|
-
})}`);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
171
|
if (!isServer && !isClient) {
|
|
216
|
-
if (verbose) {
|
|
217
|
-
logger.info(`Skipping non-server/non-client module: ${url}`);
|
|
218
|
-
}
|
|
219
172
|
// Return modified source if CJS React imports were rewritten
|
|
220
173
|
return { ...result, source };
|
|
221
174
|
}
|
|
222
175
|
|
|
223
|
-
// Handle file URLs
|
|
224
|
-
const filePath = url.startsWith("file://") ? fileURLToPath(url) : url;
|
|
225
176
|
if (verbose) {
|
|
226
|
-
logger.info(`
|
|
177
|
+
logger.info(`[react-loader] ${isServer ? 'server' : 'client'} module: ${url}`);
|
|
227
178
|
}
|
|
228
179
|
|
|
180
|
+
// Handle file URLs
|
|
181
|
+
const filePath = url.startsWith("file://") ? fileURLToPath(url) : url;
|
|
182
|
+
|
|
229
183
|
if(typeof userOptions.moduleID !== "function") {
|
|
230
184
|
// Ensure we have proper build context for RSC worker
|
|
231
185
|
// If configEnv is not available or doesn't indicate build mode, create a build-compatible configEnv
|
|
@@ -249,27 +203,11 @@ export const load: LoadHook = async (url, context, nextLoad) => {
|
|
|
249
203
|
const [, value] = userOptions.normalizer(filePath);
|
|
250
204
|
moduleID = join(userOptions.moduleBasePath, value);
|
|
251
205
|
finalID = userOptions.moduleID?.(moduleID) || moduleID;
|
|
252
|
-
if (verbose) {
|
|
253
|
-
logger.info(`Normalized IDs: ${moduleID} -> ${finalID}`);
|
|
254
|
-
logger.info(`userOptions: ${JSON.stringify(userOptions)}`);
|
|
255
|
-
}
|
|
256
206
|
}
|
|
257
207
|
|
|
258
208
|
const { code: transformed, map } = await transformer(source, moduleID, finalID);
|
|
259
209
|
|
|
260
|
-
if (verbose) {
|
|
261
|
-
logger.info(`Transformation result: ${JSON.stringify({
|
|
262
|
-
originalLength: source.length,
|
|
263
|
-
transformedLength: transformed.length,
|
|
264
|
-
wasTransformed: source !== transformed,
|
|
265
|
-
hasSourceMap: !!map,
|
|
266
|
-
})}`);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
210
|
if (loaderPort) {
|
|
270
|
-
if (verbose) {
|
|
271
|
-
logger.info("Sending SERVER_MODULE message");
|
|
272
|
-
}
|
|
273
211
|
loaderPort.postMessage({
|
|
274
212
|
type: "SERVER_MODULE",
|
|
275
213
|
id: finalID,
|
|
@@ -285,21 +223,9 @@ export const load: LoadHook = async (url, context, nextLoad) => {
|
|
|
285
223
|
};
|
|
286
224
|
}
|
|
287
225
|
|
|
288
|
-
if (verbose) {
|
|
289
|
-
logger.info(`Skipping non-module format: ${format}`);
|
|
290
|
-
}
|
|
291
226
|
return nextLoad(url, context);
|
|
292
227
|
};
|
|
293
228
|
|
|
294
229
|
export const resolve: ResolveHook = async (specifier, context, nextResolve) => {
|
|
295
|
-
|
|
296
|
-
if (verbose) {
|
|
297
|
-
logger.info(`Resolving: ${specifier}`);
|
|
298
|
-
logger.info(`Resolve context: ${JSON.stringify(context)}`);
|
|
299
|
-
}
|
|
300
|
-
const result = await nextResolve(specifier, context);
|
|
301
|
-
if (verbose) {
|
|
302
|
-
logger.info(`Resolve result: ${JSON.stringify(result)}`);
|
|
303
|
-
}
|
|
304
|
-
return result;
|
|
230
|
+
return nextResolve(specifier, context);
|
|
305
231
|
};
|
|
@@ -464,18 +464,18 @@ export const reactStaticPlugin: VitePluginFn = function _reactStaticPlugin(
|
|
|
464
464
|
const indexHtml = staticManifest?.["index.html"]?.file;
|
|
465
465
|
const serverPipeableStreamOptions = {
|
|
466
466
|
...userOptions.serverPipeableStreamOptions,
|
|
467
|
-
|
|
467
|
+
bootstrapModules: [
|
|
468
468
|
...(indexHtml ? [baseURL(indexHtml)] : []),
|
|
469
|
-
...(userOptions.serverPipeableStreamOptions?.
|
|
469
|
+
...(userOptions.serverPipeableStreamOptions?.bootstrapModules ??
|
|
470
470
|
[]),
|
|
471
471
|
],
|
|
472
472
|
};
|
|
473
473
|
userOptions.serverPipeableStreamOptions = serverPipeableStreamOptions;
|
|
474
474
|
const clientPipeableStreamOptions = {
|
|
475
475
|
...userOptions.clientPipeableStreamOptions,
|
|
476
|
-
|
|
476
|
+
bootstrapModules: [
|
|
477
477
|
...(indexHtml ? [baseURL(indexHtml)] : []),
|
|
478
|
-
...(userOptions.clientPipeableStreamOptions?.
|
|
478
|
+
...(userOptions.clientPipeableStreamOptions?.bootstrapModules ??
|
|
479
479
|
[]),
|
|
480
480
|
],
|
|
481
481
|
};
|
|
@@ -322,7 +322,7 @@ export const reactStaticPlugin: VitePluginFn = function _reactStaticPlugin(
|
|
|
322
322
|
const indexHtml = staticManifest?.["index.html"]?.file;
|
|
323
323
|
const serverPipeableStreamOptions = {
|
|
324
324
|
...userOptions.serverPipeableStreamOptions,
|
|
325
|
-
|
|
325
|
+
bootstrapModules: [
|
|
326
326
|
...(indexHtml ? [baseURL(indexHtml)] : []),
|
|
327
327
|
...(userOptions.serverPipeableStreamOptions?.bootstrapModules ??
|
|
328
328
|
[]),
|
|
@@ -331,9 +331,9 @@ export const reactStaticPlugin: VitePluginFn = function _reactStaticPlugin(
|
|
|
331
331
|
userOptions.serverPipeableStreamOptions = serverPipeableStreamOptions;
|
|
332
332
|
const clientPipeableStreamOptions = {
|
|
333
333
|
...userOptions.clientPipeableStreamOptions,
|
|
334
|
-
|
|
334
|
+
bootstrapModules: [
|
|
335
335
|
...(indexHtml ? [baseURL(indexHtml)] : []),
|
|
336
|
-
...(userOptions.clientPipeableStreamOptions?.
|
|
336
|
+
...(userOptions.clientPipeableStreamOptions?.bootstrapModules ??
|
|
337
337
|
[]),
|
|
338
338
|
],
|
|
339
339
|
};
|
|
@@ -80,8 +80,8 @@ export const createRenderToPipeableStreamHandler: CreateRenderToPipeableStreamHa
|
|
|
80
80
|
|
|
81
81
|
// Create the React HTML stream using ReactDOMServer.renderToPipeableStream
|
|
82
82
|
const { pipe, abort } = ReactDOMServer.renderToPipeableStream(reactElements, {
|
|
83
|
-
|
|
84
|
-
clientPipeableStreamOptions?.
|
|
83
|
+
bootstrapModules:
|
|
84
|
+
clientPipeableStreamOptions?.bootstrapModules || [],
|
|
85
85
|
onShellReady() {
|
|
86
86
|
if (verbose) {
|
|
87
87
|
logger?.info(
|
|
@@ -4,15 +4,11 @@ import type { GenericModuleLoader } from "../../types.js";
|
|
|
4
4
|
import { createSharedLoader } from "../../helpers/createSharedLoader.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Creates a
|
|
8
|
-
*
|
|
9
|
-
* This follows the same pattern as the main thread server version:
|
|
10
|
-
* - Simple dynamic import-based loading
|
|
11
|
-
* - Proper export name resolution
|
|
12
|
-
* - Works in both dev and build scenarios
|
|
7
|
+
* Creates a GenericModuleLoader for the RSC worker.
|
|
8
|
+
* Uses createSharedLoader for virtual modules, manifest resolution, and imports.
|
|
13
9
|
*/
|
|
14
10
|
export const createRscWorkerLoader = ({
|
|
15
|
-
verbose = false,
|
|
11
|
+
verbose = false,
|
|
16
12
|
logger = createLogger(workerData.resolvedConfig?.logLevel ?? "info", {
|
|
17
13
|
prefix: "vite:plugin-react-server/worker/rsc",
|
|
18
14
|
}),
|
|
@@ -31,57 +27,14 @@ export const createRscWorkerLoader = ({
|
|
|
31
27
|
};
|
|
32
28
|
manifest?: Record<string, any>;
|
|
33
29
|
} = {}): GenericModuleLoader => {
|
|
34
|
-
// Debug log the build config
|
|
35
|
-
if (verbose) {
|
|
36
|
-
logger.info(`[createRscWorkerLoader] build config: ${JSON.stringify(build)}`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Determine projectRoot based on configEnv if not provided
|
|
40
|
-
// In dev mode, configEnv.command should be "serve", but if it's undefined,
|
|
41
|
-
// we can detect dev mode by checking if we're in a dev server environment
|
|
42
30
|
const isBuildMode = workerData.configEnv?.command === "build";
|
|
43
|
-
const isServeMode = !isBuildMode
|
|
31
|
+
const isServeMode = !isBuildMode;
|
|
44
32
|
const effectiveProjectRoot =
|
|
45
33
|
projectRoot || workerData.userOptions?.projectRoot || process.cwd();
|
|
46
34
|
|
|
47
|
-
// Log build config for debugging
|
|
48
|
-
if (verbose) {
|
|
49
|
-
logger.info(
|
|
50
|
-
`[createRscWorkerLoader] build config: ${JSON.stringify(build)}`
|
|
51
|
-
);
|
|
52
|
-
logger.info(
|
|
53
|
-
`[createRscWorkerLoader] manifest: ${JSON.stringify(manifest)}`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (verbose) {
|
|
58
|
-
logger.info(
|
|
59
|
-
`[createRscWorkerLoader] configEnv: ${JSON.stringify(
|
|
60
|
-
workerData.configEnv
|
|
61
|
-
)}`
|
|
62
|
-
);
|
|
63
|
-
logger.info(
|
|
64
|
-
`[createRscWorkerLoader] config.env: ${JSON.stringify(
|
|
65
|
-
workerData.resolvedConfig?.env
|
|
66
|
-
)}`
|
|
67
|
-
);
|
|
68
|
-
logger.info(
|
|
69
|
-
`[createRscWorkerLoader] mode: ${workerData.resolvedConfig?.mode}`
|
|
70
|
-
);
|
|
71
|
-
logger.info(`[createRscWorkerLoader] NODE_ENV: ${process.env.NODE_ENV}`);
|
|
72
|
-
logger.info(`[createRscWorkerLoader] isServeMode: ${isServeMode}`);
|
|
73
|
-
logger.info(`[createRscWorkerLoader] projectRoot: ${effectiveProjectRoot}`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Simple GenericModuleLoader using shared loader utility
|
|
77
35
|
return async (id: string) => {
|
|
78
|
-
if (verbose) {
|
|
79
|
-
logger.info(`[RSC Worker Loader] Loading module: ${id}`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
36
|
const [moduleID, exportName] = id.split("#");
|
|
83
37
|
|
|
84
|
-
// Use shared loader utility - it handles virtual modules, manifest resolution, and imports
|
|
85
38
|
return await createSharedLoader({
|
|
86
39
|
moduleId: moduleID,
|
|
87
40
|
exportName,
|