Skip to content

Commit 88ae476

Browse files
committed
Merge branch 'dev' into fix/middleware-skip-revalidation
2 parents 62b32ed + 64f8b8a commit 88ae476

File tree

8 files changed

+183
-59
lines changed

8 files changed

+183
-59
lines changed

packages/react-router-dev/cli/commands.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { transpile as convertFileToJS } from "./useJavascript";
1616
import * as profiler from "../vite/profiler";
1717
import * as Typegen from "../typegen";
1818
import { preloadVite, getVite } from "../vite/vite";
19+
import { hasReactRouterRscPlugin } from "../vite/has-rsc-plugin";
1920

2021
export async function routes(
2122
rootDirectory?: string,
@@ -89,14 +90,32 @@ export async function generateEntry(
8990
mode?: string;
9091
} = {},
9192
) {
93+
rootDirectory = resolveRootDirectory(rootDirectory, flags);
94+
95+
if (
96+
await hasReactRouterRscPlugin({
97+
root: rootDirectory,
98+
viteBuildOptions: {
99+
config: flags.config,
100+
mode: flags.mode,
101+
},
102+
})
103+
) {
104+
console.error(
105+
colors.red(
106+
`The reveal command is currently not supported in RSC Framework Mode.`,
107+
),
108+
);
109+
process.exit(1);
110+
}
111+
92112
// if no entry passed, attempt to create both
93113
if (!entry) {
94114
await generateEntry("entry.client", rootDirectory, flags);
95115
await generateEntry("entry.server", rootDirectory, flags);
96116
return;
97117
}
98118

99-
rootDirectory = resolveRootDirectory(rootDirectory, flags);
100119
let configResult = await loadConfig({
101120
rootDirectory,
102121
mode: flags.mode ?? "production",

packages/react-router-dev/config/config.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
8383

8484
type ServerModuleFormat = "esm" | "cjs";
8585

86+
type ValidateConfigFunction = (config: ReactRouterConfig) => string | void;
87+
8688
interface FutureConfig {
8789
/**
8890
* Enable route middleware
@@ -356,11 +358,13 @@ async function resolveConfig({
356358
viteNodeContext,
357359
reactRouterConfigFile,
358360
skipRoutes,
361+
validateConfig,
359362
}: {
360363
root: string;
361364
viteNodeContext: ViteNode.Context;
362365
reactRouterConfigFile?: string;
363366
skipRoutes?: boolean;
367+
validateConfig?: ValidateConfigFunction;
364368
}): Promise<Result<ResolvedReactRouterConfig>> {
365369
let reactRouterUserConfig: ReactRouterConfig = {};
366370

@@ -383,6 +387,13 @@ async function resolveConfig({
383387
}
384388

385389
reactRouterUserConfig = configModule.default;
390+
391+
if (validateConfig) {
392+
const error = validateConfig(reactRouterUserConfig);
393+
if (error) {
394+
return err(error);
395+
}
396+
}
386397
} catch (error) {
387398
return err(`Error loading ${reactRouterConfigFile}: ${error}`);
388399
}
@@ -631,11 +642,13 @@ export async function createConfigLoader({
631642
watch,
632643
mode,
633644
skipRoutes,
645+
validateConfig,
634646
}: {
635647
watch: boolean;
636648
rootDirectory?: string;
637649
mode: string;
638650
skipRoutes?: boolean;
651+
validateConfig?: ValidateConfigFunction;
639652
}): Promise<ConfigLoader> {
640653
root = Path.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
641654

@@ -660,7 +673,13 @@ export async function createConfigLoader({
660673
updateReactRouterConfigFile();
661674

662675
let getConfig = () =>
663-
resolveConfig({ root, viteNodeContext, reactRouterConfigFile, skipRoutes });
676+
resolveConfig({
677+
root,
678+
viteNodeContext,
679+
reactRouterConfigFile,
680+
skipRoutes,
681+
validateConfig,
682+
});
664683

665684
let appDirectory: string;
666685

packages/react-router-dev/vite/build.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from "./plugin";
1616
import invariant from "../invariant";
1717
import { preloadVite, getVite } from "./vite";
18+
import { hasReactRouterRscPlugin } from "./has-rsc-plugin";
1819
export interface ViteBuildOptions {
1920
assetsInlineLimit?: number;
2021
clearScreen?: boolean;
@@ -234,27 +235,3 @@ async function viteBuild(
234235
viteConfig,
235236
});
236237
}
237-
238-
async function hasReactRouterRscPlugin({
239-
root,
240-
viteBuildOptions: { config, logLevel, mode },
241-
}: {
242-
root: string;
243-
viteBuildOptions: ViteBuildOptions;
244-
}): Promise<boolean> {
245-
const vite = await import("vite");
246-
const viteConfig = await vite.resolveConfig(
247-
{
248-
configFile: config,
249-
logLevel,
250-
mode: mode ?? "production",
251-
root,
252-
},
253-
"build", // command
254-
"production", // default mode
255-
"production", // default NODE_ENV
256-
);
257-
return viteConfig.plugins.some(
258-
(plugin) => plugin?.name === "react-router/rsc",
259-
);
260-
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type * as Vite from "vite";
2+
3+
export async function hasReactRouterRscPlugin({
4+
root,
5+
viteBuildOptions: { config, logLevel, mode },
6+
}: {
7+
root: string;
8+
viteBuildOptions: {
9+
config?: string;
10+
logLevel?: Vite.LogLevel;
11+
mode?: string;
12+
};
13+
}): Promise<boolean> {
14+
const vite = await import("vite");
15+
const viteConfig = await vite.resolveConfig(
16+
{
17+
configFile: config,
18+
logLevel,
19+
mode: mode ?? "production",
20+
root,
21+
},
22+
"build", // command
23+
"production", // default mode
24+
"production", // default NODE_ENV
25+
);
26+
return viteConfig.plugins.some(
27+
(plugin) => plugin?.name === "react-router/rsc",
28+
);
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { escapePath as escapePathAsGlob } from "tinyglobby";
2+
import type { ResolvedReactRouterConfig } from "../config/config";
3+
import { resolveRelativeRouteFilePath } from "./resolve-relative-route-file-path";
4+
import { getVite } from "./vite";
5+
6+
export function getOptimizeDepsEntries({
7+
entryClientFilePath,
8+
reactRouterConfig,
9+
}: {
10+
entryClientFilePath: string;
11+
reactRouterConfig: ResolvedReactRouterConfig;
12+
}) {
13+
if (!reactRouterConfig.future.unstable_optimizeDeps) {
14+
return [];
15+
}
16+
17+
const vite = getVite();
18+
const viteMajorVersion = parseInt(vite.version.split(".")[0], 10);
19+
20+
return [
21+
vite.normalizePath(entryClientFilePath),
22+
...Object.values(reactRouterConfig.routes).map((route) =>
23+
resolveRelativeRouteFilePath(route, reactRouterConfig),
24+
),
25+
].map((entry) =>
26+
// In Vite 7, the `optimizeDeps.entries` option only accepts glob patterns.
27+
// In prior versions, absolute file paths were treated differently.
28+
viteMajorVersion >= 7 ? escapePathAsGlob(entry) : entry,
29+
);
30+
}

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

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
} from "./styles";
5656
import * as VirtualModule from "./virtual-module";
5757
import { resolveFileUrl } from "./resolve-file-url";
58+
import { resolveRelativeRouteFilePath } from "./resolve-relative-route-file-path";
5859
import { combineURLs } from "./combine-urls";
5960
import { removeExports } from "./remove-exports";
6061
import { ssrExternals } from "./ssr-externals";
@@ -79,6 +80,7 @@ import {
7980
resolveEntryFiles,
8081
configRouteToBranchRoute,
8182
} from "../config/config";
83+
import { getOptimizeDepsEntries } from "./optimize-deps-entries";
8284
import { decorateComponentExportsWithProps } from "./with-props";
8385
import validatePluginOrder from "./plugins/validate-plugin-order";
8486

@@ -263,17 +265,6 @@ const normalizeRelativeFilePath = (
263265
return vite.normalizePath(relativePath).split("?")[0];
264266
};
265267

266-
const resolveRelativeRouteFilePath = (
267-
route: RouteManifestEntry,
268-
reactRouterConfig: ResolvedReactRouterConfig,
269-
) => {
270-
let vite = getVite();
271-
let file = route.file;
272-
let fullPath = path.resolve(reactRouterConfig.appDirectory, file);
273-
274-
return vite.normalizePath(fullPath);
275-
};
276-
277268
let virtual = {
278269
serverBuild: VirtualModule.create("server-build"),
279270
serverManifest: VirtualModule.create("server-manifest"),
@@ -1177,7 +1168,6 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
11771168

11781169
// Ensure sync import of Vite works after async preload
11791170
let vite = getVite();
1180-
let viteMajorVersion = parseInt(vite.version.split(".")[0], 10);
11811171

11821172
viteUserConfig = _viteUserConfig;
11831173
viteConfigEnv = _viteConfigEnv;
@@ -1259,18 +1249,10 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
12591249
resolve: serverEnvironment.resolve,
12601250
},
12611251
optimizeDeps: {
1262-
entries: ctx.reactRouterConfig.future.unstable_optimizeDeps
1263-
? [
1264-
vite.normalizePath(ctx.entryClientFilePath),
1265-
...Object.values(ctx.reactRouterConfig.routes).map((route) =>
1266-
resolveRelativeRouteFilePath(route, ctx.reactRouterConfig),
1267-
),
1268-
].map((entry) =>
1269-
// In Vite 7, the `optimizeDeps.entries` option only accepts glob patterns.
1270-
// In prior versions, absolute file paths were treated differently.
1271-
viteMajorVersion >= 7 ? escapePathAsGlob(entry) : entry,
1272-
)
1273-
: [],
1252+
entries: getOptimizeDepsEntries({
1253+
entryClientFilePath: ctx.entryClientFilePath,
1254+
reactRouterConfig: ctx.reactRouterConfig,
1255+
}),
12741256
include: [
12751257
// Pre-bundle React dependencies to avoid React duplicates,
12761258
// even if React dependencies are not direct dependencies.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import path from "pathe";
2+
import type { ResolvedReactRouterConfig } from "../config/config";
3+
import type { RouteManifestEntry } from "../config/routes";
4+
import { getVite } from "./vite";
5+
6+
export function resolveRelativeRouteFilePath(
7+
route: RouteManifestEntry,
8+
reactRouterConfig: ResolvedReactRouterConfig,
9+
) {
10+
let vite = getVite();
11+
let file = route.file;
12+
let fullPath = path.resolve(reactRouterConfig.appDirectory, file);
13+
return vite.normalizePath(fullPath);
14+
}

0 commit comments

Comments
 (0)