Skip to content

Commit 23b62b6

Browse files
Handle route config changes in RSC Framework Mode (#14272)
1 parent c37c53c commit 23b62b6

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

packages/react-router-dev/vite/rsc/plugin.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type * as Vite from "vite";
22
import { init as initEsModuleLexer } from "es-module-lexer";
33
import * as babel from "@babel/core";
4+
import colors from "picocolors";
45

56
import { create } from "../virtual-module";
67
import * as Typegen from "../../typegen";
@@ -28,12 +29,14 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
2829
let typegenWatcherPromise: Promise<Typegen.Watcher> | undefined;
2930
let viteCommand: Vite.ConfigEnv["command"];
3031
let routeIdByFile: Map<string, string> | undefined;
32+
let logger: Vite.Logger;
3133

3234
return [
3335
{
3436
name: "react-router/rsc",
3537
async config(viteUserConfig, { command, mode }) {
3638
await initEsModuleLexer;
39+
3740
viteCommand = command;
3841
const rootDirectory = getRootDirectory(viteUserConfig);
3942
const watch = command === "serve";
@@ -58,6 +61,11 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
5861
);
5962
}
6063

64+
const vite = await import("vite");
65+
logger = vite.createLogger(viteUserConfig.logLevel, {
66+
prefix: "[react-router]",
67+
});
68+
6169
const rscEntries = getRscEntries();
6270

6371
return {
@@ -147,6 +155,46 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
147155
},
148156
};
149157
},
158+
async configureServer(viteDevServer) {
159+
configLoader.onChange(
160+
async ({
161+
result,
162+
configCodeChanged,
163+
routeConfigCodeChanged,
164+
configChanged,
165+
routeConfigChanged,
166+
}) => {
167+
if (!result.ok) {
168+
invalidateVirtualModules(viteDevServer);
169+
logger.error(result.error, {
170+
clear: true,
171+
timestamp: true,
172+
});
173+
return;
174+
}
175+
176+
// prettier-ignore
177+
let message =
178+
configChanged ? "Config changed." :
179+
routeConfigChanged ? "Route config changed." :
180+
configCodeChanged ? "Config saved." :
181+
routeConfigCodeChanged ? " Route config saved." :
182+
"Config saved";
183+
184+
logger.info(colors.green(message), {
185+
clear: true,
186+
timestamp: true,
187+
});
188+
189+
// Update shared plugin config reference
190+
config = result.value;
191+
192+
if (configChanged || routeConfigChanged) {
193+
invalidateVirtualModules(viteDevServer);
194+
}
195+
},
196+
);
197+
},
150198
async buildEnd() {
151199
await configLoader.close();
152200
},
@@ -377,6 +425,17 @@ const virtual = {
377425
basename: create("unstable_rsc/basename"),
378426
};
379427

428+
function invalidateVirtualModules(viteDevServer: Vite.ViteDevServer) {
429+
for (const vmod of Object.values(virtual)) {
430+
for (const env of Object.values(viteDevServer.environments)) {
431+
const mod = env.moduleGraph.getModuleById(vmod.resolvedId);
432+
if (mod) {
433+
env.moduleGraph.invalidateModule(mod);
434+
}
435+
}
436+
}
437+
}
438+
380439
function getRootDirectory(viteUserConfig: Vite.UserConfig) {
381440
return viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
382441
}

0 commit comments

Comments
 (0)