Skip to content

Commit cae1de3

Browse files
fix: don't send browser full-reload for server-only modules by default
hotUpdate hook was unconditionally sending server.ws.send full-reload when any server-only module was detected, destroying client-side HMR. Split modules into server-only vs shared, only browser-reload when ALL modules are server-only and serverReload is explicitly enabled (default changed from true to false).
1 parent f663e76 commit cae1de3

2 files changed

Lines changed: 22 additions & 12 deletions

File tree

src/build/vite/plugin.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -238,31 +238,36 @@ function nitroMain(ctx: NitroPluginContext): VitePlugin {
238238
return configureViteDevServer(ctx, server);
239239
},
240240

241-
// Automatically reload the client when a server module is updated
241+
// Invalidate server-only modules and optionally reload the browser
242242
// see: https://github.com/vitejs/vite/issues/19114
243243
async hotUpdate({ server, modules, timestamp }) {
244244
const env = this.environment;
245-
if (
246-
ctx.pluginConfig.experimental?.vite.serverReload === false ||
247-
env.config.consumer === "client"
248-
) {
245+
if (env.config.consumer === "client") {
249246
return;
250247
}
251248
const clientEnvs = Object.values(server.environments).filter(
252249
(env) => env.config.consumer === "client"
253250
);
254-
let hasServerOnlyModule = false;
251+
const serverOnlyModules: EnvironmentModuleNode[] = [];
252+
const sharedModules: EnvironmentModuleNode[] = [];
255253
const invalidated = new Set<EnvironmentModuleNode>();
256254
for (const mod of modules) {
257255
if (mod.id && !clientEnvs.some((env) => env.moduleGraph.getModuleById(mod.id!))) {
258-
hasServerOnlyModule = true;
256+
serverOnlyModules.push(mod);
259257
env.moduleGraph.invalidateModule(mod, invalidated, timestamp, false);
258+
} else {
259+
sharedModules.push(mod);
260260
}
261261
}
262-
if (hasServerOnlyModule) {
262+
if (serverOnlyModules.length > 0) {
263263
env.hot.send({ type: "full-reload" });
264-
server.ws.send({ type: "full-reload" });
265-
return [];
264+
if (
265+
sharedModules.length === 0 &&
266+
ctx.pluginConfig.experimental?.vite.serverReload
267+
) {
268+
server.ws.send({ type: "full-reload" });
269+
}
270+
return sharedModules;
266271
}
267272
},
268273
};

src/build/vite/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,14 @@ export interface NitroPluginConfig extends NitroConfig {
3030
assetsImport?: boolean;
3131

3232
/**
33-
* Reload the page when a server module is updated.
33+
* Reload the browser page when a server-only module is updated.
3434
*
35-
* @default true
35+
* When disabled, server-only module changes will still invalidate the
36+
* server runtime but won't trigger a browser full-reload. This prevents
37+
* destroying client-side HMR updates when a file produces both client
38+
* and server-only modules.
39+
*
40+
* @default false
3641
*/
3742
serverReload?: boolean;
3843

0 commit comments

Comments
 (0)