Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ We manage release notes in this file instead of the paginated Github Releases Pa
<summary>Table of Contents</summary>

- [React Router Releases](#react-router-releases)
- [v8.3.0](#v830)
- [RSC Entry Updates](#rsc-entry-updates)
- [v8.2.0](#v820)
- [Web Streams Default Server Entry](#web-streams-default-server-entry)
- [v8.1.0](#v810)
Expand Down Expand Up @@ -109,6 +111,117 @@ We manage release notes in this file instead of the paginated Github Releases Pa

</details>

## v8.3.0

Date: 2026-07-22

### What's Changed

#### RSC Entry Updates

This release includes several updates for unstable RSC apps that use custom entry files. Apps using the default RSC Framework entries do not need any changes.

If you maintain custom RSC entries, review the generated unstable change notes for the new client version, subresource integrity, and CSP nonce wiring. Custom `entry.rsc.tsx` files should pass the generated client version to `unstable_matchRSCServerRequest`, and custom `entry.ssr.tsx` files may need to pass the generated import map integrity data and request nonce through React's HTML renderer.

### Minor Changes

- `@react-router/dev` - Restart `react-router dev` with `--conditions=development` when not already configured ([#15291](https://github.com/remix-run/react-router/pull/15291))

### Patch Changes

- `react-router` - Encode path params in `href`/`generatePath` per RFC 3986 path-segment rules instead of `encodeURIComponent` ([#15310](https://github.com/remix-run/react-router/pull/15310))
- Characters that are valid literally in a path segment (`$ & + , ; = : @` — RFC 3986 `pchar`) are no longer percent-encoded, so values like a semver build `1.0.0+1` interpolate unchanged instead of becoming `1.0.0%2B1`
- Structural/unsafe characters (`/ ? # %`, whitespace, non-ASCII) are still escaped exactly as before
- `react-router` - Use `crypto.randomUUID()` for `createMemorySessionStorage` session ids ([#15302](https://github.com/remix-run/react-router/pull/15302))
- `createMemorySessionStorage` is only intended for local development and testing - sessions are lost when the server restarts
- `react-router` - Fix `NavLink` not applying its `pending` state when `to` has a trailing slash ([#15300](https://github.com/remix-run/react-router/pull/15300))
- `@react-router/architect` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/cloudflare` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/dev` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/express` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/fs-routes` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/node` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- `@react-router/remix-routes-option-adapter` - Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))

### Unstable Changes

⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_

- `react-router` - Preserve RSC route component metadata so routes with a `clientLoader` can skip unnecessary server requests once their components have rendered while still fetching missing server-rendered elements ([#15323](https://github.com/remix-run/react-router/pull/15323))
- `react-router` - Harden RSC CSRF code paths ([#15311](https://github.com/remix-run/react-router/pull/15311))
- `react-router` - Fix server crash (`TypeError: Invalid state: Unable to enqueue`) when a request is aborted while the RSC HTML stream has a pending flush ([#15286](https://github.com/remix-run/react-router/pull/15286))
- Handle cancellation of the `injectRSCPayload` readable side, clear the pending flush, and cancel the underlying RSC payload stream
- `react-router` - Detect stale RSC clients during lazy route discovery and reload the destination document ([#15318](https://github.com/remix-run/react-router/pull/15318))

#### Migration

Apps using the default RSC Framework entry do not need to make any changes. Apps with a custom `entry.rsc.tsx` should import the generated client version and pass it to `unstable_matchRSCServerRequest`:

```tsx
import clientVersion from "virtual:react-router/unstable_rsc/client-version";

return unstable_matchRSCServerRequest({
// ...
clientVersion,
});
```

- `react-router` - Add CSP nonce support to RSC document rendering ([#15320](https://github.com/remix-run/react-router/pull/15320))
- Add `nonce` options to `unstable_routeRSCServerRequest` and `unstable_RSCStaticRouter`
- Forward the nonce to the HTML renderer and apply it to injected RSC payload scripts and nonce-aware framework components

To adopt nonce-based CSP, update your `entry.ssr.tsx` (run `react-router reveal entry.ssr` first in RSC Framework Mode) to generate a fresh nonce for each request. Pass it to `routeRSCServerRequest`, spread the `renderHTML` options into React's HTML renderer, pass `options.nonce` to `RSCStaticRouter`, and use the same nonce in the `Content-Security-Policy` response header:

```tsx
const nonce = crypto.randomUUID();
const response = await routeRSCServerRequest({
request,
serverResponse,
createFromReadableStream,
nonce,
async renderHTML(getPayload, options) {
const payload = getPayload();
return renderHTMLToReadableStream(
<RSCStaticRouter getPayload={getPayload} nonce={options.nonce} />,
{
...options,
bootstrapScriptContent,
formState: await payload.formState,
signal: request.signal,
},
);
},
});
response.headers.set(
"Content-Security-Policy",
`script-src 'self' 'nonce-${nonce}'`,
);
```

- `@react-router/dev` - Add `unstable_rsc/client-version` client build version virtual module ([#15318](https://github.com/remix-run/react-router/pull/15318))

- `@react-router/dev` - Support the `subResourceIntegrity` config option in RSC Framework Mode ([#15321](https://github.com/remix-run/react-router/pull/15321))

#### Migration guide

No changes are required when using the default RSC SSR entry. If you maintain a custom `app/entry.ssr.tsx`, import the new virtual module and pass its hashes to React's `importMap` render option:

```diff
+import subResourceIntegrity from "virtual:react-router/unstable_rsc/subresource-integrity";

return renderToReadableStream(<RSCStaticRouter getPayload={getPayload} />, {
...options,
bootstrapScriptContent,
formState,
+ importMap: subResourceIntegrity
+ ? { integrity: subResourceIntegrity }
+ : undefined,
signal: request.signal,
});
```

**Full Changelog**: [`v8.2.0...v8.3.0`](https://github.com/remix-run/react-router/compare/react-router@8.2.0...react-router@8.3.0)

## v8.2.0

Date: 2026-07-08
Expand Down
6 changes: 6 additions & 0 deletions packages/create-react-router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# `create-react-router`

## v8.3.0

### Patch Changes

- _No changes_

## v8.2.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/create-react-router/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "create-react-router",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Create a new React Router app",
"homepage": "https://reactrouter.com",
"bugs": {
Expand Down
9 changes: 9 additions & 0 deletions packages/react-router-architect/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# `@react-router/architect`

## v8.3.0

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- Updated dependencies:
- [`react-router@8.3.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.0)
- [`@react-router/node@8.3.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.3.0)

## v8.2.0

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-architect/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/architect",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Architect server request handler for React Router",
"bugs": {
"url": "https://github.com/remix-run/react-router/issues"
Expand Down Expand Up @@ -61,7 +61,7 @@
"peerDependencies": {
"@react-router/node": "workspace:^",
"react-router": "workspace:^",
"typescript": "^5.1.0 || ^6.0.0"
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down
8 changes: 8 additions & 0 deletions packages/react-router-cloudflare/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# `@react-router/cloudflare`

## v8.3.0

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- Updated dependencies:
- [`react-router@8.3.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.0)

## v8.2.0

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-cloudflare/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/cloudflare",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Cloudflare platform abstractions for React Router",
"bugs": {
"url": "https://github.com/remix-run/react-router/issues"
Expand Down Expand Up @@ -50,7 +50,7 @@
"peerDependencies": {
"@cloudflare/workers-types": "^4.0.0",
"react-router": "workspace:^",
"typescript": "^5.1.0 || ^6.0.0"
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

41 changes: 41 additions & 0 deletions packages/react-router-dev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
# `@react-router/dev`

## v8.3.0

### Minor Changes

- Restart `react-router dev` with `--conditions=development` when not already configured ([#15291](https://github.com/remix-run/react-router/pull/15291))

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))

### Unstable Changes

⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_

- Add `unstable_rsc/client-version` client build version virtual module ([#15318](https://github.com/remix-run/react-router/pull/15318))

- Support the `subResourceIntegrity` config option in RSC Framework Mode ([#15321](https://github.com/remix-run/react-router/pull/15321))

#### Migration guide

No changes are required when using the default RSC SSR entry. If you maintain a custom `app/entry.ssr.tsx`, import the new virtual module and pass its hashes to React's `importMap` render option:

```diff
+import subResourceIntegrity from "virtual:react-router/unstable_rsc/subresource-integrity";

return renderToReadableStream(<RSCStaticRouter getPayload={getPayload} />, {
...options,
bootstrapScriptContent,
formState,
+ importMap: subResourceIntegrity
+ ? { integrity: subResourceIntegrity }
+ : undefined,
signal: request.signal,
});
```

- Updated dependencies:
- [`react-router@8.3.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.0)
- [`@react-router/node@8.3.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.3.0)
- [`@react-router/serve@8.3.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@8.3.0)

## v8.2.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-dev/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/dev",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Dev tools and CLI for React Router",
"keywords": [
"react",
Expand Down Expand Up @@ -144,7 +144,7 @@
"@vitejs/plugin-rsc": "catalog:",
"react-router": "workspace:^",
"react-server-dom-webpack": "catalog:",
"typescript": "^5.1.0 || ^6.0.0",
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0",
"vite": "^7.0.0 || ^8.0.0",
"wrangler": "^4.0.0"
},
Expand Down
9 changes: 9 additions & 0 deletions packages/react-router-express/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# `@react-router/express`

## v8.3.0

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- Updated dependencies:
- [`react-router@8.3.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.0)
- [`@react-router/node@8.3.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.3.0)

## v8.2.0

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-express/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/express",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Express server request handler for React Router",
"bugs": {
"url": "https://github.com/remix-run/react-router/issues"
Expand Down Expand Up @@ -57,7 +57,7 @@
"peerDependencies": {
"express": "^4.22.2 || ^5",
"react-router": "workspace:*",
"typescript": "^5.1.0 || ^6.0.0"
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down
8 changes: 8 additions & 0 deletions packages/react-router-fs-routes/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# `@react-router/fs-routes`

## v8.3.0

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- Updated dependencies:
- [`@react-router/dev@8.3.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/dev@8.3.0)

## v8.2.0

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-fs-routes/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/fs-routes",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "File system routing conventions for React Router, for use within routes.ts",
"bugs": {
"url": "https://github.com/remix-run/react-router/issues"
Expand Down Expand Up @@ -51,7 +51,7 @@
},
"peerDependencies": {
"@react-router/dev": "workspace:^",
"typescript": "^5.1.0 || ^6.0.0"
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down
8 changes: 8 additions & 0 deletions packages/react-router-node/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# `@react-router/node`

## v8.3.0

### Patch Changes

- Allow `typescript@7` to be used ([#15317](https://github.com/remix-run/react-router/pull/15317))
- Updated dependencies:
- [`react-router@8.3.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.3.0)

## v8.2.0

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router-node/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@react-router/node",
"type": "module",
"version": "8.2.0",
"version": "8.3.0",
"description": "Node.js platform abstractions for React Router",
"bugs": {
"url": "https://github.com/remix-run/react-router/issues"
Expand Down Expand Up @@ -53,7 +53,7 @@
},
"peerDependencies": {
"react-router": "workspace:*",
"typescript": "^5.1.0 || ^6.0.0"
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down
Loading