Skip to content

Commit 87f8147

Browse files
Stabilize v8_splitRouteModules and v8_viteEnvironmentApi (#14595)
1 parent 173d7f4 commit 87f8147

27 files changed

+213
-121
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@react-router/dev": minor
3+
---
4+
5+
Stabilize `future.v8_splitRouteModules`, replacing `future.unstable_splitRouteModules`
6+
7+
- ⚠️ This is a breaking change if you have begun using `future.unstable_splitRouteModules`. Please update your `react-router.config.ts`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@react-router/dev": minor
3+
---
4+
5+
Stabilize `future.v8_viteEnvironmentApi`, replacing `future.unstable_viteEnvironmentApi`
6+
7+
- ⚠️ This is a breaking change if you have begun using `future.unstable_viteEnvironmentApi`. Please update your `react-router.config.ts`.

docs/how-to/react-server-components.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ For the initial unstable release, the following options from `react-router.confi
284284
- `routeDiscovery`
285285
- `serverBundles`
286286
- `ssr: false` (SPA Mode)
287-
- `future.unstable_splitRouteModules`
287+
- `future.v8_splitRouteModules`
288288
- `future.unstable_subResourceIntegrity`
289289

290290
Custom build entry files are also not yet supported.

docs/upgrading/future.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,60 @@ If you're using `react-router-serve`, then you should not need to make any updat
4848

4949
You should only need to update your code if you are using the `context` parameter in `loader` and `action` functions. This only applies if you have a custom server with a `getLoadContext` function. Please see the docs on the middleware [`getLoadContext` changes](../how-to/middleware#changes-to-getloadcontextapploadcontext) and the instructions to [migrate to the new API](../how-to/middleware#migration-from-apploadcontext).
5050

51+
## `future.v8_splitRouteModules`
52+
53+
[MODES: framework]
54+
55+
<br/>
56+
<br/>
57+
58+
**Background**
59+
60+
This feature enables splitting client-side route exports (`clientLoader`, `clientAction`, `clientMiddleware`, `HydrateFallback`) into separate chunks that can be loaded independently from the route component. This allows these exports to be fetched and executed while the component code is still downloading, improving performance for client-side data loading.
61+
62+
This can be set to `true` for opt-in behavior, or `"enforce"` to require all routes to be splittable (which will cause build failures for routes that cannot be split due to shared code).
63+
64+
👉 **Enable the Flag**
65+
66+
```ts filename=react-router.config.ts
67+
import type { Config } from "@react-router/dev/config";
68+
69+
export default {
70+
future: {
71+
v8_splitRouteModules: true,
72+
},
73+
} satisfies Config;
74+
```
75+
76+
**Update your Code**
77+
78+
No code changes are required. This is an optimization feature that works automatically once enabled.
79+
80+
## `future.v8_viteEnvironmentApi`
81+
82+
[MODES: framework]
83+
84+
<br/>
85+
<br/>
86+
87+
**Background**
88+
89+
This enables support for the experimental Vite Environment API, which provides a more flexible and powerful way to configure Vite environments. This is only available when using Vite 6+.
90+
91+
👉 **Enable the Flag**
92+
93+
```ts filename=react-router.config.ts
94+
import type { Config } from "@react-router/dev/config";
95+
96+
export default {
97+
future: {
98+
v8_viteEnvironmentApi: true,
99+
},
100+
} satisfies Config;
101+
```
102+
103+
**Update your Code**
104+
105+
No code changes are required unless you have custom Vite configuration that needs to be updated for the Environment API. Most users won't need to make any changes.
106+
51107
[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response

integration/client-data-test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,17 @@ test.describe("Client Data", () => {
125125
}
126126

127127
test.describe(`template: ${templateName}`, () => {
128-
for (const splitRouteModules of [true, false]) {
129-
test.describe(`splitRouteModules: ${splitRouteModules}`, () => {
128+
for (const v8_splitRouteModules of [true, false]) {
129+
test.describe(`v8_splitRouteModules: ${v8_splitRouteModules}`, () => {
130130
test.skip(
131-
templateName.includes("rsc") && splitRouteModules,
131+
templateName.includes("rsc") && v8_splitRouteModules,
132132
"RSC Framework Mode doesn't support splitRouteModules",
133133
);
134134

135135
test.skip(
136136
({ browserName }) =>
137137
Boolean(process.env.CI) &&
138-
splitRouteModules &&
138+
v8_splitRouteModules &&
139139
(browserName === "webkit" || process.platform === "win32"),
140140
"Webkit/Windows tests only run on a single worker in CI and splitRouteModules is not OS/browser-specific",
141141
);
@@ -149,7 +149,7 @@ test.describe("Client Data", () => {
149149
templateName,
150150
files: {
151151
"react-router.config.ts": reactRouterConfig({
152-
splitRouteModules,
152+
v8_splitRouteModules,
153153
}),
154154
"app/root.tsx": js`
155155
import { Form, Outlet, Scripts } from "react-router"

integration/helpers/vite-plugin-cloudflare-template/react-router.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import type { Config } from "@react-router/dev/config";
22

33
export default {
44
future: {
5-
unstable_viteEnvironmentApi: true,
5+
v8_viteEnvironmentApi: true,
66
},
77
} satisfies Config;

integration/helpers/vite.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,18 @@ export const reactRouterConfig = ({
2828
basename,
2929
prerender,
3030
appDirectory,
31-
splitRouteModules,
32-
viteEnvironmentApi,
3331
v8_middleware,
32+
v8_splitRouteModules,
33+
v8_viteEnvironmentApi,
3434
routeDiscovery,
3535
}: {
3636
ssr?: boolean;
3737
basename?: string;
3838
prerender?: boolean | string[];
3939
appDirectory?: string;
40-
splitRouteModules?: NonNullable<
41-
Config["future"]
42-
>["unstable_splitRouteModules"];
43-
viteEnvironmentApi?: boolean;
4440
v8_middleware?: boolean;
41+
v8_splitRouteModules?: NonNullable<Config["future"]>["v8_splitRouteModules"];
42+
v8_viteEnvironmentApi?: boolean;
4543
routeDiscovery?: Config["routeDiscovery"];
4644
}) => {
4745
let config: Config = {
@@ -51,9 +49,9 @@ export const reactRouterConfig = ({
5149
appDirectory,
5250
routeDiscovery,
5351
future: {
54-
unstable_splitRouteModules: splitRouteModules,
55-
unstable_viteEnvironmentApi: viteEnvironmentApi,
5652
v8_middleware,
53+
v8_splitRouteModules,
54+
v8_viteEnvironmentApi,
5755
},
5856
};
5957

integration/middleware-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ test.describe("Middleware", () => {
369369
"react-router.config.ts": reactRouterConfig({
370370
ssr: false,
371371
v8_middleware: true,
372-
splitRouteModules: true,
372+
v8_splitRouteModules: true,
373373
}),
374374
"vite.config.ts": js`
375375
import { defineConfig } from "vite";
@@ -1061,7 +1061,7 @@ test.describe("Middleware", () => {
10611061
files: {
10621062
"react-router.config.ts": reactRouterConfig({
10631063
v8_middleware: true,
1064-
splitRouteModules: true,
1064+
v8_splitRouteModules: true,
10651065
}),
10661066
"vite.config.ts": js`
10671067
import { defineConfig } from "vite";

integration/split-route-modules-test.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,17 @@ async function unblockClientLoader(page: Page) {
250250

251251
test.describe("Split route modules", async () => {
252252
test.describe("enabled", () => {
253-
let splitRouteModules = true;
253+
let v8_splitRouteModules = true;
254254
let port: number;
255255
let cwd: string;
256256
let stop: Awaited<ReturnType<typeof reactRouterServe>>;
257257

258258
test.beforeAll(async () => {
259259
port = await getPort();
260260
cwd = await createProject({
261-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
261+
"react-router.config.ts": reactRouterConfig({
262+
v8_splitRouteModules,
263+
}),
262264
"vite.config.js": await viteConfig.basic({ port }),
263265
...files,
264266
});
@@ -355,15 +357,17 @@ test.describe("Split route modules", async () => {
355357
});
356358

357359
test.describe("disabled", () => {
358-
let splitRouteModules = false;
360+
let v8_splitRouteModules = false;
359361
let port: number;
360362
let cwd: string;
361363
let stop: Awaited<ReturnType<typeof reactRouterServe>>;
362364

363365
test.beforeAll(async () => {
364366
port = await getPort();
365367
cwd = await createProject({
366-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
368+
"react-router.config.ts": reactRouterConfig({
369+
v8_splitRouteModules,
370+
}),
367371
"vite.config.js": await viteConfig.basic({ port }),
368372
...files,
369373
});
@@ -444,15 +448,17 @@ test.describe("Split route modules", async () => {
444448
});
445449

446450
test.describe("enforce", () => {
447-
let splitRouteModules = "enforce" as const;
451+
let v8_splitRouteModules = "enforce" as const;
448452
let port: number;
449453
let cwd: string;
450454

451455
test.describe("splittable routes", () => {
452456
test.beforeAll(async () => {
453457
port = await getPort();
454458
cwd = await createProject({
455-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
459+
"react-router.config.ts": reactRouterConfig({
460+
v8_splitRouteModules,
461+
}),
456462
"vite.config.js": await viteConfig.basic({ port }),
457463
// Make unsplittable routes valid so the build can pass
458464
"app/routes/unsplittable.tsx": "export default function(){}",
@@ -470,7 +476,9 @@ test.describe("Split route modules", async () => {
470476
test.beforeAll(async () => {
471477
port = await getPort();
472478
cwd = await createProject({
473-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
479+
"react-router.config.ts": reactRouterConfig({
480+
v8_splitRouteModules,
481+
}),
474482
"vite.config.js": await viteConfig.basic({ port }),
475483
"app/root.tsx": js`
476484
import { Outlet } from "react-router";
@@ -496,7 +504,9 @@ test.describe("Split route modules", async () => {
496504
test.beforeAll(async () => {
497505
port = await getPort();
498506
cwd = await createProject({
499-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
507+
"react-router.config.ts": reactRouterConfig({
508+
v8_splitRouteModules,
509+
}),
500510
"vite.config.js": await viteConfig.basic({ port }),
501511
"app/root.tsx": js`
502512
import { Outlet } from "react-router";
@@ -523,7 +533,9 @@ test.describe("Split route modules", async () => {
523533
test.beforeAll(async () => {
524534
port = await getPort();
525535
cwd = await createProject({
526-
"react-router.config.ts": reactRouterConfig({ splitRouteModules }),
536+
"react-router.config.ts": reactRouterConfig({
537+
v8_splitRouteModules,
538+
}),
527539
"vite.config.js": await viteConfig.basic({ port }),
528540
...files,
529541
// Ensure we're only testing the mixed route

integration/vite-build-test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ let stop: () => void;
2020
const js = String.raw;
2121

2222
test.describe("Build", () => {
23-
[false, true].forEach((viteEnvironmentApi) => {
23+
[false, true].forEach((v8_viteEnvironmentApi) => {
2424
viteMajorTemplates.forEach(({ templateName, templateDisplayName }) => {
2525
// Vite 5 doesn't support the Environment API
26-
if (templateName === "vite-5-template" && viteEnvironmentApi) {
26+
if (templateName === "vite-5-template" && v8_viteEnvironmentApi) {
2727
return;
2828
}
2929

3030
test.describe(`${templateDisplayName}${
31-
viteEnvironmentApi ? " with Vite Environment API" : ""
31+
v8_viteEnvironmentApi ? " with Vite Environment API" : ""
3232
}`, () => {
3333
test.beforeAll(async () => {
3434
port = await getPort();
@@ -38,7 +38,7 @@ test.describe("Build", () => {
3838
ENV_VAR_FROM_DOTENV_FILE=true
3939
`,
4040
"react-router.config.ts": reactRouterConfig({
41-
viteEnvironmentApi,
41+
v8_viteEnvironmentApi,
4242
}),
4343
"vite.config.ts": js`
4444
import { defineConfig } from "vite";

0 commit comments

Comments
 (0)