@@ -2,6 +2,7 @@ import type * as Vite from "vite";
22import rsc , { type RscPluginOptions } from "@vitejs/plugin-rsc" ;
33import { init as initEsModuleLexer } from "es-module-lexer" ;
44import * as babel from "@babel/core" ;
5+ import colors from "picocolors" ;
56
67import { create } from "../virtual-module" ;
78import * 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+
373432function getRootDirectory ( viteUserConfig : Vite . UserConfig ) {
374433 return viteUserConfig . root ?? process . env . REACT_ROUTER_ROOT ?? process . cwd ( ) ;
375434}
0 commit comments