NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #2143 most downloaded on npm
Modern and scalable routing for React applications
Last release 4 days ago
30 Sep 2026
Ships fairly regularly
a new release about every 1 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
497 releases · first in 2022
One column per quarter.
### Patch Changes - #8573 `d521abd` - Align server function request and response handling.
### Patch Changes - #8297 `488d046` - Update seroval and seroval-plugins from 1.6.2 to 1.6.7. This picks up the typed array length guard, the maxBase6
#8297 488d046 - Update seroval and seroval-plugins from 1.6.2 to 1.6.7. This picks up the typed array length guard, the maxBase64Length and compactArrayBufferViews options, and the isStream export.
#8460 0c1b5e3 - Abort reserved loader generations with no remaining owners when invalidation removes them from discovery, ensuring their public abort signals are retired.
#8519 3cdd1af - Hand native scroll restoration back to the browser on pagehide, including entries entering BFCache, and reclaim manual restoration when a cached document resumes.
Null-prototype mode now applies only when constructing a copy; existing incoming objects can be reused with their original prototype.
#8363 cecae54 - Detect plain objects by constructor instead of Object.prototype.toString dispatches in isPlainObject, which gates every deepEqual and replaceEqualDeep recursion step. Object literals, JSON.parse output and null-prototype objects are still plain; objects from another realm no longer are. Records with an own constructor key (for example the search params of ?constructor=foo) fall back to a prototype check, so they keep structural sharing while class instances stay opaque.
#8364 0103578 - Compare and copy plain objects in replaceEqualDeep by their string keys only, skipping the symbol-key lookup that dominated key enumeration. Objects with non-enumerable own properties, or symbol keys on the incoming value, now pass through untouched instead of being structurally shared.
#8411 ce10dcd - Reduce structural-sharing allocations by reusing array key storage and returning incoming objects when their children need no replacements. Preserve signed zero consistently, remove stale symbol properties, and keep sparse arrays with extra keys and built-ins with an own constructor opaque.
Null-prototype mode now applies only when constructing a copy; existing incoming objects can be reused with their original prototype.
#8362 84936cc - Allocate the replaceEqualDeep result only at the first difference, so structural sharing of search, params, state and loader data no longer allocates when the new value is deeply equal to the previous one.
#8389 bbd2336 - Split replaceEqualDeep into an equality scan and a copy phase: arrays and objects are scanned by dedicated loops up to the first difference, matching keys prove ownership without a hasOwnProperty lookup, and once a difference is found the result is built without any further equality bookkeeping. Deeply equal search, params, state and loader data are recognised faster and changed values are copied with less work per entry.
Start now cancels discarded middleware and HEAD response bodies, including plain streams and derived branches.
#8417 bc80866 - Speed up deepEqual: identical array elements no longer recurse, the exact comparison keeps a single key counter, and the redundant typeof early exit is gone. Equal numeric arrays compare ~70% faster and record comparisons 5–12% faster in the mixed-mode workloads that Link option stabilization and active-state checks produce, with a slightly smaller bundle. Behavior, including key enumeration and getter read order, is unchanged.
#8418 e561fa1 - deepEqual now takes its flags as positional arguments — deepEqual(a, b, partial?, explicitUndefined?) — instead of an options object. The router's hot callers (Link option stabilization and active-state checks, matchRoute) no longer allocate an options object per comparison, and the comparator reads two booleans instead of a polymorphic object. explicitUndefined replaces ignoreUndefined: false. deepEqual is an internal helper; it stays exported for compatibility of two-argument calls.
#8204 cbbfbe3 - Reduce per-request SSR overhead: abort settled route matches with one shared AbortError-shaped reason instead of building a stack-capturing DOMException per match, skip JSON.parse for search values that cannot start JSON, wait on request signals with one listener per wait, and keep resolved server-function modules in production builds instead of re-importing them on every call.
#8419 a1c8d1a - resolvePath (internal helper) now takes positional arguments — resolvePath(base, to, trailingSlash?, cache?) — so buildLocation and matchRoute no longer allocate an options object per path resolution.
#8204 cbbfbe3 - Stream large deferred SSR hydration payloads through a backpressure-aware router transport, fail known setup errors before response creation, and close cancelled or expired transforms safely.
Start now cancels discarded middleware and HEAD response bodies, including plain streams and derived branches.
Server-function raw streams share one ordered response. Arbitrary or sequential consumption can require potentially unbounded buffering of unread data on the client. Cancelling one raw stream discards it locally, while aborting the whole call cancels the response and server work. Consume streams concurrently, cancel unused streams promptly, or use separate calls when independent backpressure is required. A raw stream that exceeds its unread-byte limit now fails alone; sibling streams and the JSON result keep flowing.
The JSON wire shape of a RawStream server-function argument changed. Clients and servers must run matching versions for requests that pass a RawStream.
The frame-protocol constants (FRAME_TYPE_*, MAX_FRAME_PAYLOAD_SIZE, MAX_FRAMED_STREAMS) moved from the @tanstack/start-client-core root to the @tanstack/start-client-core/client-rpc subpath.
Router requests whose Accept header allows neither text/html nor */* now receive 406 Not Acceptable instead of 500.
Framework adapters share the body <Scripts> composition (getSsrBodyScriptParts, composeSsrBodyScripts) and the eager HTML response wrapper (renderSsrHtmlResponse) from @tanstack/router-core.
Solid SSR now emits one document type and renders late lazy errors through route boundaries. A Solid <Await> without a fallback no longer holds the streamed shell; it renders inside the nearest <Suspense> boundary like React and Vue, and now renders falsy resolved values.
Static server functions decode cached RawStream values with the client deserializer plugins.
SSR Query integrations now keep request cleanup and stream ownership aligned with the router lifecycle.
#8422 a0b2ad9 - Parse the location once when router.update() changes the basepath or rewrite, collect invalidate() match ids in a single pass, and specialize internal basepath composition without arrays or loops. Preserve basepath case sensitivity when creating and updating the router.
Rebuild server route trees when caseSensitive changes and reuse the server cache only when the route tree and case sensitivity both match.
#8421 1ca361b - Parse masked locations without mutating shared state and simplify input rewrite handling.
React activeProps and inactiveProps now follow one precedence rule on every link, including links whose destination is blocked for using a disallowed
#8321 d76a332 - Cache route branches and interpolated paths on their route objects, removing the fixed template limit for registered routes and reusing cached paths across server requests. Rebuild tree-dependent caches together, preserve decoder and trailing-slash isolation, and keep unregistered templates bounded.
#8390 b747fb8 - Keep the Link location cache out of server bundles: buildLocation only creates, reads and writes it when isServer is false. Render React Links on the server without the extra prop copies and the forwarded-ref hook. Link SSR rendering is 20-40% faster in the Link benchmarks and the React Start SSR request loop about 7% faster.
React activeProps and inactiveProps now follow one precedence rule on every link, including links whose destination is blocked for using a disallowed scheme: state props override element props, ref and event handlers, while href, disabled and target stay controlled by the router. Previously a blocked link ignored a ref or handler from its inactive props.
React Link and useLinkProps split router options from element props with one key set on the client and the server. Element props pass through as given: external links forward them verbatim, falsy values included, and useLinkProps now returns children for router-controlled links as it already did for external ones.
#8382 6cfb1e8 - buildLocation no longer structurally shares the built search and state with the current location. The observable location.search and location.state still preserve equal nested references across navigations, because parseLocation stabilizes them once a location is committed. A search whose contents equal the current search but list its keys in a different order now serializes in the requested order, so navigating to it creates a new history entry instead of being treated as the same location. A state object passed to navigate or buildLocation is never mutated.
#8325 700a714 - Reuse the already-owned raw-param snapshot during lightweight source matching instead of copying it again.
#8325 700a714 - Reduce transient JIT compilation memory during navigation by separating search middleware collection from recursive execution.
#8252 7e349c3 - Collect shared pathname-cache keys during interpolation instead of parsing templates twice, and share dynamic-segment handling to reduce bundle size.
#8319 873c830 - Simplify path interpolation into ordered segment-type blocks with shared prefix/value/suffix assembly. Preserve one-pass parsing and optional metadata collection, and reuse the public result object instead of allocating and clearing a missing-parameter callback.
#8252 7e349c3 - Reuse pathname interpolation across Links with bounded router-scoped caches. Keep parameter callbacks and navigation state independent of the cache.
#8327 634da91 - Make pathParamsAllowedCharacters initialization-only. Configure it when creating the router; changing allowed characters requires a new router instance. Remove decoder-update bookkeeping and decoder-change checks from route-owned path caches.
#8370 e9396c9 - Stop exporting the internal isPlainObject and isPlainArray helpers.
#8327 634da91 - Initialize routes directly during route-tree processing, removing the callback indirection while preserving parent-first initialization and route indexes.
#8328 f151ab0 - Reduce duplication in navigation parameter handling while preserving parameter inheritance, null-prototype dictionaries, and updater isolation.
#8410 bc57fa3 - Treat 0 and false as provided _splat values when interpolating paths. Only undefined, null, and '' now omit a splat segment, matching how other path params are stringified.
#8354 9872d2a - Use lightweight request history for SSR and make server navigation a no-op. Use redirect() to issue HTTP redirects. Server hrefs use the same normalization as browser history to handle protocol-relative URLs and control characters.
#8321 d76a332 - Consolidate internal path interpolation into interpolatePath, returning a pathname directly and collecting metadata only when requested. Update router and devtools callers without changing route parsing or interpolation caching.
#8327 634da91 - Reduce route-tree initialization work by avoiding temporary path-joining arrays and duplicate ID normalization.
#8327 634da91 - Reuse parsed route segments when generating paths for navigation, Links, and Devtools. Preserve interpolation metadata and refresh segments when the route tree is rebuilt, without reparsing templates for new parameter values.
#8252 7e349c3 - Reduce the bundle cost of shared Link pathname interpolation while preserving its rendering performance. Reuse one interpolation pass for pathname and optional metadata, keep the bounded cache on the router, and simplify React Link active-state and prop merging.
#8385 9448caa - Collect search middlewares with a counted loop so the optimized code stays valid across navigations. This removes a JIT recompilation that raised peak memory in the interrupted-navigations client memory benchmark.
#8370 e9396c9 - Reuse built locations for Links whose destination does not depend on the current location. buildLocation keeps the result per options object when the build never read the current location, and the React Link passes one stable options object per instance, so navigations resolve unchanged Links with a lookup instead of a full build. The per-route pathname interpolation cache this replaces is removed. Link params, search and activeOptions are compared by value on render, so inline object literals with unchanged contents keep reusing the Link's location. Pass a new object to change a destination; like any other React prop, an object mutated in place is not re-read.
#8325 700a714 - Cache normalized route pathnames so repeated Link destinations do not decode the same interpolation result again.
#8327 634da91 - Share compact parsed route segments between matching and interpolation, preserve original parameter names, and avoid reparsing templates while building paths. Simplify route-tree traversal, reuse existing path helpers, and keep Devtools-only navigation validation out of the production formatter. Preserve dynamic match identity for standalone legacy fallback routes.
#8327 634da91 - Pass route initialization indexes directly instead of wrapping each index in an options object.
Updated dependencies [8fff7fa, f021f6d, ae68535, 9872d2a]:
Preserve native form HTTP redirects, route error handling and masks for document redirects, and per-navigation destinations for shared loader redirect
#8313 f9836f1 - Avoid constructing a query serializer when search is empty or all values are undefined.
#8308 9c1871c - Validate navigation and redirect destinations, keep ambiguous relative URLs on the current origin, and constrain prerender requests and output paths. Prevent redirect headers from appearing in serialized server function response bodies.
Preserve native form HTTP redirects, route error handling and masks for document redirects, and per-navigation destinations for shared loader redirects. Avoid redundant origin parsing and reduce link styling and server-rendering work. Configured origins must already be normalized.
Keep blocked-link inactive props consistent during React hydration, honor explicit redirect Location headers before checking route options, and refresh Vue link state when destinations become internal. Reuse the protocol-relative URL check while parsing redirect schemes once.
Reduce React link bundle size by sharing pathname comparisons, state-prop selection, and element creation.
Share normalized pathname comparisons in Solid and Vue links to reduce bundle size.
#8288 9871c06 - Reduce cache maintenance work during navigation by indexing incoming match IDs once per commit.
#8287 0654c0a - Use full-document navigation when an output rewrite produces a cross-origin destination, including the public URL of a route mask.
Respect registered history blockers during document navigation, passing history locations and the requested push or replace action.
Updated dependencies [9c1871c, 0654c0a]:
When upgrading React or Vue, narrow boundary errors (for example, with error instanceof Error) before reading message or stack. ErrorComponentProps re
#8222 edf0e16 - Make each load transaction's completion follow its current successor so a burst of back-to-back loads wakes each superseded waiter once instead of once per successor. Previously every superseded load() re-polled the current transaction on each later completion, which was quadratic in microtask work.
#8165 2f20c00 - Exclude structural descendants below error and not-found boundaries from route lifecycle callbacks. Preserve lifecycle membership through invalidation, hydration, background reloads, and superseded navigation publication.
#8209 28a5e45 - Preserve falsy thrown values in React and Vue error boundaries. Type React and Vue boundary error components and onCatch callbacks as unknown. Solid boundary errors remain typed as Error; SSR now wraps non-Error loader errors to match Solid’s native boundary behavior, preserving the original value in cause. Router state and loader onError values are unchanged.
When upgrading React or Vue, narrow boundary errors (for example, with error instanceof Error) before reading message or stack. ErrorComponentProps<TError> remains available for values narrowed to a specific error type. Route onError types are unchanged.
#8207 08eff50 - Fix consumer typechecking with skipLibCheck: false by omitting the internal beforeLoad context field from published dehydrated match declarations.
Retain the exported isAbsoluteUrl declaration used by framework bindings so the package entry point does not reference a stripped symbol.
#8259 216c0c4 - Reduce Promise allocations during client navigation and static server SSR policy resolution. Skip cancellable waits for synchronous beforeLoad results while preserving navigation cancellation.
#8240 2f91503 - Avoid quadratic resource handoff scans when navigating with many cached route matches.
#8161 f0b5eda - Retain successful not-found matches as terminal shared boundaries during client navigation, preserving route context while the destination loads.
#8142 50eafca - Avoid unnecessary JSON.parse calls for search parameter values that cannot begin valid JSON, while preserving custom parser behavior.
#8251 0497cae - Use URL.canParse for absolute URL checks in links, navigation, redirects, and build configuration. Preserve a URL constructor fallback for older browsers.
#8230 ee28348 - Replace the internal LRU cache behind path resolution, route matching and the SSR manifest lookup with a smaller SIEVE cache whose hits no longer relink a list, and fix an eviction edge case in the old implementation.
#8244 c18e690 - Reduce promise allocations during client navigation when loader data and route components are already available.
Updated dependencies [9035abc]:
### Patch Changes - #8132 `fa65287` - Build client preload locations on demand and remove the prebuilt-location argument used by framework links. - #8
### Patch Changes - #8117 `3e016ac` - optimize buildLocation path resolution https://github.com/TanStack/router/pull/8108 skip building search validat
3e016ac - optimize buildLocation path resolution https://github.com/TanStack/router/pull/8108
skip building search validation when disabled https://github.com/TanStack/router/pull/8112
skip location state sharing when impossible https://github.com/TanStack/router/pull/8110
fix cache hits for mask resolution when entry is null https://github.com/TanStack/router/pull/8111### Patch Changes - #8084 `5d3785d` - preserve pending UI across retained routes - #8092 `63d2cc9` - Render route errors when redirect target construc
### Patch Changes - #8071 `4c89b15` - inline getOpenAndCloseBraces in parseSegment for byte shaving - #8069 `cf6ab17` - inline isFunction utility fn f
### Patch Changes - #8054 `31882c7` - Reuse resolved lazy route components when revisiting code-split routes, preventing unnecessary pending UI.
### Patch Changes - #8039 `7e93431` - load-client can cache settles abandonned loader work without preload authority
### Patch Changes - #8019 `51138a8` - handle excessive parent relative links
### Patch Changes - #8006 `44a8c3e` - skip impossible JSON parse attempts - #8010 `5253e70` - perf: speed up structural sharing (replaceEqualDeep) by
#8010 5253e70 - perf: speed up structural sharing (replaceEqualDeep) by computing enumerable own keys with Object.keys + a length compare instead of getOwnPropertyNames followed by a propertyIsEnumerable call per key. This runs on every selector result on every state update when defaultStructuralSharing is enabled, and is ~1.3-1.5x faster on typical router state objects with identical behavior.
### Patch Changes - #7992 `ea3a665` - retain mounted UI during revalidation
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
#7984 84db4a8 - Improve route-tree construction and matching performance by fusing static and
dynamic node creation, sorting only dynamic sibling lists that need it, and
deriving matcher depth from trie nodes.
#7985 9cac62a - perf: compact private bundle boundaries- #7975
#7967 6aefb33 - Preserve path params in their raw string form while matching routes so structured values returned by params.parse produce stable match IDs and do not reuse stale loader data.
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
Updated dependencies [9cac62a]:
### Patch Changes - #7962 `b2908c6` - Update Seroval dependencies to version 1.6.2.
Invalidation now retires matching active preloads so older speculative loader results cannot become fresh cache data after invalidation.
#7805 45c4ad8 - Rewrite match loading around a lane-based scheduler that tracks each navigation, preload, and background reload as an ordered unit of work. This fixes pending/redirect/retry state leaking between overlapping navigations, restores correct SSR status codes for redirects, errors, and not-found responses, and closes hydration gaps where the client re-ran work the server had already completed.
headers() now only runs on the server, matching the documented behavior — it is no longer invoked during client-side asset projection.gcTime and preloadGcTime now match the existing runtime default of 5 minutes (300_000).Removed / changed exported internals
RouterState no longer includes loadedAt, isTransitioning, statusCode, or redirect. Use match.updatedAt in place of loadedAt; subscribe to router.state.status / router.state.isLoading in place of isTransitioning; server response status and redirect handling are now internal to the server loader and are no longer exposed on router.state.RouteMatch.fetchCount has been removed, with no replacement — it was purely informational.RouteMatch.status no longer includes 'redirected' (it remains 'pending' | 'success' | 'error' | 'notFound') — redirected matches are dropped from the match list instead of being rendered.RouteMatch.globalNotFound has been renamed and privatized to the internal _notFound field. Use match.status === 'notFound' instead.Match components now accept routeId instead of matchId.RouterStores adapter contract now uses route-keyed presentation stores: matchesId is replaced by ids, matchStores by byRoute, and getRouteMatchStore() by getMatchStore(). The separate loadedAt, isLoading, isTransitioning, statusCode, and redirect stores have been removed, along with the pending/cache stores and their setters. StoreConfig.init has also been removed. Read application-facing state from router.state; preload and cache coordination are now internal.RouterCore members getMatch(), updateMatch(), cancelMatch(), and cancelMatches() — read matches from router.state.matches (e.g. router.state.matches.find((m) => m.id === id)); there is no replacement for mutating or cancelling an individual in-flight match from outside the router.RouterCore.hasNotFoundMatch() — use router.state.matches.some((m) => m.status === 'notFound').RouterCore.looseRoutesById — use routesById.RouterCore.isPrerendering(), RouterCore.isViewTransitionTypesSupported, and RouterCore.viewTransitionPromise, with no replacement.RouterCore.getParsedLocationHref() and RouterCore.clearExpiredCache(), with no replacement — expired cache entries are now reconciled automatically as part of match commit.RouterCore.latestLoadPromise and RouterCore.beforeLoad(), with no replacement.RouterCore.commitLocationPromise and RouterCore.pendingBuiltLocation have been replaced by the internal _commitPromise and _pendingLocation fields.GetMatchFn and UpdateMatchFn types, along with the methods they typed.getMatchedRoutes() export from @tanstack/router-core — use the router.getMatchedRoutes() instance method instead.RouterCore.loadRouteChunk() no longer accepts an array of component types as its second argument. One-argument usage is unchanged; the optional second argument is now 'errorComponent', 'notFoundComponent', or false for internal boundary loading.Redirect.redirectHandled, which was internal redirect bookkeeping.MatchRoutesOpts.preload and MatchRoutesOpts.dest have been removed.StartTransitionFn is now (fn, expected) => Promise<boolean> (previously (fn) => void). This only affects custom framework adapters that implement startTransition.Nothing published for this version
Window and element scroll targets are now handled independently. Restoring one target no longer suppresses resets for other uncached configured target
#7807 e2dd204 - fix(router-core): handle window and element scroll restoration independently
Window and element scroll targets are now handled independently. Restoring one target no longer suppresses resets for other uncached configured targets, and a restored element is no longer reset when the window has no cached position.
Hash navigation no longer resets elements configured through scrollToTopSelectors and retains precedence over stale window positions through destination invalidations.
Scroll positions are sampled when leaving a route, preserving live changes made after the most recent scroll event. This also prevents client hydration from undoing nested positions restored by the SSR script.
Fixes #7687.
sanitizePathSegment now re-encodes characters in the WHATWG URL "path percent-encode set" (<, >, ", ` `, {, }) and ASCII control characters back to th
#7695 9809a06 - fix(router-core): re-encode URL-unsafe characters in sanitizePathSegment to prevent infinite redirect loops
sanitizePathSegment now re-encodes characters in the WHATWG URL "path percent-encode set" (<, >, ", `, {, }) and ASCII control characters back to their percent-encoded form, instead of stripping control characters. This prevents mismatches between the original URL and the router's internal representation that previously caused infinite 307 redirect loops on paths containing these characters (e.g. /%7B%7Btemplate%7D%7D).
Fixes #7587.
### Patch Changes - #7562 `776d8ef` - Prevent scroll restoration listeners from being installed when scroll restoration is disabled.
### Patch Changes - #7559 `df1076c` - Fix retained search params overriding explicit default-valued navigations when used with stripSearchParams.
### Patch Changes - #7555 `ac10815` - Fix search middleware composition so retainSearchParams does not restore search params that a downstream stripSe
### Patch Changes - #7381 `2cca73c` - fix(router-core): use search validator output type for search middleware context - #7549 `7a83e67` - Fix retainS
### Patch Changes - #7524 `b4cd5af` - defer $_TSR teardown until DOMContentLoaded
### Patch Changes - #7505 `2f53749` - Preserve primitive values thrown from beforeLoad error handling.
### Patch Changes - #7497 `d1997b6` - fix streaming
Add support for Rsbuild client output formats, including module output by default and IIFE output for classic script environments.
Add support for Rsbuild client output formats, including module output by default and IIFE output for classic script environments. (#7477)
Client entry scripts and preloads are now represented as root route manifest assets, script preloads follow the manifest script format, and script asset cross-origin configuration uses the script key. The transformAssets script callback context now exposes only kind: 'script' and url, keeping script format handling internal to manifest rendering.
Fix hash scrolling with resetScroll={false}
resetScroll={false} (#7464)Fix hash navigation being overridden by stale scroll restoration entries.
Add deferred Hydrate boundary support for TanStack Start.
Add deferred Hydrate boundary support for TanStack Start. (#7362)
Hydrate boundaries can now be code-split by the Start compiler, preload their generated client chunks, preserve server-rendered fallback HTML, and replay interaction-triggered events after hydration. The compiler integration now uses a Start-owned compiler plugin for Hydrate virtual modules across Vite and Rsbuild, with dev invalidation for generated virtual modules.
Shared AST utilities used by the router code-splitter and Hydrate virtual modules were moved into @tanstack/router-utils so both pipelines can retain referenced top-level declarations, unwrap local exports, and let dead-code elimination remove unused route module code.
Fix route mismatch warnings, HMR route index refresh, and generated route type preferences for duplicate pathless/index routes.
Run custom router hydration before the initial client route match so hydrated router configuration, such as request-specific URL rewrites, can be inst
params.priority route option as tie breaker in route matching algorithm
Add runtime-configurable inline CSS and opt-in CSS URL templates for transformAssets.
fix(router-core): fix missing closing paren in CSS.supports check for view transition types
Update seroval dependencies to version 1.5.4.
Fix params.parse inference for discriminated union path params while preserving path key validation.
Allow params.parse to experimentally return false to skip an incoming route candidate during path matching. Thrown parse errors still surface on the s
params.parse to experimentally return false to skip an incoming route candidate during path matching. Thrown parse errors still surface on the selected match instead of falling through, and outgoing typed route-template links continue to use exact route lookup followed by params.stringify for URL generation. (#7263)Updated dependencies \[`b2908c6`]:
b2908c6]:
b2908c6]:
Updated dependencies \[`45c4ad8`]:
45c4ad8]:
45c4ad8]:
Add TanStack Start inline CSS manifest support for SSR so route styles can be embedded in the HTML response and hydrated without duplicate stylesheet
Fix async loaders that throw or return notFound() so they do not briefly mark the match as success before the final not-found boundary is resolved.
Fix async loaders that throw or return notFound() so they do not briefly mark the match as success before the final not-found boundary is resolved. (#7184)
This prevents route components from rendering with missing loader data during navigation when React observes the intermediate match state before not-found finalization completes.
### Patch Changes - chore: bump to h3 v2-rc.20
Reduce React Start SSR manifest payload size by omitting unmatched route assets from dehydrated router state while keeping start-manifest asset serial
Reduce React Start SSR manifest payload size by omitting unmatched route assets from dehydrated router state while keeping start-manifest asset serialization deduplicated by shared object identity. (#7157)
This improves SSR HTML size for apps with many routes that share the same CSS assets and adds regression coverage for CSS module hydration, navigation, and start-manifest asset reuse.
avoid false notFound matches for proxied loader data
shorten internal non-minifiable store names for byte shaving
migrate createStore > createAtom for simpler API
Preserve component-thrown notFound() errors through framework error boundaries so route notFoundComponent handlers render without requiring an explici
notFound() errors through framework error boundaries so route notFoundComponent handlers render without requiring an explicit routeId. (#7077)Fix preload from continuing into child beforeLoad and head handlers after a parent beforeLoad fails.
beforeLoad and head handlers after a parent beforeLoad fails. (#7075)Avoid re-running hash scrolling after SSR hydration when later preload or invalidate cycles resolve without a location change.
Fix a regression where browser back/forward navigation could fail to restore the previous scroll position for an existing history entry.
fix: scroll restoration without throttling
### Patch Changes - tanstack/store 0.9.3
### Patch Changes - feat: transformAssets
Replace tiny-invariant and tiny-warning with in-house solution for bundle-size
Invalidation now retires matching active preloads so older speculative loader results cannot become fresh cache data after invalidation.
#7805 45c4ad8 - Rewrite match loading around a lane-based scheduler that tracks each navigation, preload, and background reload as an ordered unit of work. This fixes pending/redirect/retry state leaking between overlapping navigations, restores correct SSR status codes for redirects, errors, and not-found responses, and closes hydration gaps where the client re-ran work the server had already completed.
headers() now only runs on the server, matching the documented behavior — it is no longer invoked during client-side asset projection.gcTime and preloadGcTime now match the existing runtime default of 5 minutes (300_000).Removed / changed exported internals
RouterState no longer includes loadedAt, isTransitioning, statusCode, or redirect. Use match.updatedAt in place of loadedAt; subscribe to router.state.status / router.state.isLoading in place of isTransitioning; server response status and redirect handling are now internal to the server loader and are no longer exposed on router.state.RouteMatch.fetchCount has been removed, with no replacement — it was purely informational.RouteMatch.status no longer includes 'redirected' (it remains 'pending' | 'success' | 'error' | 'notFound') — redirected matches are dropped from the match list instead of being rendered.RouteMatch.globalNotFound has been renamed and privatized to the internal _notFound field. Use match.status === 'notFound' instead.Match components now accept routeId instead of matchId.RouterStores adapter contract now uses route-keyed presentation stores: matchesId is replaced by ids, matchStores by byRoute, and getRouteMatchStore() by getMatchStore(). The separate loadedAt, isLoading, isTransitioning, statusCode, and redirect stores have been removed, along with the pending/cache stores and their setters. StoreConfig.init has also been removed. Read application-facing state from router.state; preload and cache coordination are now internal.RouterCore members getMatch(), updateMatch(), cancelMatch(), and cancelMatches() — read matches from router.state.matches (e.g. router.state.matches.find((m) => m.id === id)); there is no replacement for mutating or cancelling an individual in-flight match from outside the router.RouterCore.hasNotFoundMatch() — use router.state.matches.some((m) => m.status === 'notFound').RouterCore.looseRoutesById — use routesById.RouterCore.isPrerendering(), RouterCore.isViewTransitionTypesSupported, and RouterCore.viewTransitionPromise, with no replacement.RouterCore.getParsedLocationHref() and RouterCore.clearExpiredCache(), with no replacement — expired cache entries are now reconciled automatically as part of match commit.RouterCore.latestLoadPromise and RouterCore.beforeLoad(), with no replacement.RouterCore.commitLocationPromise and RouterCore.pendingBuiltLocation have been replaced by the internal _commitPromise and _pendingLocation fields.GetMatchFn and UpdateMatchFn types, along with the methods they typed.getMatchedRoutes() export from @tanstack/router-core — use the router.getMatchedRoutes() instance method instead.RouterCore.loadRouteChunk() no longer accepts an array of component types as its second argument. One-argument usage is unchanged; the optional second argument is now 'errorComponent', 'notFoundComponent', or false for internal boundary loading.Redirect.redirectHandled, which was internal redirect bookkeeping.MatchRoutesOpts.preload and MatchRoutesOpts.dest have been removed.StartTransitionFn is now (fn, expected) => Promise<boolean> (previously (fn) => void). This only affects custom framework adapters that implement startTransition.Updated dependencies [45c4ad8]:
remove pendingMatches, cachedMatches (#6704) move to signal-based reactivity solid uses its own native signals
Your coding agent can read these notes before it upgrades. Set up the MCP server →