Skip to content
Merged
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions .changeset/ten-pears-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-router/dev": patch
---

Skip unnecessary `routes.ts` evaluation before Vite build is started
123 changes: 69 additions & 54 deletions packages/react-router-dev/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,12 @@ async function resolveConfig({
root,
viteNodeContext,
reactRouterConfigFile,
skipRoutes,
}: {
root: string;
viteNodeContext: ViteNode.Context;
reactRouterConfigFile?: string;
skipRoutes?: boolean;
}): Promise<Result<ResolvedReactRouterConfig>> {
let reactRouterUserConfig: ReactRouterConfig = {};

Expand Down Expand Up @@ -499,61 +501,67 @@ async function resolveConfig({
);
}

let routes: RouteManifest = {
root: { path: "", id: "root", file: rootRouteFile },
};
let routes: RouteManifest = {};

let routeConfigFile = findEntry(appDirectory, "routes");
if (!skipRoutes) {
routes = {
root: { path: "", id: "root", file: rootRouteFile },
};

try {
if (!routeConfigFile) {
let routeConfigDisplayPath = Path.relative(
root,
Path.join(appDirectory, "routes.ts")
);
return err(`Route config file not found at "${routeConfigDisplayPath}".`);
}
let routeConfigFile = findEntry(appDirectory, "routes");

setAppDirectory(appDirectory);
let routeConfigExport = (
await viteNodeContext.runner.executeFile(
Path.join(appDirectory, routeConfigFile)
)
).default;
let routeConfig = await routeConfigExport;

let result = validateRouteConfig({
routeConfigFile,
routeConfig,
});
try {
if (!routeConfigFile) {
let routeConfigDisplayPath = Path.relative(
root,
Path.join(appDirectory, "routes.ts")
);
return err(
`Route config file not found at "${routeConfigDisplayPath}".`
);
}

if (!result.valid) {
return err(result.message);
}
setAppDirectory(appDirectory);
let routeConfigExport = (
await viteNodeContext.runner.executeFile(
Path.join(appDirectory, routeConfigFile)
)
).default;
let routeConfig = await routeConfigExport;

let result = validateRouteConfig({
routeConfigFile,
routeConfig,
});

routes = {
...routes,
...configRoutesToRouteManifest(appDirectory, routeConfig),
};
} catch (error: any) {
return err(
[
colors.red(`Route config in "${routeConfigFile}" is invalid.`),
"",
error.loc?.file && error.loc?.column && error.frame
? [
Path.relative(appDirectory, error.loc.file) +
":" +
error.loc.line +
":" +
error.loc.column,
error.frame.trim?.(),
]
: error.stack,
]
.flat()
.join("\n")
);
if (!result.valid) {
return err(result.message);
}

routes = {
...routes,
...configRoutesToRouteManifest(appDirectory, routeConfig),
};
} catch (error: any) {
return err(
[
colors.red(`Route config in "${routeConfigFile}" is invalid.`),
"",
error.loc?.file && error.loc?.column && error.frame
? [
Path.relative(appDirectory, error.loc.file) +
":" +
error.loc.line +
":" +
error.loc.column,
error.frame.trim?.(),
]
: error.stack,
]
.flat()
.join("\n")
);
}
}

let future: FutureConfig = {
Expand Down Expand Up @@ -613,10 +621,12 @@ export async function createConfigLoader({
rootDirectory: root,
watch,
mode,
skipRoutes,
}: {
watch: boolean;
rootDirectory?: string;
mode: string;
skipRoutes?: boolean;
}): Promise<ConfigLoader> {
root = Path.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());

Expand All @@ -641,7 +651,7 @@ export async function createConfigLoader({
updateReactRouterConfigFile();

let getConfig = () =>
resolveConfig({ root, viteNodeContext, reactRouterConfigFile });
resolveConfig({ root, viteNodeContext, reactRouterConfigFile, skipRoutes });

let appDirectory: string;

Expand Down Expand Up @@ -740,9 +750,11 @@ export async function createConfigLoader({
filepath
));

let routeConfigFile = findEntry(appDirectory, "routes", {
absolute: true,
});
let routeConfigFile = !skipRoutes
? findEntry(appDirectory, "routes", {
absolute: true,
})
: undefined;
let routeConfigCodeChanged =
routeConfigFile !== undefined &&
isEntryFileDependency(
Expand Down Expand Up @@ -793,13 +805,16 @@ export async function createConfigLoader({
export async function loadConfig({
rootDirectory,
mode,
skipRoutes,
}: {
rootDirectory: string;
mode: string;
skipRoutes?: boolean;
}) {
let configLoader = await createConfigLoader({
rootDirectory,
mode,
skipRoutes,
watch: false,
});
let config = await configLoader.getConfig();
Expand Down
3 changes: 3 additions & 0 deletions packages/react-router-dev/vite/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export async function build(root: string, viteBuildOptions: ViteBuildOptions) {
let configResult = await loadConfig({
rootDirectory: root,
mode: viteBuildOptions.mode ?? "production",
// In this scope we only need future flags, so we can skip evaluating
// routes.ts until we're within the Vite build context
skipRoutes: true,
});

if (!configResult.ok) {
Expand Down