React Router v8 Graduates Its Future Flags to Defaults, Goes ESM-Only, and Drops `react-router-dom`

React Router v8 Graduates Its Future Flags to Defaults, Goes ESM-Only, and Drops `react-router-dom`

lschvn

React Router v8.0.0 shipped on June 17, 2026, followed by a v8.0.1 patch the next day. It is the first major release under the project's Open Governance model and the first on a planned yearly cadence, deliberately timed to the Node 20 end-of-life window. Node 22 itself is scheduled to reach EOL around May 2027, which is where the team is pointing v9. The headline is less a single feature and more a graduation: the API Development Strategy's job is to make major releases boring by landing breaking changes early behind Future Flags, and v8 is the release where every future.v8_* flag from v7 becomes the default.

Future flags graduate to defaults

If you adopted all active future flags in v7, the v8 API surface is largely unchanged, because those flags are removed or lifted to top-level config and their behavior is now unconditional. The flags that graduated:

  • future.v8_trailingSlashAwareDataRequests is gone; trailing-slash-aware data request URLs are the default.
  • future.v8_passThroughRequests is gone; the raw incoming request is now always passed through to loader and action. Use the url parameter when you want the normalized URL without React Router internals like .data suffixes and _routes search params.
  • future.v8_middleware is gone; middleware always runs. The context passed to loaders, actions, and middleware is always a RouterContextProvider, getLoadContext in a custom server must return one rather than a plain object, the MiddlewareEnabled type is removed, and the interface Future { v8_middleware: true } augmentation trick is no longer needed to type context in Data Mode.
  • future.v8_viteEnvironmentApi is gone; the Vite Environment API build path is mandatory, which is why v8 requires Vite 7+ and why the old pre-rendering implementation was replaced by the Vite preview-server flow.
  • future.v8_splitRouteModules moved to a top-level splitRouteModules config option and defaults to true. Set it to false to keep route modules in a single chunk, or "enforce" to require every route to be splittable.

The "graduation" framing is the real story. Future flags let the team land a breaking change in a v7 minor, let users opt in and report back, and then flip the default in the major with a year of production validation behind it. v8 is the payoff release for that pipeline.

New baselines: Node 22.22, React 19.2.7, Vite 7, and ESM-only

v8 sets a new baseline policy that is worth reading closely. React Router now officially supports all Active LTS Node versions and only the latest minor branch of Maintenance LTS, so it can bump the Maintenance LTS floor quickly when a security patch lands (as it did in the June 2026 Node.js security releases) and adopt Active LTS features that get backported. For the launch that floor is Node 22.22.0+, alongside React 19.2.7+ and Vite 7+.

To modernize the library, every published package is now ESM-only and the tsconfig target/lib fields moved from ES2020 to ES2022 across the board. That ESM-only decision is not cosmetic: it is what unlocked the adapter rewrites below, because the adapters could finally consume other ESM-only packages directly.

react-router-dom is gone, and so are a few deprecated APIs

The most visible removal is react-router-dom. In v7 the DOM APIs were collapsed into react-router/dom, and react-router-dom was kept only as a re-export shim so existing v6 imports kept working. The shim is gone in v8. Any remaining react-router-dom imports must move: RouterProvider and HydratedRouter come from react-router/dom, everything else from react-router.

Three more removals round out the list. The deprecated data fields passed to route-module meta functions are gone; use loaderData instead on MetaArgs and each item in MetaArgs.matches (#14931). The Cloudflare dev proxy at @react-router/dev/vite/cloudflare is removed in favor of @cloudflare/vite-plugin, which also drops wrangler@3 as a peer dependency of @react-router/dev. And the internal hasErrorBoundary field that was injected onto router.routes is gone; the router now infers error boundaries directly, and hasErrorBoundary is no longer accepted on RouteObject, DataRouteObject, the <Route> JSX props, or lazy route definitions (#15074).

Adapter internals: native fetch, node-fetch-server, tsdown, TypeScript 6

The adapter layer got a quiet rewrite that matters for anyone running React Router on Node or generating apps with create-react-router. @react-router/node and @react-router/serve switch from @mjackson/node-fetch-server to @remix-run/node-fetch-server, and create-react-router replaces @remix-run/web-fetch with Node's native fetch. The practical side effect: create-react-router no longer supports the HTTPS_PROXY environment variable that the old node-fetch-based polyfill honored (#14929), which is worth knowing if your CI sits behind a corporate proxy.

On the build side, the package build migrated from tsup to tsdown and the TypeScript tooling moved to TypeScript 6, while preserving individual module files in the published artifacts so public APIs and documented import paths are unchanged (#15092). @react-router/dev replaced cookie and set-cookie-parser with cookie-es, removed the vite-node dependency in favor of Vite's native module runner APIs, and bumped a long tail of dependencies (Babel to 7.29, react-refresh to 0.18, es-module-lexer to 2.1, chokidar to 5). The Express adapter now requires Express ^4.22.2 || ^5, and @react-router/serve moved to Express 5.2.1.

The upgrade path

For most teams the upgrade is mechanical if v7's future flags were already on. The work is: bump Node to 22.22+, React to 19.2.7+, and Vite to 7+; swap any lingering react-router-dom imports; rename data to loaderData in meta functions; and make sure getLoadContext returns a RouterContextProvider. The v7.18.0 release on June 16 also shipped a CSRF check logic fix that is a potential "breaking bug fix" behind a reverse proxy: the check now reads the host from the request URL rather than HTTP headers, so @react-router/serve or @react-router/express apps without trust proxy enabled may need to add the internal host to allowedActionOrigins. Test mutation requests as part of the upgrade.

v8.0.1 (June 18) is a single cleanup patch that removes the obsolete AppLoadContext type export left over from v7, now that request context always flows through RouterContextProvider (#15207). It lands a day after the major, which itself lands the same week vue-router hit its v5 line. The yearly cadence and the future-flag pipeline mean the next major should look a lot like this one: most of the breaks will already have shipped in a v8 minor, and v9 will mostly flip the defaults.

Frequently Asked Questions

Related articles

More coverage with overlapping topics and tags.

Oxc v0.134: oxlint v1.68 Adds Vue Linter Rules and TypeScript Accessor Checks
frameworks

Oxc v0.134: oxlint v1.68 Adds Vue Linter Rules and TypeScript Accessor Checks

Oxc's June release ships oxlint v1.68.0 with two new Vue rules, a TypeScript method-signature-style linter rule, and parser improvements that reject ambient context misuse. oxfmt v0.53.0 ships formatter updates alongside performance work on token parsing.
SWC v1.15.26: Rust-Powered JavaScript Compiler Keeps Shipping
frameworks

SWC v1.15.26: Rust-Powered JavaScript Compiler Keeps Shipping

The swc-project Rust compiler released v1.15.26 with bug fixes, performance improvements, and continued integration across the Node.js and bundler ecosystem.
JetBrains Opens the Vault: JavaScript and TypeScript Support Now Free in IntelliJ IDEA
frameworks

JetBrains Opens the Vault: JavaScript and TypeScript Support Now Free in IntelliJ IDEA

As of March 2026, IntelliJ IDEA v2026.1 ships JavaScript, TypeScript, HTML, CSS, and basic React features at no extra cost, features that previously required a paid Ultimate subscription. The catch: Angular, Vue, and advanced debugging still need Ultimate.

Comments

Log in Log in to join the conversation.

No comments yet. Be the first to share your thoughts.