diff --git a/.changeset/pre.json b/.changeset/pre.json index e99b056adb..47b0566765 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -26,5 +26,25 @@ "@playground/split-route-modules-spa": "0.0.0", "@playground/vite-plugin-cloudflare": "0.0.0" }, - "changesets": [] + "changesets": [ + "afraid-tigers-promise", + "cool-pillows-sing", + "dry-impalas-live", + "gold-insects-remain", + "hip-jars-hunt", + "lucky-icons-tap", + "middleware", + "modern-forks-ring", + "new-houses-hug", + "ninety-otters-repeat", + "orange-meals-repair", + "pretty-flies-crash", + "real-adults-protect", + "sharp-sloths-swim", + "short-comics-fly", + "slow-coats-arrive", + "spa-context", + "tough-rats-sparkle", + "yellow-glasses-sort" + ] } diff --git a/packages/create-react-router/CHANGELOG.md b/packages/create-react-router/CHANGELOG.md index e304232ce4..84adfa7d00 100644 --- a/packages/create-react-router/CHANGELOG.md +++ b/packages/create-react-router/CHANGELOG.md @@ -1,5 +1,7 @@ # `create-react-router` +## 7.3.0-pre.0 + ## 7.2.0 _No changes_ diff --git a/packages/create-react-router/package.json b/packages/create-react-router/package.json index 8ef02072e9..8cb1f6ee5c 100644 --- a/packages/create-react-router/package.json +++ b/packages/create-react-router/package.json @@ -1,6 +1,6 @@ { "name": "create-react-router", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Create a new React Router app", "homepage": "https://reactrouter.com", "bugs": { diff --git a/packages/react-router-architect/CHANGELOG.md b/packages/react-router-architect/CHANGELOG.md index dacb578721..97630454f2 100644 --- a/packages/react-router-architect/CHANGELOG.md +++ b/packages/react-router-architect/CHANGELOG.md @@ -1,5 +1,13 @@ # `@react-router/architect` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.3.0-pre.0` + - `@react-router/node@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-architect/package.json b/packages/react-router-architect/package.json index 1fa71660da..244da11ef7 100644 --- a/packages/react-router-architect/package.json +++ b/packages/react-router-architect/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/architect", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Architect server request handler for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-cloudflare/CHANGELOG.md b/packages/react-router-cloudflare/CHANGELOG.md index 8dffb4d47b..c6ad1adcc0 100644 --- a/packages/react-router-cloudflare/CHANGELOG.md +++ b/packages/react-router-cloudflare/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/cloudflare` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-cloudflare/package.json b/packages/react-router-cloudflare/package.json index d333110261..8ee03d7a4d 100644 --- a/packages/react-router-cloudflare/package.json +++ b/packages/react-router-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/cloudflare", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Cloudflare platform abstractions for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-dev/CHANGELOG.md b/packages/react-router-dev/CHANGELOG.md index 3274951dde..621838f195 100644 --- a/packages/react-router-dev/CHANGELOG.md +++ b/packages/react-router-dev/CHANGELOG.md @@ -1,5 +1,29 @@ # `@react-router/dev` +## 7.3.0-pre.0 + +### Patch Changes + +- Fix support for custom client `build.rollupOptions.output.entryFileNames` ([#13098](https://github.com/remix-run/react-router/pull/13098)) +- Fix usage of `prerender` option when `serverBundles` option has been configured or provided by a preset, e.g. `vercelPreset` from `@vercel/react-router` ([#13082](https://github.com/remix-run/react-router/pull/13082)) +- Fix support for custom `build.assetsDir` ([#13077](https://github.com/remix-run/react-router/pull/13077)) +- Remove unused dependencies ([#13134](https://github.com/remix-run/react-router/pull/13134)) +- Stub all routes except root in "SPA Mode" server builds to avoid issues when route modules or their dependencies import non-SSR-friendly modules ([#13023](https://github.com/remix-run/react-router/pull/13023)) +- Fix errors with `future.unstable_viteEnvironmentApi` when the `ssr` environment has been configured by another plugin to be a custom `Vite.DevEnvironment` rather than the default `Vite.RunnableDevEnvironment` ([#13008](https://github.com/remix-run/react-router/pull/13008)) +- Remove unused Vite file system watcher ([#13133](https://github.com/remix-run/react-router/pull/13133)) +- Fix support for custom SSR build input when `serverBundles` option has been configured ([#13107](https://github.com/remix-run/react-router/pull/13107)) + + Note that for consumers using the `future.unstable_viteEnvironmentApi` and `serverBundles` options together, hyphens are no longer supported in server bundle IDs since they also need to be valid Vite environment names. + +- Fix dev server when using HTTPS by stripping HTTP/2 pseudo headers from dev server requests ([#12830](https://github.com/remix-run/react-router/pull/12830)) +- Lazy load Cloudflare platform proxy on first dev server request when using the `cloudflareDevProxy` Vite plugin to avoid creating unnecessary workerd processes ([#13016](https://github.com/remix-run/react-router/pull/13016)) +- When `future.unstable_viteEnvironmentApi` is enabled and the `ssr` environment has `optimizeDeps.noDiscovery` disabled, define `optimizeDeps.entries` and `optimizeDeps.include` ([#13007](https://github.com/remix-run/react-router/pull/13007)) +- Fix duplicated entries in typegen for layout routes and their corresponding index route ([#13140](https://github.com/remix-run/react-router/pull/13140)) +- Updated dependencies: + - `react-router@7.3.0-pre.0` + - `@react-router/node@7.3.0-pre.0` + - `@react-router/serve@7.3.0-pre.0` + ## 7.2.0 ### Minor Changes diff --git a/packages/react-router-dev/package.json b/packages/react-router-dev/package.json index 9c5f6da00c..32d8cf09a6 100644 --- a/packages/react-router-dev/package.json +++ b/packages/react-router-dev/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/dev", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Dev tools and CLI for React Router", "homepage": "https://reactrouter.com", "bugs": { diff --git a/packages/react-router-dom/CHANGELOG.md b/packages/react-router-dom/CHANGELOG.md index 54d12dd697..b5c3a0694c 100644 --- a/packages/react-router-dom/CHANGELOG.md +++ b/packages/react-router-dom/CHANGELOG.md @@ -1,5 +1,12 @@ # react-router-dom +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-dom/package.json b/packages/react-router-dom/package.json index cabba98568..0423a6b212 100644 --- a/packages/react-router-dom/package.json +++ b/packages/react-router-dom/package.json @@ -1,6 +1,6 @@ { "name": "react-router-dom", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Declarative routing for React web applications", "keywords": [ "react", diff --git a/packages/react-router-express/CHANGELOG.md b/packages/react-router-express/CHANGELOG.md index 533681fe58..2002ce0055 100644 --- a/packages/react-router-express/CHANGELOG.md +++ b/packages/react-router-express/CHANGELOG.md @@ -1,5 +1,14 @@ # `@react-router/express` +## 7.3.0-pre.0 + +### Patch Changes + +- Update `express` `peerDependency` to include v5 (https://github.com/remix-run/react-router/pull/13064) ([#12961](https://github.com/remix-run/react-router/pull/12961)) +- Updated dependencies: + - `react-router@7.3.0-pre.0` + - `@react-router/node@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-express/package.json b/packages/react-router-express/package.json index 482ace04e5..7310b3beaa 100644 --- a/packages/react-router-express/package.json +++ b/packages/react-router-express/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/express", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Express server request handler for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-fs-routes/CHANGELOG.md b/packages/react-router-fs-routes/CHANGELOG.md index af9eed8949..292ade2fc8 100644 --- a/packages/react-router-fs-routes/CHANGELOG.md +++ b/packages/react-router-fs-routes/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/fs-routes` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `@react-router/dev@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-fs-routes/package.json b/packages/react-router-fs-routes/package.json index b5637e9563..a03204bd25 100644 --- a/packages/react-router-fs-routes/package.json +++ b/packages/react-router-fs-routes/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/fs-routes", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "File system routing conventions for React Router, for use within routes.ts", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-node/CHANGELOG.md b/packages/react-router-node/CHANGELOG.md index 776d16e899..3c1ebf3819 100644 --- a/packages/react-router-node/CHANGELOG.md +++ b/packages/react-router-node/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/node` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-node/package.json b/packages/react-router-node/package.json index fe7ec08bcc..52e71f6dea 100644 --- a/packages/react-router-node/package.json +++ b/packages/react-router-node/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/node", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Node.js platform abstractions for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-remix-routes-option-adapter/CHANGELOG.md b/packages/react-router-remix-routes-option-adapter/CHANGELOG.md index 11cedb7205..480ce0ab45 100644 --- a/packages/react-router-remix-routes-option-adapter/CHANGELOG.md +++ b/packages/react-router-remix-routes-option-adapter/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/remix-config-routes-adapter` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `@react-router/dev@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-remix-routes-option-adapter/package.json b/packages/react-router-remix-routes-option-adapter/package.json index 3fca4d3bc5..25d74fb53f 100644 --- a/packages/react-router-remix-routes-option-adapter/package.json +++ b/packages/react-router-remix-routes-option-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/remix-routes-option-adapter", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Adapter for Remix's \"routes\" config option, for use within routes.ts", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-serve/CHANGELOG.md b/packages/react-router-serve/CHANGELOG.md index 14dfc21b63..a3fb4d39c3 100644 --- a/packages/react-router-serve/CHANGELOG.md +++ b/packages/react-router-serve/CHANGELOG.md @@ -1,5 +1,14 @@ # `@react-router/serve` +## 7.3.0-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.3.0-pre.0` + - `@react-router/express@7.3.0-pre.0` + - `@react-router/node@7.3.0-pre.0` + ## 7.2.0 ### Patch Changes diff --git a/packages/react-router-serve/package.json b/packages/react-router-serve/package.json index 3f99cff734..8e444727ce 100644 --- a/packages/react-router-serve/package.json +++ b/packages/react-router-serve/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/serve", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Production application server for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router/CHANGELOG.md b/packages/react-router/CHANGELOG.md index 2d8ecdd9bf..732819d544 100644 --- a/packages/react-router/CHANGELOG.md +++ b/packages/react-router/CHANGELOG.md @@ -1,5 +1,264 @@ # `react-router` +## 7.3.0-pre.0 + +### Minor Changes + +- Add `fetcherKey` as a parameter to `patchRoutesOnNavigation` ([#13061](https://github.com/remix-run/react-router/pull/13061)) + + - In framework mode, Lazy Route Discovery will now detect manifest version mismatches after a new deploy + - On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path + - On `fetcher` calls to undiscovered routes, this mismatch will trigger a document reload of the current path + +### Patch Changes + +- Skip resource route flow in dev server in SPA mode ([#13113](https://github.com/remix-run/react-router/pull/13113)) +- Support middleware on routes (unstable) ([#12941](https://github.com/remix-run/react-router/pull/12941)) + + Middleware is implemented behind a `future.unstable_middleware` flag. To enable, you must enable the flag and the types in your `react-router-config.ts` file: + + ```ts + import type { Config } from "@react-router/dev/config"; + import type { Future } from "react-router"; + + declare module "react-router" { + interface Future { + unstable_middleware: true; // 👈 Enable middleware types + } + } + + export default { + future: { + unstable_middleware: true, // 👈 Enable middleware + }, + } satisfies Config; + ``` + + ⚠️ Middleware is unstable and should not be adopted in production. There is at least one known de-optimization in route module loading for `clientMiddleware` that we will be addressing this before a stable release. + + ⚠️ Enabling middleware contains a breaking change to the `context` parameter passed to your `loader`/`action` functions - see below for more information. + + Once enabled, routes can define an array of middleware functions that will run sequentially before route handlers run. These functions accept the same parameters as `loader`/`action` plus an additional `next` parameter to run the remaining data pipeline. This allows middlewares to perform logic before and after handlers execute. + + ```tsx + // Framework mode + export const unstable_middleware = [serverLogger, serverAuth]; // server + export const unstable_clientMiddleware = [clientLogger]; // client + + // Library mode + const routes = [ + { + path: "/", + // Middlewares are client-side for library mode SPA's + unstable_middleware: [clientLogger, clientAuth], + loader: rootLoader, + Component: Root, + }, + ]; + ``` + + Here's a simple example of a client-side logging middleware that can be placed on the root route: + + ```tsx + const clientLogger: Route.unstable_ClientMiddlewareFunction = async ( + { request }, + next + ) => { + let start = performance.now(); + + // Run the remaining middlewares and all route loaders + await next(); + + let duration = performance.now() - start; + console.log(`Navigated to ${request.url} (${duration}ms)`); + }; + ``` + + Note that in the above example, the `next`/`middleware` functions don't return anything. This is by design as on the client there is no "response" to send over the network like there would be for middlewares running on the server. The data is all handled behind the scenes by the stateful `router`. + + For a server-side middleware, the `next` function will return the HTTP `Response` that React Router will be sending across the wire, thus giving you a chance to make changes as needed. You may throw a new response to short circuit and respond immediately, or you may return a new or altered response to override the default returned by `next()`. + + ```tsx + const serverLogger: Route.unstable_MiddlewareFunction = async ( + { request, params, context }, + next + ) => { + let start = performance.now(); + + // 👇 Grab the response here + let res = await next(); + + let duration = performance.now() - start; + console.log(`Navigated to ${request.url} (${duration}ms)`); + + // 👇 And return it here (optional if you don't modify the response) + return res; + }; + ``` + + You can throw a `redirect` from a middleware to short circuit any remaining processing: + + ```tsx + import { sessionContext } from "../context"; + const serverAuth: Route.unstable_MiddlewareFunction = ( + { request, params, context }, + next + ) => { + let session = context.get(sessionContext); + let user = session.get("user"); + if (!user) { + session.set("returnTo", request.url); + throw redirect("/login", 302); + } + }; + ``` + + _Note that in cases like this where you don't need to do any post-processing you don't need to call the `next` function or return a `Response`._ + + Here's another example of using a server middleware to detect 404s and check the CMS for a redirect: + + ```tsx + const redirects: Route.unstable_MiddlewareFunction = async ({ + request, + next, + }) => { + // attempt to handle the request + let res = await next(); + + // if it's a 404, check the CMS for a redirect, do it last + // because it's expensive + if (res.status === 404) { + let cmsRedirect = await checkCMSRedirects(request.url); + if (cmsRedirect) { + throw redirect(cmsRedirect, 302); + } + } + + return res; + }; + ``` + + **`context` parameter** + + When middleware is enabled, your application will use a different type of `context` parameter in your loaders and actions to provide better type safety. Instead of `AppLoadContext`, `context` will now be an instance of `ContextProvider` that you can use with type-safe contexts (similar to `React.createContext`): + + ```ts + import { unstable_createContext } from "react-router"; + import { Route } from "./+types/root"; + import type { Session } from "./sessions.server"; + import { getSession } from "./sessions.server"; + + let sessionContext = unstable_createContext(); + + const sessionMiddleware: Route.unstable_MiddlewareFunction = ({ + context, + request, + }) => { + let session = await getSession(request); + context.set(sessionContext, session); + // ^ must be of type Session + }; + + // ... then in some downstream middleware + const loggerMiddleware: Route.unstable_MiddlewareFunction = ({ + context, + request, + }) => { + let session = context.get(sessionContext); + // ^ typeof Session + console.log(session.get("userId"), request.method, request.url); + }; + + // ... or some downstream loader + export function loader({ context }: Route.LoaderArgs) { + let session = context.get(sessionContext); + let profile = await getProfile(session.get("userId")); + return { profile }; + } + ``` + + If you are using a custom server with a `getLoadContext` function, the return value for initial context values passed from the server adapter layer is no longer an object and should now return an `unstable_InitialContext` (`Map`): + + ```ts + let adapterContext = unstable_createContext(); + + function getLoadContext(req, res): unstable_InitialContext { + let map = new Map(); + map.set(adapterContext, getAdapterContext(req)); + return map; + } + ``` + +- Fix types for loaderData and actionData that contained `Record`s ([#13139](https://github.com/remix-run/react-router/pull/13139)) + + UNSTABLE(BREAKING): + + `unstable_SerializesTo` added a way to register custom serialization types in Single Fetch for other library and framework authors like Apollo. + It was implemented with branded type whose branded property that was made optional so that casting arbitrary values was easy: + + ```ts + // without the brand being marked as optional + let x1 = 42 as unknown as unstable_SerializesTo; + // ^^^^^^^^^^ + + // with the brand being marked as optional + let x2 = 42 as unstable_SerializesTo; + ``` + + However, this broke type inference in `loaderData` and `actionData` for any `Record` types as those would now (incorrectly) match `unstable_SerializesTo`. + This affected all users, not just those that depended on `unstable_SerializesTo`. + To fix this, the branded property of `unstable_SerializesTo` is marked as required instead of optional. + + For library and framework authors using `unstable_SerializesTo`, you may need to add `as unknown` casts before casting to `unstable_SerializesTo`. + +- Fix single fetch `_root.data` requests when a `basename` is used ([#12898](https://github.com/remix-run/react-router/pull/12898)) +- Add `context` support to client side data routers (unstable) ([#12941](https://github.com/remix-run/react-router/pull/12941)) + + Your application `loader` and `action` functions on the client will now receive a `context` parameter. This is an instance of `unstable_RouterContextProvider` that you use with type-safe contexts (similar to `React.createContext`) and is most useful with the corresponding `middleware`/`clientMiddleware` API's: + + ```ts + import { unstable_createContext } from "react-router"; + + type User = { + /*...*/ + }; + + let userContext = unstable_createContext(); + + function sessionMiddleware({ context }) { + let user = await getUser(); + context.set(userContext, user); + } + + // ... then in some downstream loader + function loader({ context }) { + let user = context.get(userContext); + let profile = await getProfile(user.id); + return { profile }; + } + ``` + + Similar to server-side requests, a fresh `context` will be created per navigation (or `fetcher` call). If you have initial data you'd like to populate in the context for every request, you can provide an `unstable_getContext` function at the root of your app: + + - Library mode - `createBrowserRouter(routes, { unstable_getContext })` + - Framework mode - `` + + This function should return an value of type `unstable_InitialContext` which is a `Map` of context's and initial values: + + ```ts + const loggerContext = unstable_createContext<(...args: unknown[]) => void>(); + + function logger(...args: unknown[]) { + console.log(new Date.toISOString(), ...args); + } + + function unstable_getContext() { + let map = new Map(); + map.set(loggerContext, logger); + return map; + } + ``` + ## 7.2.0 ### Minor Changes diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 252d2cb5af..245271730d 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "react-router", - "version": "7.2.0", + "version": "7.3.0-pre.0", "description": "Declarative routing for React", "keywords": [ "react",