Skip to content

Commit 2a3b0e5

Browse files
authored
fix(react): support Vite 8 for React Router apps (#35365)
## Current Behavior `@react-router/dev` peer dep tops out at Vite 7, so the React app generator forces Vite 7 when `--use-react-router` is passed, and the react-router typecheck e2e test is skipped in CI. ## Expected Behavior `@react-router/dev` 7.14.2 expands its peer dep to include Vite 8 (`^5.1.0 || ^6.0.0 || ^7.0.0 || ^8.0.0`), so: - `useViteV7: true` is no longer forced when generating a React Router app - The `useViteV7` field is removed from `ViteConfigurationGeneratorSchema` (was only added for this workaround and was never wired into the configuration generator body) - The react-router typecheck e2e test is un-skipped - `reactRouterVersion` is bumped to `^7.14.2` - A new `22.7.0` packageJsonUpdate migrates `@react-router/*` packages to `7.14.2` in existing workspaces ## Related Issue(s) Fixes NXC-4182
1 parent 7b42332 commit 2a3b0e5

6 files changed

Lines changed: 99 additions & 6 deletions

File tree

e2e/react/src/react-router-ts-solution.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ describe('React Router Applications - TS Solution', () => {
3737
checkFilesExist(`${appName}/vite.config.mts`);
3838
});
3939

40-
// TODO: re-enable once @react-router/dev supports Vite 8 — currently pnpm can resolve both vite 7 and 8, causing typecheck failures
41-
xit('should be able to build, lint, test and typecheck a react-router application', async () => {
40+
it('should be able to build, lint, test and typecheck a react-router application', async () => {
4241
const buildResult = runCLI(`build ${appName}`);
4342
const lintResult = runCLI(`lint ${appName}`);
4443
const testResult = runCLI(`test ${appName}`);

packages/react/migrations.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,47 @@
195195
"alwaysAddToPackageJson": false
196196
}
197197
}
198+
},
199+
"22.7.0": {
200+
"version": "22.7.0-beta.18",
201+
"packages": {
202+
"react-router": {
203+
"version": "7.14.2",
204+
"alwaysAddToPackageJson": false
205+
},
206+
"@react-router/dev": {
207+
"version": "7.14.2",
208+
"alwaysAddToPackageJson": false
209+
},
210+
"@react-router/node": {
211+
"version": "7.14.2",
212+
"alwaysAddToPackageJson": false
213+
},
214+
"@react-router/serve": {
215+
"version": "7.14.2",
216+
"alwaysAddToPackageJson": false
217+
},
218+
"@react-router/express": {
219+
"version": "7.14.2",
220+
"alwaysAddToPackageJson": false
221+
},
222+
"@react-router/fs-routes": {
223+
"version": "7.14.2",
224+
"alwaysAddToPackageJson": false
225+
},
226+
"@react-router/cloudflare": {
227+
"version": "7.14.2",
228+
"alwaysAddToPackageJson": false
229+
},
230+
"@react-router/architect": {
231+
"version": "7.14.2",
232+
"alwaysAddToPackageJson": false
233+
},
234+
"@react-router/remix-routes-option-adapter": {
235+
"version": "7.14.2",
236+
"alwaysAddToPackageJson": false
237+
}
238+
}
198239
}
199240
}
200241
}

packages/react/src/generators/application/application.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,29 @@ describe('app', () => {
11671167
expect(packageJson.devDependencies['@react-router/dev']).toBeDefined();
11681168
});
11691169

1170-
it('should use Vite 7 since React Router does not support Vite 8', async () => {
1170+
it('should default to Vite 8 when @react-router/dev supports it', async () => {
1171+
await applicationGenerator(appTree, {
1172+
...schema,
1173+
skipFormat: false,
1174+
useReactRouter: true,
1175+
routing: true,
1176+
bundler: 'vite',
1177+
unitTestRunner: 'vitest',
1178+
});
1179+
1180+
const rootPackageJson = readJson(appTree, 'package.json');
1181+
expect(rootPackageJson.devDependencies['vite']).toMatch(/^\^8\./);
1182+
});
1183+
1184+
it('should force Vite 7 when workspace has @react-router/dev < 7.14.0', async () => {
1185+
updateJson(appTree, 'package.json', (json) => {
1186+
json.devDependencies = {
1187+
...json.devDependencies,
1188+
'@react-router/dev': '7.13.2',
1189+
};
1190+
return json;
1191+
});
1192+
11711193
await applicationGenerator(appTree, {
11721194
...schema,
11731195
skipFormat: false,

packages/react/src/generators/application/lib/bundlers/add-vite.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { type Tree, ensurePackage, joinPathFragments } from '@nx/devkit';
22
import { nxVersion } from '../../../../utils/versions';
3+
import { reactRouterSupportsVite8 } from '../../../../utils/version-utils';
34
import { NormalizedSchema, Schema } from '../../schema';
45

56
export async function setupViteConfiguration(
@@ -32,6 +33,10 @@ export async function setupViteConfiguration(
3233
plugins: ['react()'],
3334
};
3435

36+
// @react-router/dev < 7.14.0 caps its Vite peer dep at ^7, so fall back to
37+
// Vite 7 when an older version is already installed in the workspace.
38+
const forceViteV7 = options.useReactRouter && !reactRouterSupportsVite8(tree);
39+
3540
const viteTask = await viteConfigurationGenerator(tree, {
3641
uiFramework: 'react',
3742
project: options.projectName,
@@ -43,8 +48,7 @@ export async function setupViteConfiguration(
4348
addPlugin: options.addPlugin,
4449
projectType: 'application',
4550
port: options.port,
46-
// React Router does not yet support Vite 8, so force Vite 7.
47-
...(options.useReactRouter ? { useViteV7: true } : {}),
51+
...(forceViteV7 ? { useViteV7: true } : {}),
4852
});
4953
tasks.push(viteTask);
5054
createOrEditViteConfig(

packages/react/src/utils/version-utils.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,30 @@ export async function getInstalledReactVersionFromGraph() {
8585
}
8686
return clean(reactDep.data.version) ?? coerce(reactDep.data.version).version;
8787
}
88+
89+
export function getInstalledReactRouterDevVersion(
90+
tree: Tree
91+
): string | undefined {
92+
const installed = getDependencyVersionFromPackageJson(
93+
tree,
94+
'@react-router/dev'
95+
);
96+
97+
if (!installed || installed === 'latest' || installed === 'next') {
98+
return undefined;
99+
}
100+
101+
return clean(installed) ?? coerce(installed)?.version;
102+
}
103+
104+
export function reactRouterSupportsVite8(tree: Tree): boolean {
105+
const installed = getInstalledReactRouterDevVersion(tree);
106+
if (!installed) {
107+
return true;
108+
}
109+
const coerced = coerce(installed);
110+
if (!coerced) {
111+
return true;
112+
}
113+
return coerced.major > 7 || (coerced.major === 7 && coerced.minor >= 14);
114+
}

packages/react/src/utils/versions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const emotionBabelPlugin = '11.13.5';
3333
export const styledJsxVersion = '5.1.2';
3434

3535
export const reactRouterDomVersion = '6.30.3';
36-
export const reactRouterVersion = '^7.12.0';
36+
export const reactRouterVersion = '^7.14.2';
3737
export const reactRouterIsBotVersion = '^4.4.0';
3838

3939
export const testingLibraryReactVersion = '16.3.0';

0 commit comments

Comments
 (0)