@react-router/dev 7.13.2-pre.0 → 7.14.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -4
- package/dist/cli/index.js +75 -38
- package/dist/config/default-rsc-entries/entry.client.tsx +1 -3
- package/dist/config/default-rsc-entries/entry.rsc.tsx +3 -0
- package/dist/config/default-rsc-entries/entry.ssr.tsx +0 -1
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +2 -2
- package/dist/vite.js +469 -264
- package/package.json +9 -9
- package/rsc-types.d.ts +17 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,86 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
-
## 7.
|
|
3
|
+
## 7.14.0-pre.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add support for Vite 8 ([#14876](https://github.com/remix-run/react-router/pull/14876))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- support for prerendering multiple server bundles with v8_viteEnvironmentApi ([#14921](https://github.com/remix-run/react-router/pull/14921))
|
|
12
|
+
- rsc framework mode prerender / spa mode support ([#14907](https://github.com/remix-run/react-router/pull/14907))
|
|
13
|
+
- UNSTABLE RSC FRAMEWORK MODE BREAKING CHANGE - Existing route module exports remain unchanged from stable v7 non-RSC mode, but new exports are added for RSC mode. If you want to use RSC features, you will need to update your route modules to export the new annotations. ([#14901](https://github.com/remix-run/react-router/pull/14901))
|
|
14
|
+
|
|
15
|
+
If you are using RSC framework mode currently, you will need to update your route modules to the new conventions. The following route module components have their own mutually exclusive server component counterparts:
|
|
16
|
+
|
|
17
|
+
| Server Component Export | Client Component |
|
|
18
|
+
| ----------------------- | ----------------- |
|
|
19
|
+
| `ServerComponent` | `default` |
|
|
20
|
+
| `ServerErrorBoundary` | `ErrorBoundary` |
|
|
21
|
+
| `ServerLayout` | `Layout` |
|
|
22
|
+
| `ServerHydrateFallback` | `HydrateFallback` |
|
|
23
|
+
|
|
24
|
+
If you were previously exporting a `ServerComponent`, your `ErrorBoundary`, `Layout`, and `HydrateFallback` were also server components. If you want to keep those as server components, you can rename them and prefix them with `Server`. If you were previously importing the implementations of those components from a client module, you can simply inline them.
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
|
|
28
|
+
Before
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { ErrorBoundary as ClientErrorBoundary } from "./client";
|
|
32
|
+
|
|
33
|
+
export function ServerComponent() {
|
|
34
|
+
// ...
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function ErrorBoundary() {
|
|
38
|
+
return <ClientErrorBoundary />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function Layout() {
|
|
42
|
+
// ...
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function HydrateFallback() {
|
|
46
|
+
// ...
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
After
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
export function ServerComponent() {
|
|
54
|
+
// ...
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function ErrorBoundary() {
|
|
58
|
+
// previous implementation of ClientErrorBoundary, this is now a client component
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function ServerLayout() {
|
|
62
|
+
// rename previous Layout export to ServerLayout to make it a server component
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function ServerHydrateFallback() {
|
|
66
|
+
// rename previous HydrateFallback export to ServerHydrateFallback to make it a server component
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- update the reveal command to support rsc for `entry.client`, `entry.rsc`, `entry.ssr` ([#14904](https://github.com/remix-run/react-router/pull/14904))
|
|
71
|
+
- Updated dependencies:
|
|
72
|
+
- `react-router@7.14.0-pre.0`
|
|
73
|
+
- `@react-router/node@7.14.0-pre.0`
|
|
74
|
+
- `@react-router/serve@7.14.0-pre.0`
|
|
75
|
+
|
|
76
|
+
## 7.13.2
|
|
4
77
|
|
|
5
78
|
### Patch Changes
|
|
6
79
|
|
|
7
80
|
- Fix `react-router dev` crash when Unix socket files exist in the project root ([#14854](https://github.com/remix-run/react-router/pull/14854))
|
|
81
|
+
|
|
8
82
|
- Escape redirect locations in prerendered redirect HTML ([#14880](https://github.com/remix-run/react-router/pull/14880))
|
|
83
|
+
|
|
9
84
|
- Add `future.unstable_passThroughRequests` flag ([#14775](https://github.com/remix-run/react-router/pull/14775))
|
|
10
85
|
|
|
11
86
|
By default, React Router normalizes the `request.url` passed to your `loader`, `action`, and `middleware` functions by removing React Router's internal implementation details (`.data` suffixes, `index` + `_routes` query params).
|
|
@@ -45,9 +120,9 @@
|
|
|
45
120
|
If you don't have the flag enabled, then `unstable_url` will match `request.url`.
|
|
46
121
|
|
|
47
122
|
- Updated dependencies:
|
|
48
|
-
- `react-router@7.13.2
|
|
49
|
-
- `@react-router/node@7.13.2
|
|
50
|
-
- `@react-router/serve@7.13.2
|
|
123
|
+
- `react-router@7.13.2`
|
|
124
|
+
- `@react-router/node@7.13.2`
|
|
125
|
+
- `@react-router/serve@7.13.2`
|
|
51
126
|
|
|
52
127
|
## 7.13.1
|
|
53
128
|
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v7.
|
|
3
|
+
* @react-router/dev v7.14.0-pre.0
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -511,7 +511,7 @@ async function resolveConfig({
|
|
|
511
511
|
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
512
512
|
v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
|
|
513
513
|
v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
|
|
514
|
-
v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
|
|
514
|
+
v8_viteEnvironmentApi: (userAndPresetConfigs.future?.v8_viteEnvironmentApi || userAndPresetConfigs.future?.unstable_previewServerPrerendering) ?? false
|
|
515
515
|
};
|
|
516
516
|
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
517
517
|
let reactRouterConfig = deepFreeze({
|
|
@@ -1183,7 +1183,7 @@ function getRouteAnnotations({
|
|
|
1183
1183
|
module: Module
|
|
1184
1184
|
}>
|
|
1185
1185
|
` + "\n\n" + generate(matchesType).code + "\n\n" + import_dedent.default`
|
|
1186
|
-
type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }
|
|
1186
|
+
type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }>;
|
|
1187
1187
|
|
|
1188
1188
|
export namespace Route {
|
|
1189
1189
|
// links
|
|
@@ -1220,11 +1220,20 @@ function getRouteAnnotations({
|
|
|
1220
1220
|
// HydrateFallback
|
|
1221
1221
|
export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
|
|
1222
1222
|
|
|
1223
|
+
// ServerHydrateFallback
|
|
1224
|
+
export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"];
|
|
1225
|
+
|
|
1223
1226
|
// Component
|
|
1224
1227
|
export type ComponentProps = Annotations["ComponentProps"];
|
|
1225
1228
|
|
|
1229
|
+
// ServerComponent
|
|
1230
|
+
export type ServerComponentProps = Annotations["ServerComponentProps"];
|
|
1231
|
+
|
|
1226
1232
|
// ErrorBoundary
|
|
1227
1233
|
export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
|
|
1234
|
+
|
|
1235
|
+
// ServerErrorBoundary
|
|
1236
|
+
export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"];
|
|
1228
1237
|
}
|
|
1229
1238
|
`;
|
|
1230
1239
|
return { filename: filename2, content };
|
|
@@ -1370,7 +1379,8 @@ async function hasReactRouterRscPlugin({
|
|
|
1370
1379
|
root,
|
|
1371
1380
|
viteBuildOptions: { config, logLevel, mode }
|
|
1372
1381
|
}) {
|
|
1373
|
-
|
|
1382
|
+
await preloadVite();
|
|
1383
|
+
const vite2 = getVite();
|
|
1374
1384
|
const viteConfig = await vite2.resolveConfig(
|
|
1375
1385
|
{
|
|
1376
1386
|
configFile: config,
|
|
@@ -1392,6 +1402,7 @@ async function hasReactRouterRscPlugin({
|
|
|
1392
1402
|
var init_has_rsc_plugin = __esm({
|
|
1393
1403
|
"vite/has-rsc-plugin.ts"() {
|
|
1394
1404
|
"use strict";
|
|
1405
|
+
init_vite();
|
|
1395
1406
|
}
|
|
1396
1407
|
});
|
|
1397
1408
|
|
|
@@ -2306,12 +2317,16 @@ async function dev2(root, options = {}) {
|
|
|
2306
2317
|
var clientEntries = ["entry.client.tsx", "entry.client.js", "entry.client.jsx"];
|
|
2307
2318
|
var serverEntries = ["entry.server.tsx", "entry.server.js", "entry.server.jsx"];
|
|
2308
2319
|
var entries = ["entry.client", "entry.server"];
|
|
2320
|
+
var rscEntries = ["entry.client", "entry.rsc", "entry.ssr"];
|
|
2309
2321
|
var conjunctionListFormat = new Intl.ListFormat("en", {
|
|
2310
2322
|
style: "long",
|
|
2311
2323
|
type: "conjunction"
|
|
2312
2324
|
});
|
|
2313
2325
|
async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
2314
2326
|
rootDirectory = resolveRootDirectory(rootDirectory, flags);
|
|
2327
|
+
let configDir = "defaults";
|
|
2328
|
+
let entriesToUse = entries;
|
|
2329
|
+
let isRsc = false;
|
|
2315
2330
|
if (await hasReactRouterRscPlugin({
|
|
2316
2331
|
root: rootDirectory,
|
|
2317
2332
|
viteBuildOptions: {
|
|
@@ -2319,12 +2334,15 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2319
2334
|
mode: flags.mode
|
|
2320
2335
|
}
|
|
2321
2336
|
})) {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
)
|
|
2326
|
-
|
|
2327
|
-
|
|
2337
|
+
if (!entry) {
|
|
2338
|
+
await generateEntry("entry.client", rootDirectory, flags);
|
|
2339
|
+
await generateEntry("entry.rsc", rootDirectory, flags);
|
|
2340
|
+
await generateEntry("entry.ssr", rootDirectory, flags);
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
configDir = "default-rsc-entries";
|
|
2344
|
+
entriesToUse = rscEntries;
|
|
2345
|
+
isRsc = true;
|
|
2328
2346
|
}
|
|
2329
2347
|
if (!entry) {
|
|
2330
2348
|
await generateEntry("entry.client", rootDirectory, flags);
|
|
@@ -2340,46 +2358,65 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2340
2358
|
return;
|
|
2341
2359
|
}
|
|
2342
2360
|
let appDirectory = configResult.value.appDirectory;
|
|
2343
|
-
if (!
|
|
2344
|
-
let entriesArray = Array.from(
|
|
2361
|
+
if (!entriesToUse.includes(entry)) {
|
|
2362
|
+
let entriesArray = Array.from(entriesToUse);
|
|
2345
2363
|
let list = conjunctionListFormat.format(entriesArray);
|
|
2346
2364
|
console.error(
|
|
2347
2365
|
import_picocolors8.default.red(`Invalid entry file. Valid entry files are ${list}`)
|
|
2348
2366
|
);
|
|
2349
2367
|
return;
|
|
2350
2368
|
}
|
|
2351
|
-
let { readPackageJSON } = await import("pkg-types");
|
|
2352
|
-
let pkgJson = await readPackageJSON(rootDirectory);
|
|
2353
|
-
let deps = pkgJson.dependencies ?? {};
|
|
2354
|
-
if (!deps["@react-router/node"]) {
|
|
2355
|
-
console.error(import_picocolors8.default.red(`No default server entry detected.`));
|
|
2356
|
-
return;
|
|
2357
|
-
}
|
|
2358
2369
|
let defaultsDirectory = path9.resolve(
|
|
2359
2370
|
path9.dirname(require.resolve("@react-router/dev/package.json")),
|
|
2360
2371
|
"dist",
|
|
2361
2372
|
"config",
|
|
2362
|
-
|
|
2363
|
-
);
|
|
2364
|
-
let defaultEntryClient = path9.resolve(defaultsDirectory, "entry.client.tsx");
|
|
2365
|
-
let defaultEntryServer = path9.resolve(
|
|
2366
|
-
defaultsDirectory,
|
|
2367
|
-
`entry.server.node.tsx`
|
|
2373
|
+
configDir
|
|
2368
2374
|
);
|
|
2369
|
-
let
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
});
|
|
2380
|
-
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2375
|
+
let outputFile;
|
|
2376
|
+
if (isRsc) {
|
|
2377
|
+
let defaultEntry = path9.resolve(defaultsDirectory, `${entry}.tsx`);
|
|
2378
|
+
outputFile = path9.resolve(appDirectory, `${entry}.tsx`);
|
|
2379
|
+
if ((0, import_node_fs4.existsSync)(outputFile)) {
|
|
2380
|
+
let relative7 = path9.relative(rootDirectory, outputFile);
|
|
2381
|
+
console.error(import_picocolors8.default.red(`Entry file ${relative7} already exists.`));
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
await (0, import_promises4.copyFile)(defaultEntry, outputFile);
|
|
2381
2385
|
} else {
|
|
2382
|
-
|
|
2386
|
+
let { readPackageJSON } = await import("pkg-types");
|
|
2387
|
+
let pkgJson = await readPackageJSON(rootDirectory);
|
|
2388
|
+
let deps = pkgJson.dependencies ?? {};
|
|
2389
|
+
if (!deps["@react-router/node"]) {
|
|
2390
|
+
console.error(import_picocolors8.default.red(`No default server entry detected.`));
|
|
2391
|
+
return;
|
|
2392
|
+
}
|
|
2393
|
+
let defaultEntryClient = path9.resolve(
|
|
2394
|
+
defaultsDirectory,
|
|
2395
|
+
"entry.client.tsx"
|
|
2396
|
+
);
|
|
2397
|
+
let defaultEntryServer = path9.resolve(
|
|
2398
|
+
defaultsDirectory,
|
|
2399
|
+
`entry.server.node.tsx`
|
|
2400
|
+
);
|
|
2401
|
+
let isServerEntry = entry === "entry.server";
|
|
2402
|
+
let contents = isServerEntry ? await createServerEntry(rootDirectory, appDirectory, defaultEntryServer) : await createClientEntry(
|
|
2403
|
+
rootDirectory,
|
|
2404
|
+
appDirectory,
|
|
2405
|
+
defaultEntryClient
|
|
2406
|
+
);
|
|
2407
|
+
let useTypeScript = flags.typescript ?? true;
|
|
2408
|
+
let outputExtension = useTypeScript ? "tsx" : "jsx";
|
|
2409
|
+
let outputEntry = `${entry}.${outputExtension}`;
|
|
2410
|
+
outputFile = path9.resolve(appDirectory, outputEntry);
|
|
2411
|
+
if (!useTypeScript) {
|
|
2412
|
+
let javascript = await transpile(contents, {
|
|
2413
|
+
cwd: rootDirectory,
|
|
2414
|
+
filename: isServerEntry ? defaultEntryServer : defaultEntryClient
|
|
2415
|
+
});
|
|
2416
|
+
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2417
|
+
} else {
|
|
2418
|
+
await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
|
|
2419
|
+
}
|
|
2383
2420
|
}
|
|
2384
2421
|
console.log(
|
|
2385
2422
|
import_picocolors8.default.blue(
|
|
@@ -24,7 +24,6 @@ setServerCallback(
|
|
|
24
24
|
);
|
|
25
25
|
|
|
26
26
|
createFromReadableStream<RSCPayload>(getRSCStream()).then((payload) => {
|
|
27
|
-
// @ts-expect-error - on 18 types, requires 19.
|
|
28
27
|
startTransition(async () => {
|
|
29
28
|
const formState =
|
|
30
29
|
payload.type === "render" ? await payload.formState : undefined;
|
|
@@ -33,12 +32,11 @@ createFromReadableStream<RSCPayload>(getRSCStream()).then((payload) => {
|
|
|
33
32
|
document,
|
|
34
33
|
<StrictMode>
|
|
35
34
|
<RSCHydratedRouter
|
|
36
|
-
payload={payload}
|
|
37
35
|
createFromReadableStream={createFromReadableStream}
|
|
36
|
+
payload={payload}
|
|
38
37
|
/>
|
|
39
38
|
</StrictMode>,
|
|
40
39
|
{
|
|
41
|
-
// @ts-expect-error - no types for this yet
|
|
42
40
|
formState,
|
|
43
41
|
},
|
|
44
42
|
);
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
// Import the routes generated by routes.ts
|
|
15
15
|
import routes from "virtual:react-router/unstable_rsc/routes";
|
|
16
|
+
import routeDiscovery from "virtual:react-router/unstable_rsc/route-discovery";
|
|
16
17
|
import basename from "virtual:react-router/unstable_rsc/basename";
|
|
17
18
|
import unstable_reactRouterServeConfig from "virtual:react-router/unstable_rsc/react-router-serve-config";
|
|
18
19
|
|
|
@@ -35,6 +36,8 @@ export function fetchServer(
|
|
|
35
36
|
requestContext,
|
|
36
37
|
// The app routes.
|
|
37
38
|
routes,
|
|
39
|
+
// The route discovery configuration.
|
|
40
|
+
routeDiscovery,
|
|
38
41
|
// Encode the match with the React Server implementation.
|
|
39
42
|
generateResponse(match, options) {
|
|
40
43
|
return new Response(renderToReadableStream(match.payload, options), {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
|
|
2
|
-
// @ts-expect-error - no types for this, can import from root once on latest 19
|
|
3
2
|
import { renderToReadableStream } from "react-dom/server.edge";
|
|
4
3
|
import {
|
|
5
4
|
unstable_routeRSCServerRequest as routeRSCServerRequest,
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
package/dist/vite/cloudflare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.
|
|
2
|
+
* @react-router/dev v7.14.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -537,7 +537,7 @@ async function resolveConfig({
|
|
|
537
537
|
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
538
538
|
v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
|
|
539
539
|
v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
|
|
540
|
-
v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
|
|
540
|
+
v8_viteEnvironmentApi: (userAndPresetConfigs.future?.v8_viteEnvironmentApi || userAndPresetConfigs.future?.unstable_previewServerPrerendering) ?? false
|
|
541
541
|
};
|
|
542
542
|
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
543
543
|
let reactRouterConfig = deepFreeze({
|