Skip to content

Commit 9f7f706

Browse files
committed
Handle route config changes in RSC Framework Mode
1 parent 353d05f commit 9f7f706

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
@@ -2,6 +2,7 @@ import type * as Vite from "vite";
22
import rsc, { type RscPluginOptions } from "@vitejs/plugin-rsc";
33
import { init as initEsModuleLexer } from "es-module-lexer";
44
import * as babel from "@babel/core";
5+
import colors from "picocolors";
56

67
import { create } from "../virtual-module";
78
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
return {
6270
resolve: {
6371
dedupe: [
@@ -139,6 +147,46 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
139147
},
140148
};
141149
},
150+
async configureServer(viteDevServer) {
151+
configLoader.onChange(
152+
async ({
153+
result,
154+
configCodeChanged,
155+
routeConfigCodeChanged,
156+
configChanged,
157+
routeConfigChanged,
158+
}) => {
159+
if (!result.ok) {
160+
invalidateVirtualModules(viteDevServer);
161+
logger.error(result.error, {
162+
clear: true,
163+
timestamp: true,
164+
});
165+
return;
166+
}
167+
168+
// prettier-ignore
169+
let message =
170+
configChanged ? "Config changed." :
171+
routeConfigChanged ? "Route config changed." :
172+
configCodeChanged ? "Config saved." :
173+
routeConfigCodeChanged ? " Route config saved." :
174+
"Config saved";
175+
176+
logger.info(colors.green(message), {
177+
clear: true,
178+
timestamp: true,
179+
});
180+
181+
// Update shared plugin config reference
182+
config = result.value;
183+
184+
if (configChanged || routeConfigChanged) {
185+
invalidateVirtualModules(viteDevServer);
186+
}
187+
},
188+
);
189+
},
142190
async buildEnd() {
143191
await configLoader.close();
144192
},
@@ -370,6 +418,17 @@ const virtual = {
370418
basename: create("unstable_rsc/basename"),
371419
};
372420

421+
function invalidateVirtualModules(viteDevServer: Vite.ViteDevServer) {
422+
for (const vmod of Object.values(virtual)) {
423+
for (const env of Object.values(viteDevServer.environments)) {
424+
const mod = env.moduleGraph.getModuleById(vmod.resolvedId);
425+
if (mod) {
426+
env.moduleGraph.invalidateModule(mod);
427+
}
428+
}
429+
}
430+
}
431+
373432
function getRootDirectory(viteUserConfig: Vite.UserConfig) {
374433
return viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
375434
}

0 commit comments

Comments
 (0)