vite-plugin-react-server 1.4.0 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-react-server",
3
- "version": "1.4.0",
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",
@@ -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 handleHotUpdate
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[]) => {
@@ -35,8 +35,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
35
35
  return {
36
36
  name: "vite-plugin-react-server:dev-server-client",
37
37
  apply: "serve", // Only apply in dev server mode
38
- // Note: Removed applyToEnvironment - handleHotUpdate needs to run regardless
39
- // The plugin should apply to client environment, but handleHotUpdate is a dev server hook
38
+ // No applyToEnvironment hotUpdate needs to run for all environments
40
39
  // that should work regardless of environment filtering
41
40
  config(_config, viteConfigEnv) {
42
41
  configEnv = viteConfigEnv;
@@ -73,7 +72,13 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
73
72
  resolvedConfig: server.config,
74
73
  });
75
74
  },
76
- handleHotUpdate({ file, server }) {
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
+
77
82
  // Prevent recursive HMR updates
78
83
  if (isProcessingHmr) {
79
84
  return undefined;
@@ -98,9 +103,6 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
98
103
 
99
104
  const isServerFile = isSourceFile && !isClientFile;
100
105
 
101
- // Always log for debugging
102
- server.config.logger.info(`[vite-plugin-react-server] handleHotUpdate: file=${file}, normalized=${normalizedFile}, isServerFile=${isServerFile}, isClientFile=${isClientFile}, hasHandler=${!!hmrHandler}`);
103
-
104
106
  if (isServerFile && hmrHandler) {
105
107
  isProcessingHmr = true;
106
108
 
@@ -111,17 +113,8 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
111
113
  // This clears component caches, but Node.js's ES module cache persists
112
114
  hmrHandler.sendHmrUpdate(file);
113
115
 
114
- // CRITICAL: Send custom HMR message to client via WebSocket
115
- // Server components aren't in the client bundle, so vite:beforeUpdate doesn't fire
116
- // We need to manually notify the client to refetch the RSC stream
117
- server.ws.send({
118
- type: 'custom',
119
- event: 'vite-plugin-react-server:server-component-update',
120
- data: {
121
- file: normalizedFile,
122
- path: file,
123
- },
124
- });
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.
125
118
 
126
119
  // CRITICAL: Node.js caches ES modules, so we need to restart the worker
127
120
  // to clear the module cache. Debounce restarts to prevent recursion.
@@ -150,7 +143,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
150
143
  }, 500); // 500ms debounce
151
144
  } else {
152
145
  // No restart function available yet - worker hasn't been created
153
- // This is expected if handleHotUpdate fires before the first request
146
+ // This is expected if hotUpdate fires before the first request
154
147
  server.config.logger.warn(`[vite-plugin-react-server] Restart function not available yet - worker will be created on next request`);
155
148
  setTimeout(() => {
156
149
  isProcessingHmr = false;
@@ -164,8 +157,7 @@ export const vitePluginReactDevServer: VitePluginFn = function _vitePluginReactS
164
157
  server.config.logger.warn(`[vite-plugin-react-server] Server file changed but HMR handler not available yet: ${file}`);
165
158
  }
166
159
 
167
- // Return undefined to allow other plugins to handle the update
168
- return undefined;
160
+ // Don't suppress plugin.server.ts hotUpdate handles page reload prevention
169
161
  },
170
162
  };
171
163
  };
@@ -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
- let route = req.url
11
- ?.replace(
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
  )