Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions packages/react-router-dev/vite/rsc/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type * as Vite from "vite";
import { init as initEsModuleLexer } from "es-module-lexer";
import * as babel from "@babel/core";
import colors from "picocolors";

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

return [
{
name: "react-router/rsc",
async config(viteUserConfig, { command, mode }) {
await initEsModuleLexer;

viteCommand = command;
const rootDirectory = getRootDirectory(viteUserConfig);
const watch = command === "serve";
Expand All @@ -58,6 +61,11 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
);
}

const vite = await import("vite");
logger = vite.createLogger(viteUserConfig.logLevel, {
prefix: "[react-router]",
});

const rscEntries = getRscEntries();

return {
Expand Down Expand Up @@ -147,6 +155,46 @@ export function reactRouterRSCVitePlugin(): Vite.PluginOption[] {
},
};
},
async configureServer(viteDevServer) {
configLoader.onChange(
async ({
result,
configCodeChanged,
routeConfigCodeChanged,
configChanged,
routeConfigChanged,
}) => {
if (!result.ok) {
invalidateVirtualModules(viteDevServer);
logger.error(result.error, {
clear: true,
timestamp: true,
});
return;
}

// prettier-ignore
let message =
configChanged ? "Config changed." :
routeConfigChanged ? "Route config changed." :
configCodeChanged ? "Config saved." :
routeConfigCodeChanged ? " Route config saved." :
"Config saved";

logger.info(colors.green(message), {
clear: true,
timestamp: true,
});

// Update shared plugin config reference
config = result.value;

if (configChanged || routeConfigChanged) {
invalidateVirtualModules(viteDevServer);
}
},
);
},
async buildEnd() {
await configLoader.close();
},
Expand Down Expand Up @@ -377,6 +425,17 @@ const virtual = {
basename: create("unstable_rsc/basename"),
};

function invalidateVirtualModules(viteDevServer: Vite.ViteDevServer) {
for (const vmod of Object.values(virtual)) {
for (const env of Object.values(viteDevServer.environments)) {
const mod = env.moduleGraph.getModuleById(vmod.resolvedId);
if (mod) {
env.moduleGraph.invalidateModule(mod);
}
}
}
}

function getRootDirectory(viteUserConfig: Vite.UserConfig) {
return viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
}
Expand Down
Loading