@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 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-19e1f0f2c-20260321
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
- const vite2 = await import("vite");
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
- console.error(
2323
- import_picocolors8.default.red(
2324
- `The reveal command is currently not supported in RSC Framework Mode.`
2325
- )
2326
- );
2327
- process.exit(1);
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 (!entries.includes(entry)) {
2344
- let entriesArray = Array.from(entries);
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
- "defaults"
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 isServerEntry = entry === "entry.server";
2370
- let contents = isServerEntry ? await createServerEntry(rootDirectory, appDirectory, defaultEntryServer) : await createClientEntry(rootDirectory, appDirectory, defaultEntryClient);
2371
- let useTypeScript = flags.typescript ?? true;
2372
- let outputExtension = useTypeScript ? "tsx" : "jsx";
2373
- let outputEntry = `${entry}.${outputExtension}`;
2374
- let outputFile = path9.resolve(appDirectory, outputEntry);
2375
- if (!useTypeScript) {
2376
- let javascript = await transpile(contents, {
2377
- cwd: rootDirectory,
2378
- filename: isServerEntry ? defaultEntryServer : defaultEntryClient
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
- await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
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
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-nightly-19e1f0f2c-20260321
2
+ * @react-router/dev v0.0.0-nightly-111f3a3f2-20260324
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/routes.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-nightly-19e1f0f2c-20260321
2
+ * @react-router/dev v0.0.0-nightly-111f3a3f2-20260324
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-nightly-19e1f0f2c-20260321
2
+ * @react-router/dev v0.0.0-nightly-111f3a3f2-20260324
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-nightly-19e1f0f2c-20260321
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
- esbuild: {
3530
- jsx: "automatic",
3531
- jsxDev: viteCommand !== "build"
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
- esbuildOptions: {
6069
- jsx: "automatic"
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
- esbuild: {
6093
- jsx: "automatic",
6094
- jsxDev: viteCommand !== "build"
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-19e1f0f2c-20260321",
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-19e1f0f2c-20260321"
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.7",
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
- "@react-router/serve": "0.0.0-nightly-19e1f0f2c-20260321",
120
- "react-router": "^0.0.0-nightly-19e1f0f2c-20260321"
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.7",
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-19e1f0f2c-20260321",
129
- "react-router": "^0.0.0-nightly-19e1f0f2c-20260321"
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": {