vite-plugin-react-server 1.3.6 → 1.4.1
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 +33 -19
- package/dist/package.json +4 -2
- package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
- package/dist/plugin/config/resolveOptions.js +4 -2
- package/dist/plugin/dev-server/configureReactServer.client.js +1 -1
- package/dist/plugin/dev-server/plugin.client.d.ts.map +1 -1
- package/dist/plugin/dev-server/plugin.client.js +17 -15
- package/dist/plugin/dev-server/plugin.server.d.ts.map +1 -1
- package/dist/plugin/dev-server/plugin.server.js +54 -4
- package/dist/plugin/helpers/requestInfo.d.ts.map +1 -1
- package/dist/plugin/helpers/requestInfo.js +4 -3
- package/dist/plugin/helpers/requestToRoute.d.ts.map +1 -1
- package/dist/plugin/helpers/requestToRoute.js +2 -2
- package/dist/plugin/react-static/plugin.server.d.ts.map +1 -1
- package/dist/plugin/react-static/plugin.server.js +9 -1
- package/dist/plugin/react-static/renderPagesBatched.d.ts.map +1 -1
- package/dist/plugin/react-static/renderPagesBatched.js +136 -36
- package/dist/plugin/react-static/types.d.ts +1 -0
- package/dist/plugin/react-static/types.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +15 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/utils/createReactFetcher.js +24 -2
- package/dist/plugin/utils/useRscHmr.js +10 -2
- package/dist/plugin/vendor/register-vendor.js +1 -1
- package/dist/plugin/vendor/vendor-alias.d.ts +5 -2
- package/dist/plugin/vendor/vendor-alias.d.ts.map +1 -1
- package/dist/plugin/vendor/vendor-alias.js +60 -26
- package/dist/plugin/vendor/vendor.server.d.ts.map +1 -1
- package/dist/plugin/vendor/vendor.server.js +2 -2
- package/dist/plugin/vendor/vendor.static.d.ts.map +1 -1
- package/dist/plugin/vendor/vendor.static.js +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +1 -1
- package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js +1 -1
- package/oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +1 -1
- package/oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +1 -1
- package/oss-experimental/react-server-dom-esm/package.json +3 -3
- package/package.json +4 -2
- package/plugin/config/resolveOptions.ts +2 -0
- package/plugin/dev-server/configureReactServer.client.ts +1 -1
- package/plugin/dev-server/plugin.client.ts +23 -20
- package/plugin/dev-server/plugin.server.ts +71 -4
- package/plugin/helpers/requestInfo.ts +6 -3
- package/plugin/helpers/requestToRoute.ts +3 -2
- package/plugin/react-static/plugin.server.ts +11 -1
- package/plugin/react-static/renderPagesBatched.ts +148 -39
- package/plugin/react-static/types.ts +1 -0
- package/plugin/types.ts +15 -0
- package/plugin/vendor/register-vendor.ts +1 -1
- package/plugin/vendor/vendor-alias.ts +61 -39
- package/plugin/vendor/vendor.server.ts +3 -3
- package/plugin/vendor/vendor.static.ts +3 -2
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js
CHANGED
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
51
51
|
if (existingPromise)
|
|
52
52
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
53
|
-
var modulePromise = import(metadata.specifier);
|
|
53
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
54
54
|
modulePromise.then(
|
|
55
55
|
function (value) {
|
|
56
56
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js
CHANGED
|
@@ -26,7 +26,7 @@ function preloadModule(metadata) {
|
|
|
26
26
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
27
27
|
if (existingPromise)
|
|
28
28
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
29
|
-
var modulePromise = import(metadata.specifier);
|
|
29
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
30
30
|
modulePromise.then(
|
|
31
31
|
function (value) {
|
|
32
32
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js
CHANGED
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
51
51
|
if (existingPromise)
|
|
52
52
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
53
|
-
var modulePromise = import(metadata.specifier);
|
|
53
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
54
54
|
modulePromise.then(
|
|
55
55
|
function (value) {
|
|
56
56
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js
CHANGED
|
@@ -27,7 +27,7 @@ function preloadModule(metadata) {
|
|
|
27
27
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
28
28
|
if (existingPromise)
|
|
29
29
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
30
|
-
var modulePromise = import(metadata.specifier);
|
|
30
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
31
31
|
modulePromise.then(
|
|
32
32
|
function (value) {
|
|
33
33
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js
CHANGED
|
@@ -2854,7 +2854,7 @@
|
|
|
2854
2854
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
2855
2855
|
if (existingPromise)
|
|
2856
2856
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
2857
|
-
var modulePromise = import(metadata.specifier);
|
|
2857
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
2858
2858
|
modulePromise.then(
|
|
2859
2859
|
function (value) {
|
|
2860
2860
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js
CHANGED
|
@@ -1952,7 +1952,7 @@ function preloadModule(metadata) {
|
|
|
1952
1952
|
var existingPromise = asyncModuleCache.get(metadata.specifier);
|
|
1953
1953
|
if (existingPromise)
|
|
1954
1954
|
return "fulfilled" === existingPromise.status ? null : existingPromise;
|
|
1955
|
-
var modulePromise = import(metadata.specifier);
|
|
1955
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
1956
1956
|
modulePromise.then(
|
|
1957
1957
|
function (value) {
|
|
1958
1958
|
modulePromise.status = "fulfilled";
|
package/oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js
CHANGED
|
@@ -122,7 +122,7 @@ function preloadModule(metadata) {
|
|
|
122
122
|
return existingPromise;
|
|
123
123
|
} else {
|
|
124
124
|
// $FlowFixMe[unsupported-syntax]
|
|
125
|
-
var modulePromise = import(metadata.specifier);
|
|
125
|
+
var modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
126
126
|
modulePromise.then(function (value) {
|
|
127
127
|
var fulfilledThenable = modulePromise;
|
|
128
128
|
fulfilledThenable.status = 'fulfilled';
|
package/oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js
CHANGED
|
@@ -55,7 +55,7 @@ function preloadModule(metadata) {
|
|
|
55
55
|
return existingPromise;
|
|
56
56
|
} else {
|
|
57
57
|
// $FlowFixMe[unsupported-syntax]
|
|
58
|
-
const modulePromise = import(metadata.specifier);
|
|
58
|
+
const modulePromise = import(/* @vite-ignore */ metadata.specifier);
|
|
59
59
|
modulePromise.then(value => {
|
|
60
60
|
const fulfilledThenable = modulePromise;
|
|
61
61
|
fulfilledThenable.status = 'fulfilled';
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"./client.node": "./client.node.js",
|
|
33
33
|
"./server": {
|
|
34
34
|
"react-server": "./server.node.js",
|
|
35
|
-
"default": "./server.js"
|
|
35
|
+
"default": "./server.node.js"
|
|
36
36
|
},
|
|
37
37
|
"./server.node": "./server.node.js",
|
|
38
38
|
"./static": {
|
|
39
39
|
"react-server": "./static.node.js",
|
|
40
|
-
"default": "./static.js"
|
|
40
|
+
"default": "./static.node.js"
|
|
41
41
|
},
|
|
42
42
|
"./static.node": "./static.node.js",
|
|
43
43
|
"./node-loader": "./esm/react-server-dom-esm-node-loader.production.js",
|
|
@@ -60,4 +60,4 @@
|
|
|
60
60
|
"acorn-loose": "^8.3.0",
|
|
61
61
|
"webpack-sources": "^3.2.0"
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-react-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Vite plugin for React Server Components (RSC)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/plugin/index.js",
|
|
@@ -43,7 +43,9 @@
|
|
|
43
43
|
"./stream": "./dist/plugin/stream/index.js",
|
|
44
44
|
"./stream/client": "./dist/plugin/stream/index.client.js",
|
|
45
45
|
"./stream/server": "./dist/plugin/stream/index.server.js",
|
|
46
|
-
"./env":
|
|
46
|
+
"./env": {
|
|
47
|
+
"types": "./env.d.ts"
|
|
48
|
+
},
|
|
47
49
|
"./config": "./dist/plugin/config/index.js",
|
|
48
50
|
"./error": "./dist/plugin/error/index.js",
|
|
49
51
|
"./vendor": "./dist/plugin/vendor/index.js",
|
|
@@ -668,6 +668,8 @@ export const resolveOptions: ResolveOptionsFn = function _resolveOptions(
|
|
|
668
668
|
useHtmlWorker: options.build?.useHtmlWorker ??
|
|
669
669
|
// Force useHtmlWorker to true when build.pages is explicitly configured, regardless of default logic
|
|
670
670
|
(options.build?.pages && (Array.isArray(options.build.pages) || typeof options.build.pages === 'function')) ? true : DEFAULT_CONFIG.BUILD.useHtmlWorker,
|
|
671
|
+
renderMode: options.build?.renderMode ?? "parallel",
|
|
672
|
+
batchSize: options.build?.batchSize ?? 8,
|
|
671
673
|
} satisfies ResolvedUserOptions["build"];
|
|
672
674
|
|
|
673
675
|
// Development configuration
|
|
@@ -74,7 +74,7 @@ export const configureReactServer: CreateReactWorkerServerFn =
|
|
|
74
74
|
},
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
// Return object with restart function and HMR update sender for
|
|
77
|
+
// Return object with restart function and HMR update sender for hotUpdate
|
|
78
78
|
return {
|
|
79
79
|
restart: restartFn,
|
|
80
80
|
sendHmrUpdate: (file: string, routes?: string[]) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
1
2
|
import type { VitePluginFn } from "../../types.js";
|
|
2
3
|
import { configureReactServer } from "./configureReactServer.client.js";
|
|
3
4
|
import { resolveOptions } from "../config/resolveOptions.js";
|
|
@@ -34,8 +35,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
34
35
|
return {
|
|
35
36
|
name: "vite-plugin-react-server:dev-server-client",
|
|
36
37
|
apply: "serve", // Only apply in dev server mode
|
|
37
|
-
//
|
|
38
|
-
// The plugin should apply to client environment, but handleHotUpdate is a dev server hook
|
|
38
|
+
// No applyToEnvironment — hotUpdate needs to run for all environments
|
|
39
39
|
// that should work regardless of environment filtering
|
|
40
40
|
config(_config, viteConfigEnv) {
|
|
41
41
|
configEnv = viteConfigEnv;
|
|
@@ -72,7 +72,13 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
72
72
|
resolvedConfig: server.config,
|
|
73
73
|
});
|
|
74
74
|
},
|
|
75
|
-
|
|
75
|
+
hotUpdate(ctx: any) {
|
|
76
|
+
const { file, server } = ctx;
|
|
77
|
+
const envName = ctx.environment?.name ?? 'unknown';
|
|
78
|
+
|
|
79
|
+
// Only run worker invalidation from the client environment (once per change)
|
|
80
|
+
if (envName !== 'client') return;
|
|
81
|
+
|
|
76
82
|
// Prevent recursive HMR updates
|
|
77
83
|
if (isProcessingHmr) {
|
|
78
84
|
return undefined;
|
|
@@ -84,11 +90,18 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
84
90
|
|
|
85
91
|
// Normalize paths for comparison (handle both absolute and relative)
|
|
86
92
|
const normalizedFile = file.replace(projectRoot, '').replace(/^\/+/, '');
|
|
87
|
-
const
|
|
93
|
+
const isSourceFile = normalizedFile.startsWith(moduleBase + '/') &&
|
|
88
94
|
(file.endsWith('.tsx') || file.endsWith('.ts') || file.endsWith('.jsx') || file.endsWith('.js'));
|
|
89
95
|
|
|
90
|
-
//
|
|
91
|
-
|
|
96
|
+
// Skip client components — let @vitejs/plugin-react handle them with Fast Refresh
|
|
97
|
+
const isClientFile = isSourceFile && (() => {
|
|
98
|
+
try {
|
|
99
|
+
const head = readFileSync(file, 'utf-8').slice(0, 200);
|
|
100
|
+
return /^\s*["']use client["']/.test(head.split('\n')[0]);
|
|
101
|
+
} catch { return false; }
|
|
102
|
+
})();
|
|
103
|
+
|
|
104
|
+
const isServerFile = isSourceFile && !isClientFile;
|
|
92
105
|
|
|
93
106
|
if (isServerFile && hmrHandler) {
|
|
94
107
|
isProcessingHmr = true;
|
|
@@ -100,17 +113,8 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
100
113
|
// This clears component caches, but Node.js's ES module cache persists
|
|
101
114
|
hmrHandler.sendHmrUpdate(file);
|
|
102
115
|
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
// We need to manually notify the client to refetch the RSC stream
|
|
106
|
-
server.ws.send({
|
|
107
|
-
type: 'custom',
|
|
108
|
-
event: 'vite-plugin-react-server:server-component-update',
|
|
109
|
-
data: {
|
|
110
|
-
file: normalizedFile,
|
|
111
|
-
path: file,
|
|
112
|
-
},
|
|
113
|
-
});
|
|
116
|
+
// NOTE: The WS event to notify the client is sent by the hotUpdate hook
|
|
117
|
+
// in plugin.server.ts — don't duplicate it here.
|
|
114
118
|
|
|
115
119
|
// CRITICAL: Node.js caches ES modules, so we need to restart the worker
|
|
116
120
|
// to clear the module cache. Debounce restarts to prevent recursion.
|
|
@@ -139,7 +143,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
139
143
|
}, 500); // 500ms debounce
|
|
140
144
|
} else {
|
|
141
145
|
// No restart function available yet - worker hasn't been created
|
|
142
|
-
// This is expected if
|
|
146
|
+
// This is expected if hotUpdate fires before the first request
|
|
143
147
|
server.config.logger.warn(`[vite-plugin-react-server] Restart function not available yet - worker will be created on next request`);
|
|
144
148
|
setTimeout(() => {
|
|
145
149
|
isProcessingHmr = false;
|
|
@@ -153,8 +157,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
|
|
|
153
157
|
server.config.logger.warn(`[vite-plugin-react-server] Server file changed but HMR handler not available yet: ${file}`);
|
|
154
158
|
}
|
|
155
159
|
|
|
156
|
-
//
|
|
157
|
-
return undefined;
|
|
160
|
+
// Don't suppress — plugin.server.ts hotUpdate handles page reload prevention
|
|
158
161
|
},
|
|
159
162
|
};
|
|
160
163
|
};
|
|
@@ -2,6 +2,7 @@ import type { StreamPluginOptions } from "../../types.js";
|
|
|
2
2
|
import { configureReactServer } from "./configureReactServer.server.js";
|
|
3
3
|
import { resolveOptions } from "../config/resolveOptions.js";
|
|
4
4
|
import type { Plugin, ViteDevServer } from "vite";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Dev server plugin for server environment.
|
|
@@ -26,15 +27,74 @@ export const vitePluginReactDevServer = function _vitePluginReactServerDevServer
|
|
|
26
27
|
name: "vite-plugin-react-server:server-hmr",
|
|
27
28
|
apply: "serve" as const,
|
|
28
29
|
// Server-level handleHotUpdate — sends custom WS event to client
|
|
30
|
+
// Vite 6 Environment API: hotUpdate runs per-environment.
|
|
31
|
+
// Prevent server/ssr environments from triggering page reload for client components.
|
|
32
|
+
hotUpdate(ctx: any) {
|
|
33
|
+
const { file, server } = ctx;
|
|
34
|
+
const envName = ctx.environment?.name ?? 'unknown';
|
|
35
|
+
|
|
36
|
+
const moduleBase = userOptions.moduleBase || "src";
|
|
37
|
+
const projectRoot = userOptions.projectRoot || server?.config?.root || '';
|
|
38
|
+
const normalizedFile = file.replace(projectRoot, '').replace(/^\/+/, '');
|
|
39
|
+
const isSourceFile = normalizedFile.startsWith(moduleBase + '/');
|
|
40
|
+
|
|
41
|
+
if (!isSourceFile) return;
|
|
42
|
+
|
|
43
|
+
// Client environment: let Vite/@vitejs/plugin-react handle it
|
|
44
|
+
if (envName === 'client') {
|
|
45
|
+
// Check if it's a client component — let Fast Refresh handle it
|
|
46
|
+
const isClient = (file.endsWith('.tsx') || file.endsWith('.ts') || file.endsWith('.jsx') || file.endsWith('.js')) && (() => {
|
|
47
|
+
try {
|
|
48
|
+
const head = readFileSync(file, 'utf-8').slice(0, 200);
|
|
49
|
+
return /^\s*["']use client["']/.test(head.split('\n')[0]);
|
|
50
|
+
} catch { return false; }
|
|
51
|
+
})();
|
|
52
|
+
|
|
53
|
+
if (isClient) return; // Let Fast Refresh handle client components
|
|
54
|
+
|
|
55
|
+
// Server component changed — send RSC refetch event to client
|
|
56
|
+
// Only do this once (from client env) to avoid duplicate events
|
|
57
|
+
server.config.logger.info(`[vite-plugin-react-server] File changed (RSC refetch): ${normalizedFile}`);
|
|
58
|
+
server.ws.send({
|
|
59
|
+
type: 'custom',
|
|
60
|
+
event: 'vite-plugin-react-server:server-component-update',
|
|
61
|
+
data: { file: normalizedFile, path: file },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return []; // Don't trigger client-side page reload
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Server/SSR environments: suppress page reload for all source files
|
|
68
|
+
// Server components are handled by the RSC refetch event sent above
|
|
69
|
+
// Invalidate the server module so next RSC request gets fresh content
|
|
70
|
+
if (envName === 'server') {
|
|
71
|
+
const mod = ctx.environment?.moduleGraph?.getModulesByFile(file);
|
|
72
|
+
if (mod) {
|
|
73
|
+
for (const m of mod) {
|
|
74
|
+
ctx.environment.moduleGraph.invalidateModule(m);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return [];
|
|
79
|
+
},
|
|
29
80
|
handleHotUpdate({ file, server }: { file: string; server: ViteDevServer }) {
|
|
30
81
|
const moduleBase = userOptions.moduleBase || "src";
|
|
31
82
|
const projectRoot = userOptions.projectRoot || server.config.root;
|
|
32
83
|
const normalizedFile = file.replace(projectRoot, '').replace(/^\/+/, '');
|
|
33
|
-
const
|
|
84
|
+
const isSourceFile = normalizedFile.startsWith(moduleBase + '/') &&
|
|
34
85
|
(file.endsWith('.tsx') || file.endsWith('.ts') || file.endsWith('.jsx') || file.endsWith('.js'));
|
|
35
86
|
|
|
36
|
-
|
|
37
|
-
|
|
87
|
+
// Skip client components — let @vitejs/plugin-react handle them
|
|
88
|
+
// with Fast Refresh (preserves component-level state).
|
|
89
|
+
const isClientFile = isSourceFile && (() => {
|
|
90
|
+
try {
|
|
91
|
+
const head = readFileSync(file, 'utf-8').slice(0, 200);
|
|
92
|
+
return /^\s*["']use client["']/.test(head.split('\n')[0]);
|
|
93
|
+
} catch { return false; }
|
|
94
|
+
})();
|
|
95
|
+
|
|
96
|
+
if (isSourceFile && !isClientFile) {
|
|
97
|
+
server.config.logger.info(`[vite-plugin-react-server] File changed (RSC refetch): ${normalizedFile}`);
|
|
38
98
|
|
|
39
99
|
// Send custom HMR event so client can refetch RSC stream
|
|
40
100
|
server.ws.send({
|
|
@@ -58,13 +118,20 @@ export const vitePluginReactDevServer = function _vitePluginReactServerDevServer
|
|
|
58
118
|
// The client will refetch the RSC stream via the custom event
|
|
59
119
|
return [];
|
|
60
120
|
}
|
|
121
|
+
|
|
122
|
+
if (isClientFile) {
|
|
123
|
+
// Client components are handled by @vitejs/plugin-react (Fast Refresh)
|
|
124
|
+
// or Vite's client-side HMR. Return empty to prevent the server
|
|
125
|
+
// environment from triggering a full page reload.
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
61
128
|
},
|
|
62
129
|
};
|
|
63
130
|
|
|
64
131
|
const serverPlugin = {
|
|
65
132
|
name: "vite-plugin-react-server:dev-server-server",
|
|
66
133
|
apply: "serve" as const,
|
|
67
|
-
|
|
134
|
+
applyToEnvironment(partialEnvironment: any) {
|
|
68
135
|
return partialEnvironment?.consumer === 'server';
|
|
69
136
|
},
|
|
70
137
|
configureServer(server: ViteDevServer) {
|
|
@@ -76,6 +76,8 @@ export function requestInfo(
|
|
|
76
76
|
const hasJsonHeader = req.headers["accept"]?.includes("application/json");
|
|
77
77
|
const hasHtmlHeader = req.headers.accept?.includes("text/html");
|
|
78
78
|
const hasRscHeader = req.headers.accept?.includes("text/x-component");
|
|
79
|
+
// Support ?_rsc query param (e.g. /?_rsc for browser debugging) as alternative to Accept header (useful for browser debugging)
|
|
80
|
+
const hasRscQueryParam = /[?&]_rsc\b/.test(req.url || "");
|
|
79
81
|
const hasCssHeader = req.headers.accept?.includes("text/css");
|
|
80
82
|
const isFolder = !ext;
|
|
81
83
|
const isFormContentType =
|
|
@@ -112,15 +114,16 @@ export function requestInfo(
|
|
|
112
114
|
// Form action detection
|
|
113
115
|
|
|
114
116
|
const isHtmlRequest =
|
|
115
|
-
isHtml ||
|
|
117
|
+
!hasRscQueryParam && (isHtml ||
|
|
116
118
|
hasHtmlHeader ||
|
|
117
119
|
(isFolder &&
|
|
118
120
|
!hasRscHeader &&
|
|
121
|
+
!hasRscQueryParam &&
|
|
119
122
|
!isRsc &&
|
|
120
123
|
!isJsRequest &&
|
|
121
|
-
!isFormActionRequest);
|
|
124
|
+
!isFormActionRequest));
|
|
122
125
|
const isRscRequest =
|
|
123
|
-
!isJsRequest && !isHtmlRequest && (isRsc || hasRscHeader);
|
|
126
|
+
hasRscQueryParam || (!isJsRequest && !isHtmlRequest && (isRsc || hasRscHeader));
|
|
124
127
|
const isCssRequest =
|
|
125
128
|
!isHtmlRequest &&
|
|
126
129
|
!isRscRequest &&
|
|
@@ -7,8 +7,9 @@ export function requestToRoute(
|
|
|
7
7
|
"moduleBasePath" | "moduleBaseURL" | "build"
|
|
8
8
|
>
|
|
9
9
|
) {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// Strip query string before route matching
|
|
11
|
+
let route = req.url?.split("?")[0]
|
|
12
|
+
.replace(
|
|
12
13
|
handlerOptions.moduleBaseURL + handlerOptions.build.rscOutputPath,
|
|
13
14
|
""
|
|
14
15
|
)
|
|
@@ -31,7 +31,8 @@ import type {
|
|
|
31
31
|
AutoDiscoveredFiles,
|
|
32
32
|
VitePluginFn,
|
|
33
33
|
} from "../types.js";
|
|
34
|
-
import {
|
|
34
|
+
import { renderPagesBatched } from "./renderPagesBatched.js";
|
|
35
|
+
import { renderPages as renderPagesSequential } from "./renderPages.js";
|
|
35
36
|
import { getBundleManifest } from "../helpers/getBundleManifest.js";
|
|
36
37
|
import { createWorker } from "../worker/createWorker.js";
|
|
37
38
|
import {
|
|
@@ -445,6 +446,14 @@ export const reactStaticPlugin: VitePluginFn = function _reactStaticPlugin(
|
|
|
445
446
|
}
|
|
446
447
|
}
|
|
447
448
|
|
|
449
|
+
// Select render mode based on build config
|
|
450
|
+
const renderMode = userOptions.build?.renderMode ?? "parallel";
|
|
451
|
+
const renderPages = renderMode === "sequential" ? renderPagesSequential : renderPagesBatched;
|
|
452
|
+
|
|
453
|
+
if (userOptions.verbose) {
|
|
454
|
+
logger.info(`[static] Using ${renderMode} rendering${renderMode === "parallel" ? ` (batch size: ${userOptions.build?.batchSize ?? 8})` : ""}`);
|
|
455
|
+
}
|
|
456
|
+
|
|
448
457
|
// this will render the routes
|
|
449
458
|
const renderPagesGenerator = renderPages(
|
|
450
459
|
routes,
|
|
@@ -465,6 +474,7 @@ export const reactStaticPlugin: VitePluginFn = function _reactStaticPlugin(
|
|
|
465
474
|
staticManifest: staticManifest, // Pass static manifest for path resolution
|
|
466
475
|
autoDiscoveredFiles: autoDiscoveredFiles!,
|
|
467
476
|
cssFilesByPage: cssFilesByPage,
|
|
477
|
+
batchSize: userOptions.build?.batchSize,
|
|
468
478
|
},
|
|
469
479
|
renderPage
|
|
470
480
|
);
|