-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
fix: scope router to basepath for MFE support #6063
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
When a router has a basepath configured, it now only processes location changes that are within its basepath scope. This enables micro-frontend architectures where multiple TanStack routers coexist. Changes: - Add isPathInScope() utility to check if a path is within basepath scope - Add basepath check at start of router.load() method - Add comprehensive unit tests for isPathInScope() The implementation mirrors React Router's stripBasename behavior where paths outside the basename scope are silently ignored. Fixes TanStack#2103 Fixes TanStack#2108 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
WalkthroughAdded a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (2)**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{js,ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (5)📓 Common learnings📚 Learning: 2025-10-01T18:30:26.591ZApplied to files:
📚 Learning: 2025-10-08T08:11:47.088ZApplied to files:
📚 Learning: 2025-10-09T12:59:02.129ZApplied to files:
📚 Learning: 2025-12-06T15:03:07.223ZApplied to files:
🧬 Code graph analysis (2)packages/router-core/tests/path.test.ts (1)
packages/router-core/src/router.ts (1)
🔇 Additional comments (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| } | ||
|
|
||
| load: LoadFn = async (opts?: { sync?: boolean }): Promise<void> => { | ||
| // If this router has a basepath, only respond to paths within scope. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we add support for opting out of navigation, we need to check where that should happen best.
if that's here, then i would rather add an optional callback function that can execute arbitrary user code instead of adding this logic here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you mean adding an optional callback that decides whether navigation should occur or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can make that change, I just want to make sure that Tanstack Router is OK with intercepting changes outside of its route boundaries setup by basepath.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These can be combined also - basepath scoping + optional callback for user overrides.
Question is: is basepath scoping a fundamental enough expectation for it to be the default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as i wrote above, we first need to identify the correct location of such a change.
i feel like history would be better suited. did you have a look at it?
in essence you are building a blocker functionality that history already has
|
Thanks for the suggestion - I explored the history blocker API and I see what you mean about keeping this at the history level. However, I noticed a semantic difference between blockers and what MFE basepath scoping needs:
With the current blocker API, returning A few options I can think of:
Which approach aligns best with how you see the history API evolving? Or did you have something else in mind? |
Problem
When multiple TanStack routers coexist in a micro-frontend (MFE) architecture, all routers respond to all history changes, even when the path is outside their configured
basepath. This causes unexpected behavior:defaultNotFoundComponenttriggers incorrectlyRoot Cause
In
Transitioner.tsx(line 44), every router subscribes to history changes via:This means when the shell navigates to
/settings, an MFE router withbasepath: '/user-management'still receives the event and attempts to match/settingsagainst its routes - which fails, triggering a 404.Why This Happens
TanStack Router's
basepathoption is currently only used for:But it does not filter which history events the router processes. A router with
basepath: '/app'will still try to process navigation to/,/settings,/other-module, etc.Solution
Add a basepath scope check at the beginning of the router's
loadmethod. When a router has abasepathconfigured, it now only processes location changes within its basepath scope.Implementation
New utility function
isPathInScope(pathname, basepath)inpath.ts:trueif the pathname is within the basepath scope/appdoesn't match/application)Basepath check in
router.load():basepathis set and not/, check if current path is in scopeHow React Router Handles This
This implementation mirrors React Router's
stripBasenamebehavior:When
stripBasename()returnsnull,matchRoutes()returnsnull, and nothing renders - the router completely ignores out-of-scope paths.Use Case: Micro-Frontends
Before This Fix
/user-management/users(MFE is loaded)/settings(shell route)/settingsdefaultNotFoundComponentrendersAfter This Fix
/user-management/users(MFE is loaded)/settings(shell route)/settingswithin/user-management? No/settingscorrectlyBreaking Changes
None for most users.
basepath(orbasepath: '/') behave exactly the samebasepathwill now correctly ignore out-of-scope pathsThis is actually fixing the expected behavior. If you set
basepath: '/app', you intuitively expect the router to only care about paths like/app/*.Testing
isPathInScope()://appvs/application)All existing tests pass (213 path tests total).
Files Changed
packages/router-core/src/path.ts- AddedisPathInScope()utilitypackages/router-core/src/router.ts- Added basepath scope check inload()packages/router-core/tests/path.test.ts- Added unit testsFixes #2103
Fixes #2108
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.