Are there workarounds for using validateSearch with lazy file routes?
Looking to reap the benefits of
validateSearch alongside lazy-loaded routes (createLazyFileRoute). I get why it's not possible, but, wondering if there's a preferred work-around or some magic cooking to make validation possible once a lazy route file has loaded. 🙏 Thanks all!
24 Replies
fair-rose•15mo ago
Uhm, you just need to create 2 files, one
<your_route>.tsx which contains only the route settings (including validateSearch) and the other one <your_route>.lazy.tsx that only contains the component for code splitting and lazy loadingexotic-emerald•15mo ago
If you are using a bundler (like Vite, Webpack, Rspack), then you can get the benefits of automatic code-splitting without having to create both files.
https://tanstack.com/router/latest/docs/framework/react/guide/code-splitting#using-automatic-code-splitting
Code Splitting | TanStack Router React Docs
Code splitting and lazy loading is a powerful technique for improving the bundle size and load performance of an application.
Reduces the amount of code that needs to be loaded on initial page load
xenial-blackOP•15mo ago
Using Vite over here.
Interesting ... so I can most likely yank the "lazy" part of all my routes and let vite automagically code split.
Part of this is carry-over from migrating off react-router where I was previously doing stuff like:
const Access = lazy(() => import('@/routes/Access'));
const IdeaPublic = lazy(() => import('@/routes/IdeaPublic'));
const Landing = lazy(() => import('@/routes/Landing'));
const router = createBrowserRouter([
{
element: <Root />,
children: [
{
path: '/',
element: <Landing />,
},
{
path: 'login',
element: <Access />,
},
{
path: '/id/:id',
element: <IdeaPublic />, ...
exotic-emerald•15mo ago
Assuming, this was from your react-router config, then yes.
Just create you routes like:
And turn on the
autoCodeSplitting flag in your TanStackRouterVite plugin config.xenial-blackOP•15mo ago
Gave this a shot — Removed
.lazy from all routes, updated vite config with plugin plugins: [TanStackRouterVite({ autoCodeSplitting: true }), react()],, and it throws an error at runtime on my main layout file. I'm defining a Layout function right inside _layout.tsx ... it's almost as though it's not getting compiled. I'll try moving it to a separate file outside of src/routes and will import it into src/routes/_layout.tsx to see if that helps (Edit: No dice, same result). Appreciate all the help (happy to provide additional info), love the package so far! ❤️
fair-rose•15mo ago
Do you export your route components? The only thing that should be exported from a page file is the
Route object.xenial-blackOP•15mo ago
There we go! I removed all default exports, only have named Route exports and splitting is now working 🙌 . Thanks all!
ratty-blush•15mo ago
could you please share the original file so we can handle this better in the code splitter?
either fix this fully or at least give a descriptive error
xenial-blackOP•15mo ago
@Manuel Schiller
ratty-blush•15mo ago
thanks, I will make sure this will be a nicer experience
xenial-blackOP•15mo ago
Is the “preload” option on <Link> expected to work with autoCodeSplitting enabled?
exotic-emerald•15mo ago
Yes,
preload='intent' | 'viewport' would with the code-splitting option.
The automatic code-splitting is more of a bundler side integration, that essentially generates what's there in the .lazy.tsx file in a virtual file-system.
Since the component is being exported, we shouldn't be code-splitting it. This is because, if it were to be code-split, it'd be moved to the file?tsr-split (a virtual route), which would break other imports. Therefore, we should retain the export in the same compiled file and not do any code-splitting on that export.exotic-emerald•15mo ago
@Manuel Schiller I've opened a fix for this.
https://github.com/TanStack/router/pull/2334
@TrappedInABasement with this fix, you'll be able to import the
Layout component, but you'll have a console.warning telling you that you aren't going to benefit from code-splitting.GitHub
fix(router-plugin): do not split if known ident is exported by Sean...
From https://discord.com/channels/719702312431386674/1283438765817331712
When using autoCodeSplitting, we need to take into account the scenario where the user is exporting their component or loade...
xenial-blackOP•15mo ago
For sanity’s sake, I’m also no longer seeing lazy-loaded routes prefetch with “intent” set on respective <Links> after switching to autoCodeSplitting. I’ll give that a more thorough look to ensure it’s not operator error. I'm stepping through the Link component in debugger, will report back :D.
Interesting — with or without autoCodeSplitting, I have to add
.lazy back into my route filename for preload="intent" and preload="viewport" on links to work.exotic-emerald•15mo ago
Just rechecked, preloading DOES work with
autoCodeSplitting.exotic-emerald•15mo ago
Can confirm that preloading works by observing the split bundle being loaded in with the suffix of
?tsr-split
For example, it'd look like http://localhost:3001/src/routes/index.tsx?tsr-splitexotic-emerald•15mo ago
Can also confirm that preloading works, by observing a loader firing on another route with
preload='intent' when hovering on a link targeting that route.exotic-emerald•15mo ago
@TrappedInABasement your methodology for testing may be wrong, or you might not actually have the
autoCodeSplitting flag turned on.xenial-blackOP•15mo ago
Thanks for the example, mind linking the above repo? I'll record a video of what's going on over here in a few. Attached a screenshot, I'm definitely splitting. Started stepping through router.ts last night and the callstack for the mouseenter handler to walk the flow of
doPreload. It does trigger when I hover on my <Link preload="intent> ... </Link>. Started digging for why it doesn't actually perform the loading. If anything, I want to help ensure it's operator error so others can avoid the same thing 😅 .

ratty-blush•15mo ago
this looks like the quick start example
https://github.com/TanStack/router/tree/main/examples%2Freact%2Fquickstart-file-based
GitHub
router/examples/react/quickstart-file-based at main · TanStack/router
🤖 Fully typesafe Router for React (and friends) w/ built-in caching, 1st class search-param APIs, client-side cache integration and isomorphic rendering. - TanStack/router
ratty-blush•15mo ago
is it possible that you share your app with us?
xenial-blackOP•15mo ago
@Manuel Schiller Happy to hop on a Google meet and screenshare/walkthrough my setup.
Additional notes:
-
_layout.tsx is my core layout file, _ideas.tsx and _groups.tsx are the respective tabbed layouts for each of their nested routes (individual tab content resides inside _ideas and _groups folders.
- On latest package version 1.57.15
- Setting true/false on autoCodeSplitting does correctly work, it's just preload="intent" does nothing.
- Running on tRPC + tanstack-query for data-fetching — I haven't started playing with loader options (yet), I did yank all <Suspense> implementations to see if that made any difference during preloading — no such luck.
- I'm in your shoes most days (debugging client issues), I'll keep digging but LMK if you want to block off 15-20 min to 👀 on a screenshare. Another option, DM me and I can provide steps for logging in to the deployed environment.
xenial-blackOP•15mo ago
Interesting, I'm able to replicate what I'm seeing in my project starting with the example from https://github.com/TanStack/router/tree/main/examples/react/quickstart-file-based. I enabled
autoCodeSplitting in the example's vite config. Code properly splits but hovering over the links does not preload on intent until I add .lazy to the filename. I guess I was under the impression routes would be defined with createLazyFileRoute under the hood when code-split.xenial-blackOP•15mo ago
Added a "Hover me" example in the video above that behaves how I'd expect.