@react-router/dev 0.0.0-nightly-19e1f0f2c-20260321 → 0.0.0-nightly-111f3a3f2-20260324
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 +51 -0
- package/dist/cli/index.js +64 -36
- package/dist/config/default-rsc-entries/entry.client.tsx +0 -2
- 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 +1 -1
- package/dist/vite.js +43 -12
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix `react-router dev` crash when Unix socket files exist in the project root ([#14854](https://github.com/remix-run/react-router/pull/14854))
|
|
8
|
+
|
|
9
|
+
- Escape redirect locations in prerendered redirect HTML ([#14880](https://github.com/remix-run/react-router/pull/14880))
|
|
10
|
+
|
|
11
|
+
- Add `future.unstable_passThroughRequests` flag ([#14775](https://github.com/remix-run/react-router/pull/14775))
|
|
12
|
+
|
|
13
|
+
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).
|
|
14
|
+
|
|
15
|
+
Enabling this flag removes that normalization and passes the raw HTTP `request` instance to your handlers. This provides a few benefits:
|
|
16
|
+
- Reduces server-side overhead by eliminating multiple `new Request()` calls on the critical path
|
|
17
|
+
- Allows you to distinguish document from data requests in your handlers base don the presence of a `.data` suffix (useful for observability purposes)
|
|
18
|
+
|
|
19
|
+
If you were previously relying on the normalization of `request.url`, you can switch to use the new sibling `unstable_url` parameter which contains a `URL` instance representing the normalized location:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// ❌ Before: you could assume there was no `.data` suffix in `request.url`
|
|
23
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
24
|
+
let url = new URL(request.url);
|
|
25
|
+
if (url.pathname === "/path") {
|
|
26
|
+
// This check will fail with the flag enabled because the `.data` suffix will
|
|
27
|
+
// exist on data requests
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ✅ After: use `unstable_url` for normalized routing logic and `request.url`
|
|
32
|
+
// for raw routing logic
|
|
33
|
+
export async function loader({ request, unstable_url }: Route.LoaderArgs) {
|
|
34
|
+
if (unstable_url.pathname === "/path") {
|
|
35
|
+
// This will always have the `.data` suffix stripped
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// And now you can distinguish between document versus data requests
|
|
39
|
+
let isDataRequest = new URL(request.url).pathname.endsWith(".data");
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Add a new `unstable_url: URL` parameter to route handler methods (`loader`, `action`, `middleware`, etc.) representing the normalized URL the application is navigating to or fetching, with React Router implementation details removed (`.data`suffix, `index`/`_routes` query params) ([#14775](https://github.com/remix-run/react-router/pull/14775))
|
|
44
|
+
|
|
45
|
+
This is being added alongside the new `future.unstable_passthroughRequests` future flag so that users still have a way to access the normalized URL when that flag is enabled and non-normalized `request`'s are being passed to your handlers. When adopting this flag, you will only need to start leveraging this new parameter if you are relying on the normalization of `request.url` in your application code.
|
|
46
|
+
|
|
47
|
+
If you don't have the flag enabled, then `unstable_url` will match `request.url`.
|
|
48
|
+
|
|
49
|
+
- Updated dependencies:
|
|
50
|
+
- `react-router@7.13.2`
|
|
51
|
+
- `@react-router/node@7.13.2`
|
|
52
|
+
- `@react-router/serve@7.13.2`
|
|
53
|
+
|
|
3
54
|
## 7.13.1
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v0.0.0-nightly-
|
|
3
|
+
* @react-router/dev v0.0.0-nightly-111f3a3f2-20260324
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -1370,7 +1370,8 @@ async function hasReactRouterRscPlugin({
|
|
|
1370
1370
|
root,
|
|
1371
1371
|
viteBuildOptions: { config, logLevel, mode }
|
|
1372
1372
|
}) {
|
|
1373
|
-
|
|
1373
|
+
await preloadVite();
|
|
1374
|
+
const vite2 = getVite();
|
|
1374
1375
|
const viteConfig = await vite2.resolveConfig(
|
|
1375
1376
|
{
|
|
1376
1377
|
configFile: config,
|
|
@@ -1392,6 +1393,7 @@ async function hasReactRouterRscPlugin({
|
|
|
1392
1393
|
var init_has_rsc_plugin = __esm({
|
|
1393
1394
|
"vite/has-rsc-plugin.ts"() {
|
|
1394
1395
|
"use strict";
|
|
1396
|
+
init_vite();
|
|
1395
1397
|
}
|
|
1396
1398
|
});
|
|
1397
1399
|
|
|
@@ -2306,12 +2308,16 @@ async function dev2(root, options = {}) {
|
|
|
2306
2308
|
var clientEntries = ["entry.client.tsx", "entry.client.js", "entry.client.jsx"];
|
|
2307
2309
|
var serverEntries = ["entry.server.tsx", "entry.server.js", "entry.server.jsx"];
|
|
2308
2310
|
var entries = ["entry.client", "entry.server"];
|
|
2311
|
+
var rscEntries = ["entry.client", "entry.rsc", "entry.ssr"];
|
|
2309
2312
|
var conjunctionListFormat = new Intl.ListFormat("en", {
|
|
2310
2313
|
style: "long",
|
|
2311
2314
|
type: "conjunction"
|
|
2312
2315
|
});
|
|
2313
2316
|
async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
2314
2317
|
rootDirectory = resolveRootDirectory(rootDirectory, flags);
|
|
2318
|
+
let configDir = "defaults";
|
|
2319
|
+
let entriesToUse = entries;
|
|
2320
|
+
let isRsc = false;
|
|
2315
2321
|
if (await hasReactRouterRscPlugin({
|
|
2316
2322
|
root: rootDirectory,
|
|
2317
2323
|
viteBuildOptions: {
|
|
@@ -2319,12 +2325,15 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2319
2325
|
mode: flags.mode
|
|
2320
2326
|
}
|
|
2321
2327
|
})) {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
)
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
+
if (!entry) {
|
|
2329
|
+
await generateEntry("entry.client", rootDirectory, flags);
|
|
2330
|
+
await generateEntry("entry.rsc", rootDirectory, flags);
|
|
2331
|
+
await generateEntry("entry.ssr", rootDirectory, flags);
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
configDir = "default-rsc-entries";
|
|
2335
|
+
entriesToUse = rscEntries;
|
|
2336
|
+
isRsc = true;
|
|
2328
2337
|
}
|
|
2329
2338
|
if (!entry) {
|
|
2330
2339
|
await generateEntry("entry.client", rootDirectory, flags);
|
|
@@ -2340,46 +2349,65 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2340
2349
|
return;
|
|
2341
2350
|
}
|
|
2342
2351
|
let appDirectory = configResult.value.appDirectory;
|
|
2343
|
-
if (!
|
|
2344
|
-
let entriesArray = Array.from(
|
|
2352
|
+
if (!entriesToUse.includes(entry)) {
|
|
2353
|
+
let entriesArray = Array.from(entriesToUse);
|
|
2345
2354
|
let list = conjunctionListFormat.format(entriesArray);
|
|
2346
2355
|
console.error(
|
|
2347
2356
|
import_picocolors8.default.red(`Invalid entry file. Valid entry files are ${list}`)
|
|
2348
2357
|
);
|
|
2349
2358
|
return;
|
|
2350
2359
|
}
|
|
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
2360
|
let defaultsDirectory = path9.resolve(
|
|
2359
2361
|
path9.dirname(require.resolve("@react-router/dev/package.json")),
|
|
2360
2362
|
"dist",
|
|
2361
2363
|
"config",
|
|
2362
|
-
|
|
2363
|
-
);
|
|
2364
|
-
let defaultEntryClient = path9.resolve(defaultsDirectory, "entry.client.tsx");
|
|
2365
|
-
let defaultEntryServer = path9.resolve(
|
|
2366
|
-
defaultsDirectory,
|
|
2367
|
-
`entry.server.node.tsx`
|
|
2364
|
+
configDir
|
|
2368
2365
|
);
|
|
2369
|
-
let
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
});
|
|
2380
|
-
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2366
|
+
let outputFile;
|
|
2367
|
+
if (isRsc) {
|
|
2368
|
+
let defaultEntry = path9.resolve(defaultsDirectory, `${entry}.tsx`);
|
|
2369
|
+
outputFile = path9.resolve(appDirectory, `${entry}.tsx`);
|
|
2370
|
+
if ((0, import_node_fs4.existsSync)(outputFile)) {
|
|
2371
|
+
let relative7 = path9.relative(rootDirectory, outputFile);
|
|
2372
|
+
console.error(import_picocolors8.default.red(`Entry file ${relative7} already exists.`));
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
await (0, import_promises4.copyFile)(defaultEntry, outputFile);
|
|
2381
2376
|
} else {
|
|
2382
|
-
|
|
2377
|
+
let { readPackageJSON } = await import("pkg-types");
|
|
2378
|
+
let pkgJson = await readPackageJSON(rootDirectory);
|
|
2379
|
+
let deps = pkgJson.dependencies ?? {};
|
|
2380
|
+
if (!deps["@react-router/node"]) {
|
|
2381
|
+
console.error(import_picocolors8.default.red(`No default server entry detected.`));
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
let defaultEntryClient = path9.resolve(
|
|
2385
|
+
defaultsDirectory,
|
|
2386
|
+
"entry.client.tsx"
|
|
2387
|
+
);
|
|
2388
|
+
let defaultEntryServer = path9.resolve(
|
|
2389
|
+
defaultsDirectory,
|
|
2390
|
+
`entry.server.node.tsx`
|
|
2391
|
+
);
|
|
2392
|
+
let isServerEntry = entry === "entry.server";
|
|
2393
|
+
let contents = isServerEntry ? await createServerEntry(rootDirectory, appDirectory, defaultEntryServer) : await createClientEntry(
|
|
2394
|
+
rootDirectory,
|
|
2395
|
+
appDirectory,
|
|
2396
|
+
defaultEntryClient
|
|
2397
|
+
);
|
|
2398
|
+
let useTypeScript = flags.typescript ?? true;
|
|
2399
|
+
let outputExtension = useTypeScript ? "tsx" : "jsx";
|
|
2400
|
+
let outputEntry = `${entry}.${outputExtension}`;
|
|
2401
|
+
outputFile = path9.resolve(appDirectory, outputEntry);
|
|
2402
|
+
if (!useTypeScript) {
|
|
2403
|
+
let javascript = await transpile(contents, {
|
|
2404
|
+
cwd: rootDirectory,
|
|
2405
|
+
filename: isServerEntry ? defaultEntryServer : defaultEntryClient
|
|
2406
|
+
});
|
|
2407
|
+
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2408
|
+
} else {
|
|
2409
|
+
await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
|
|
2410
|
+
}
|
|
2383
2411
|
}
|
|
2384
2412
|
console.log(
|
|
2385
2413
|
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;
|
|
@@ -38,7 +37,6 @@ createFromReadableStream<RSCPayload>(getRSCStream()).then((payload) => {
|
|
|
38
37
|
/>
|
|
39
38
|
</StrictMode>,
|
|
40
39
|
{
|
|
41
|
-
// @ts-expect-error - no types for this yet
|
|
42
40
|
formState,
|
|
43
41
|
},
|
|
44
42
|
);
|
|
@@ -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
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-nightly-
|
|
2
|
+
* @react-router/dev v0.0.0-nightly-111f3a3f2-20260324
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -111,6 +111,14 @@ function getVite() {
|
|
|
111
111
|
invariant(vite, "getVite() called before preloadVite()");
|
|
112
112
|
return vite;
|
|
113
113
|
}
|
|
114
|
+
function defineCompilerOptions(options) {
|
|
115
|
+
let vite2 = getVite();
|
|
116
|
+
return parseInt(vite2.version.split(".")[0], 10) >= 8 ? { oxc: options.oxc } : { esbuild: options.esbuild };
|
|
117
|
+
}
|
|
118
|
+
function defineOptimizeDepsCompilerOptions(options) {
|
|
119
|
+
let vite2 = getVite();
|
|
120
|
+
return parseInt(vite2.version.split(".")[0], 10) >= 8 ? { rolldownOptions: options.rolldown } : { esbuildOptions: options.esbuild };
|
|
121
|
+
}
|
|
114
122
|
|
|
115
123
|
// vite/ssr-externals.ts
|
|
116
124
|
var ssrExternals = isReactRouterRepo() ? [
|
|
@@ -3526,10 +3534,18 @@ var reactRouterVitePlugin = () => {
|
|
|
3526
3534
|
}) ? ["react-router-dom"] : []
|
|
3527
3535
|
]
|
|
3528
3536
|
},
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3537
|
+
...defineCompilerOptions({
|
|
3538
|
+
oxc: {
|
|
3539
|
+
jsx: {
|
|
3540
|
+
runtime: "automatic",
|
|
3541
|
+
development: viteCommand !== "build"
|
|
3542
|
+
}
|
|
3543
|
+
},
|
|
3544
|
+
esbuild: {
|
|
3545
|
+
jsx: "automatic",
|
|
3546
|
+
jsxDev: viteCommand !== "build"
|
|
3547
|
+
}
|
|
3548
|
+
}),
|
|
3533
3549
|
resolve: {
|
|
3534
3550
|
dedupe: [
|
|
3535
3551
|
// https://react.dev/warnings/invalid-hook-call-warning#duplicate-react
|
|
@@ -6065,9 +6081,16 @@ ${errors.map((x) => ` - ${x}`).join("\n")}
|
|
|
6065
6081
|
entryClientFilePath: entries.client,
|
|
6066
6082
|
reactRouterConfig: config
|
|
6067
6083
|
}),
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6084
|
+
...defineOptimizeDepsCompilerOptions({
|
|
6085
|
+
rolldown: {
|
|
6086
|
+
transform: {
|
|
6087
|
+
jsx: "react-jsx"
|
|
6088
|
+
}
|
|
6089
|
+
},
|
|
6090
|
+
esbuild: {
|
|
6091
|
+
jsx: "automatic"
|
|
6092
|
+
}
|
|
6093
|
+
}),
|
|
6071
6094
|
include: [
|
|
6072
6095
|
// Pre-bundle React dependencies to avoid React duplicates,
|
|
6073
6096
|
// even if React dependencies are not direct dependencies.
|
|
@@ -6089,10 +6112,18 @@ ${errors.map((x) => ` - ${x}`).join("\n")}
|
|
|
6089
6112
|
"react-router > set-cookie-parser"
|
|
6090
6113
|
]
|
|
6091
6114
|
},
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6115
|
+
...defineCompilerOptions({
|
|
6116
|
+
oxc: {
|
|
6117
|
+
jsx: {
|
|
6118
|
+
runtime: "automatic",
|
|
6119
|
+
development: viteCommand !== "build"
|
|
6120
|
+
}
|
|
6121
|
+
},
|
|
6122
|
+
esbuild: {
|
|
6123
|
+
jsx: "automatic",
|
|
6124
|
+
jsxDev: viteCommand !== "build"
|
|
6125
|
+
}
|
|
6126
|
+
}),
|
|
6096
6127
|
environments: {
|
|
6097
6128
|
client: {
|
|
6098
6129
|
build: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "0.0.0-nightly-
|
|
3
|
+
"version": "0.0.0-nightly-111f3a3f2-20260324",
|
|
4
4
|
"description": "Dev tools and CLI for React Router",
|
|
5
5
|
"homepage": "https://reactrouter.com",
|
|
6
6
|
"bugs": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"tinyglobby": "^0.2.14",
|
|
93
93
|
"valibot": "^1.2.0",
|
|
94
94
|
"vite-node": "^3.2.2",
|
|
95
|
-
"@react-router/node": "0.0.0-nightly-
|
|
95
|
+
"@react-router/node": "0.0.0-nightly-111f3a3f2-20260324"
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@types/babel__core": "^7.20.5",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"@types/node": "^20.0.0",
|
|
107
107
|
"@types/npmcli__package-json": "^4.0.0",
|
|
108
108
|
"@types/semver": "^7.7.0",
|
|
109
|
-
"@vitejs/plugin-rsc": "~0.5.
|
|
109
|
+
"@vitejs/plugin-rsc": "~0.5.21",
|
|
110
110
|
"esbuild-register": "^3.6.0",
|
|
111
111
|
"execa": "5.1.1",
|
|
112
112
|
"express": "^4.19.2",
|
|
@@ -116,17 +116,17 @@
|
|
|
116
116
|
"vite": "^6.3.0",
|
|
117
117
|
"wireit": "0.14.9",
|
|
118
118
|
"wrangler": "^4.23.0",
|
|
119
|
-
"
|
|
120
|
-
"react-router": "
|
|
119
|
+
"react-router": "^0.0.0-nightly-111f3a3f2-20260324",
|
|
120
|
+
"@react-router/serve": "0.0.0-nightly-111f3a3f2-20260324"
|
|
121
121
|
},
|
|
122
122
|
"peerDependencies": {
|
|
123
|
-
"@vitejs/plugin-rsc": "~0.5.
|
|
123
|
+
"@vitejs/plugin-rsc": "~0.5.21",
|
|
124
124
|
"react-server-dom-webpack": "^19.2.3",
|
|
125
125
|
"typescript": "^5.1.0",
|
|
126
|
-
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
|
|
126
|
+
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
|
|
127
127
|
"wrangler": "^3.28.2 || ^4.0.0",
|
|
128
|
-
"@react-router/serve": "^0.0.0-nightly-
|
|
129
|
-
"react-router": "^0.0.0-nightly-
|
|
128
|
+
"@react-router/serve": "^0.0.0-nightly-111f3a3f2-20260324",
|
|
129
|
+
"react-router": "^0.0.0-nightly-111f3a3f2-20260324"
|
|
130
130
|
},
|
|
131
131
|
"peerDependenciesMeta": {
|
|
132
132
|
"@vitejs/plugin-rsc": {
|