TanStack: A Deep Dive into Server Functions and Routing with Tanner Linsley - JsJ 667

In this episode of JavaScript Jabber, host Steve Edwards is joined by panelists Dan Shappir and AJ O'Neil, along with special guest Tanner Lindsley, to explore the innovative world of TanStack, a collection of open-source libraries designed to enhance web development. Tanner shares insights into the origins and evolution of TanStack, highlighting its journey from simple libraries like React Table to a comprehensive toolkit including TanStack Query, TanStack Virtual, and more.

Special Guests: Tanner Linsley

Show Notes

In this episode of JavaScript Jabber, host Steve Edwards is joined by panelists Dan Shappir and AJ O'Neil, along with special guest Tanner Lindsley, to explore the innovative world of TanStack, a collection of open-source libraries designed to enhance web development. Tanner shares insights into the origins and evolution of TanStack, highlighting its journey from simple libraries like React Table to a comprehensive toolkit including TanStack Query, TanStack Virtual, and more. The discussion delves into the nuances of building framework-agnostic tools, the challenges of server-side rendering, and the rise of remote procedure calls (RPCs) as a modern development approach. With intriguing debates on the future of meta frameworks and the role of server components, this episode provides a deep dive into the cutting-edge technologies shaping the development landscape. Whether you're a fan of React, Solid, or just curious about the direction of web frameworks, this conversation offers valuable insights and expert opinions on the current and future state of web development. Tune in to discover how TanStack is influencing the way we build and manage applications in the ever-evolving JavaScript ecosystem.

Transcript

Steve Edwards [00:00:04]:
Hello, everybody. Welcome to another exciting episode of JavaScript Jabber. I am Steve Edwards, the host with the face for radio and the voice for being in mind, but you're stuck with me as your host. Today with me on our panel, we have mister Dan Shapiro. How are you doing, Dan?

Dan Shappir [00:00:21]:
I'm fine. Hello from Tel Aviv.

Steve Edwards [00:00:23]:
Where it's probably really warm. Right?

Dan Shappir [00:00:25]:
Oh, not super warm, but nice. You know, you can wear a t shirt outside if you like.

Steve Edwards [00:00:30]:
Right. Yeah. I was just I'll I'll diverge a little bit here. I was just in Thailand. I've been gone for a couple weeks. Was visiting my daughter there, and and in Thailand, it's really, really warm. It barely gets below 70 Fahrenheit during the year even at the lowest point in the year. And on the way there, we got so I dressed for Thailand, right, to have clothes for Thailand.

Steve Edwards [00:00:53]:
Well, on the way there, we got delayed in twenty four hours in Seoul, Korea. And, to say it was cold is an understatement of the year. It we went from I told when we left Seoul and went to Chiang Mai, we went from 22 Fahrenheit to 22 Celsius, because it was, like, below zero cold. It was so cold. We tried to go for a walk one day and lasted about three minutes and said, okay. We're going back inside. So, but, yeah, Chiang Mai was awesome because we had, it was, like, in the eighties Fahrenheit. You know? No humidity.

Steve Edwards [00:01:27]:
This is the coolest time of the year. Coolest in terms of temperature, not because I was there. But, but, yeah, it was perfect perfect weather. And then I came back from wearing shorts and no coat all week to bundling up and and, having multiple blankets on the bed.

Dan Shappir [00:01:44]:
So So Tel Aviv is not in the eighties, but it's in the high sixties, low seventies.

Steve Edwards [00:01:49]:
That's still pretty nice.

Dan Shappir [00:01:51]:
During the day.

Steve Edwards [00:01:52]:
Yeah. That's nice.

Dan Shappir [00:01:53]:
At night at night, it gets a bit colder.

Steve Edwards [00:01:55]:
And then, also on our panel, we have mister AJ. How are you doing, AJ?

AJ O'Neil [00:02:00]:
Yo. Yo. Yo. Coming at you live from

Steve Edwards [00:02:04]:
the showroom.

Dan Shappir [00:02:05]:
Oh, it's better than the alternative.

Steve Edwards [00:02:07]:
Yes. Coming at you dead? Yes. I agree. So and our very special guest today is mister Tanner Lindsley of TAMstack fame. How are you doing, Tanner?

Tanner Lindsley [00:02:19]:
I'm doing great. Yeah.

Dan Shappir [00:02:21]:
I'm very excited.

Tanner Lindsley [00:02:22]:
Good to be here.

Steve Edwards [00:02:23]:
Alright. It's good to have you back. We had have had Tanner here in the past on JavaScript Jabber on episode what was it, Dan? I forgot the number.

Dan Shappir [00:02:31]:
Oh, I think it was episode five seventy eight.

Steve Edwards [00:02:34]:
Five 70 eight. Talking about the tan stack. And, for for those of you who might be wondering, this is a question I asked on a previous episode. Data's not called Tanner tan stack because he is tan because if you look at him, he is obviously not very tan like me. I don't know. Is tan because of Tanner. So for those of you unlike me, who made that logical jump, good for you, but, some of us aren't that smart. Anyway, so we are here ten days to talk about well, actually, before we get into start, let's, just give a brief description of what the TAN stack is overview for those who might not have heard of it before.

Tanner Lindsley [00:03:13]:
You guys are gonna need that. Right? Not me?

Steve Edwards [00:03:18]:
Yeah. Yeah. Sure. Let me pull up the about us page.

Tanner Lindsley [00:03:21]:
I'll do it. And

Dan Shappir [00:03:22]:
you'll do it. Thank you.

Tanner Lindsley [00:03:24]:
So so do it if you want

Dan Shappir [00:03:26]:
to, but I prefer you

Tanner Lindsley [00:03:27]:
do it. I got it. I'm just playing with you. No. So when I I started TanStack as a like, an open source GitHub organization a couple years ago to start collecting all of my libraries that I was building. It started with, React table and then React query, and we took both of those agnostics so they became something that I didn't wanna have to, like, brand, you know, every framework times every library that I had. So I decided to call it TanStack. And so I pulled all those libraries together, and then we kept building.

Tanner Lindsley [00:04:03]:
So now there's a there's a virtualization library called tanstack virtual. We have some libraries that are for, like, helping you build open source packages. We have our own store now, our reactive store.

Dan Shappir [00:04:17]:
Oh, that's cool.

Tanner Lindsley [00:04:19]:
Canstack form is a an agnostic headless form library, which is pretty sweet. It's almost one dot o, which is pretty pretty cool.

Steve Edwards [00:04:28]:
What is that? Is that like a form rendering library where you provide the underlying structure and it renders the form, or what exactly

Tanner Lindsley [00:04:35]:
is that is that what? So it's it's more around just like the state management, the validation, and the form life cycles, for forms, like, for doing client side and full stack forms. But it's headless. So when it comes time to render those forms, you attach the form logic to, whatever you want, whether it's, like, a component library or just a raw input, something like that. Yeah. So it gives you full control over you over your UI, but gives you all of the nice logic and validation and management of the form state that you would expect.

Dan Shappir [00:05:11]:
That's cool.

Tanner Lindsley [00:05:12]:
Yeah. Corbin Crutchley is the one who's kind of heading that up. We we combined our libraries together. He was building, I can't remember when he was built. It's been a while. It's been about two years, but he was building a form library that was supposed to kind of be the next version of Formic, but it was React only. And then I was building one that was really, really type safe and agnostic. So we put them together, and that became Panstack form.

Steve Edwards [00:05:42]:
Yes. The the according to the description, it helps you, quote, stop crying over your forms. So, obviously, obviously, you have experience in working with forms.

Tanner Lindsley [00:05:50]:
I I don't cry too much. But if there's something that would make me cry, it would be building forms. Yeah.

Dan Shappir [00:05:57]:
By the way, are you familiar with the vest form validator?

Tanner Lindsley [00:06:02]:
The what validator? Sorry.

Dan Shappir [00:06:03]:
Vest.

Tanner Lindsley [00:06:04]:
No. I'm not.

Dan Shappir [00:06:06]:
It's we actually had the creator on, Eviatal. He's, he works at Meta, but it it's it's his own project. It's it it's interesting in that it does form validation in a way that looks very much like a unit testing.

Tanner Lindsley [00:06:23]:
Interesting. Yeah. I I would love to look at it. That sounds cool.

Dan Shappir [00:06:26]:
So it's called VEST.

Tanner Lindsley [00:06:28]:
K.

Steve Edwards [00:06:28]:
Needless to say, he's you hear this coming very invested in it. Sorry. That was just hanging out there. I had to grab that one.

Tanner Lindsley [00:06:37]:
Oh, yeah. Like a matzo ball. So that so form is kind of the another one we're working on. And then, obviously, the last so a a year ago, we did one dot o four ten stack router, which I'd been working on for several years before that as well. And now we're here to talk about start, which is

Dan Shappir [00:06:59]:
So before before we go there, I noticed that you have a few more things on the 10 stack site. You've got, 10 stack ranger. What is that?

Tanner Lindsley [00:07:08]:
Ranger is, it's not it's not used as much in my opinion. It's it's a fun little library from my past, but, you can use it to create multirange sliders. So if you ever use the range element, you've got that single slider. Yeah. We we needed some that had both handles that you'll kinda see, for range slider selectors. And then we even had some that would create steps. So we'd have, like, three or four different handles on an individual range input, and you'd be able to kind of create different steps, using different handles. So it's a headless library to create those.

Tanner Lindsley [00:07:49]:
We wanted it to have a very custom UI. I I don't use it as much anymore, admittedly, but it's still a pretty cool library.

Dan Shappir [00:07:58]:
And also, 10 stack config.

Tanner Lindsley [00:08:01]:
Yeah. The con the config is what we use for, publishing all of our libraries. So it it helps us, both build all of the the different versions, like ESM and and common JS, like legacy and modern versions, and it helps us publish those to TenStack using or to NPM using kind of our, it's it's based on, Angular semantic versioning, but, basically, it lets us do all of our PR automation for releasing new versions and whatnot.

Dan Shappir [00:08:39]:
Cool. Okay. So now back to 10 stack start.

Tanner Lindsley [00:08:46]:
So start is, I'm I'm gonna be honest. It's like 90% of start is just TANSTACK router, because routers are frameworks. There's not really any way around that. But we decided to I decided to build the router first as just like a client side router that would have some SSR utilities on top of it. But then trying to put together your own SSR environment really sucks, which is why, like, meta frameworks, as we call them, exist. So 10 stack start is, like, the official implementation of getting server features into a 10 stack router application. That mostly includes, so you get SSR, which is the very first thing which most people want. It gives you streaming on top of that as well, so all the new streaming, you know, APIs that React has for suspense and and just being able to stream data down in responses in general.

Tanner Lindsley [00:09:51]:
And then it gives you, bundling for both like, for all the environment. So it bundles the client side, the server side, and it also bundles for server functions, which is it's our version of being able to access, you know, all of the server features that you would expect. But so it that's where it gets a little interesting. I think we could discuss that a little bit more, but server functions are really cool.

Dan Shappir [00:10:20]:
Before we get to server functions, which I will definitely want to discuss, RPCs is a is a Yeah. Favorite topic of mine. And I actually had an episode on JavaScript Jabber when I spoke about RPCs.

Tanner Lindsley [00:10:32]:
Awesome.

Dan Shappir [00:10:33]:
I don't even I don't remember the number off the top of my head. What about offhand?

Steve Edwards [00:10:38]:
I always check both places.

Dan Shappir [00:10:40]:
Yeah. That's true. I I think it it's worth mentioning, though, because I think we kinda skipped it, that all of your libraries, utilities, frameworks, whatever, they're all built on top of React. Right? There's nothing like you don't you haven't implemented your own frame view framework or whatever it's supposed to be called.

Tanner Lindsley [00:11:04]:
No. They're not built on top of React. We have React adapters for all of them. So every single one of these libraries is, in fact, called TanStack something because it's no longer just React. So for instance, their TanStack Query has adapters for React and Vue and Svelte and Solid. TenStack virtual has adapters for all of those, and so does TenStack form and table. TenStack router is the only one that is currently React only, and that's mostly just for our own sanity's sake right now. Basically, because we we just wanted to get all the way finished from, you know, zero to one dot o on one framework.

Tanner Lindsley [00:11:56]:
We're still preparing the code base and writing it to be agnostic, but we're just not trying to, you know, do too much at once.

Dan Shappir [00:12:06]:
You think it's really doable? I think I spoke with Ryan Carniato a while back where he told me that I I think it might have been him. Maybe I'm confusing it with somebody else, but I think it was probably him, and he probably said something along the lines that he came to the conclusion that writing a true multi framework router is bordering on impossible or something.

Tanner Lindsley [00:12:32]:
I recently changed his mind.

Dan Shappir [00:12:35]:
So,

Tanner Lindsley [00:12:37]:
he had some concerns, and so did I, honestly. And we got together, and we we've been talking for, I mean, years. We we go back a long time, and we've been chatting a lot about this. And and recently, he he's like, oh, you know what? With our new solid two point o stuff they're working on and the new async data primitives, there's really no concerns anymore. It's just opinions on top of routing, and life cycles for navigation. So, really, what we're going to do is, actually, I'll let you in on some fun news. So it's nothing it's something official, and it might might never become something official. But behind the scenes so the TanStack start and the solid start team, we're working very, very closely now, on a lot of things.

Tanner Lindsley [00:13:26]:
So mainly one is that Tencent start and solid have both been based on Vinci up to this point, which is awesome. It helped us get to where we are today. But to to better consume Nitro and to even further align our architectures, we are we are moving away from Vinci to just a unified layer for start, essentially. And it's just gonna have some server function plugins, a Nitro coordinator, and that's going to set the stage for TANSTACK router for solid. So solid router. And that's that's known for That that is a semi active development. We have some people who are you know, we're separating some of the utilities. We're making sure that,

Dan Shappir [00:14:16]:
you

Tanner Lindsley [00:14:16]:
know, we're not mixing up framework types and and getting ready to build these adapters. But, essentially, there's nothing blocking us now. If we want if I wanted to divert all my attention to solid router and solid you know, getting that working in solid, I could do that today, but I'm not gonna do that till we get the React one done.

Dan Shappir [00:14:35]:
So question about that. You threw out a whole bunch of project names, some of which I'm familiar with, some of which less so. Vinci, Nitro. Also, as I recall, Vinci is built on Vite. Yeah. So can you tell us a little bit about all these projects?

Tanner Lindsley [00:14:53]:
I would love to. So let's start at the let's start at the bottom level. So all of this is based on Vite. We're a % bought into the Vite ecosystem. I believe it's I believe it's the future. So we wouldn't be able to do any of this without Vite. And at the end of the day, a lot of this boils down to just Vite and Vite plug ins. And some some of it is going to use the new Vite six environment APIs, and some of it we can just do today already just by building multiple environments ourselves.

Tanner Lindsley [00:15:26]:
So then on top of Vite, there's Nitro. So Nitro is this toolkit that it it uses Vite, but it helps you build your back end code to work basically anywhere you wanna deploy it. So you can use Nitro as this unified layer. Nitro is by the UNJS team. And it has this unified layer for pretty much everything you'd wanna do on the back end. You can write your code one mostly one way and deploy it to basically anywhere that they maintain an adapter for, and it will just work.

Dan Shappir [00:16:03]:
So they handle the deployment part of, building a framework slash meta framework for you because that's obviously a big challenge having to deploy to all the different platforms.

Tanner Lindsley [00:16:15]:
Well, like, to put it into perspective, if you so, so, like, Next. Js and Remix, they have to maintain their own adapters to build their projects into the right formats for all these different, deployment destinations. Nitro does that. That's Nitro's job. And so if you just use Nitro, you don't have to worry about that and duplicate all that effort. You just get to use what Nitro has built. So, literally, for me, I recently migrated a site from Vercel over to Netlify. And it was literally the difference of me going into my config and saying, deployment, you know, I think deployment preset, I think, is what it's called.

Tanner Lindsley [00:17:06]:
I just changed it. It's a string. I just changed it from Vercel to Netlify. And when I rebuilt it, it just rebuilt everything for Netlify instead. I didn't have to change anything.

Dan Shappir [00:17:18]:
And it also seems supports AWS, CloudFlare, whatever, and so on and so forth.

Tanner Lindsley [00:17:24]:
Yeah. And and so Nitro is built on top of Vite, and they're upgrading to the new Vite APIs as well. So, it's the clearest path for no duplicated effort really whatsoever is they're gonna maintain these adapters, and we're going to use Nitro directly, and you get to use the Nitro APIs in your apps as well. So they have wonderful products like Unstorage, where you just kinda have this unified storage API, and you supply the drivers. And that driver may map to, you know, one type of memory on this host, or you could map it to another one. If you're using CloudFlare, you could map it to d one or something like that. So they have a really great, like, abstraction for all of these different, implementations of features that we like to use on servers.

Dan Shappir [00:18:19]:
I'm I'm curious. Aside from you guys, you and Ryan, and, who else is using them for what project?

Tanner Lindsley [00:18:28]:
It actually came out of the view in the Nuxt ecosystem. So Nuxt is built on top of UNJS, essentially, like, all of it, and that's what they use. So UN UNJS and Nitro is kind of like the lower level server toolkit and the primitives that came out of the Nuxt project.

Steve Edwards [00:18:50]:
I was wondering if there was a relationship because I remember talking with Daniel Roe about Nitro when that first came

Tanner Lindsley [00:18:55]:
in Yeah.

Steve Edwards [00:18:55]:
When they first started using that. And the the speed increase was supposedly really phenomenal.

Tanner Lindsley [00:19:01]:
And and you know who else uses it is, Brandon who built, analog JS. So it's it's the it's kind of the same approach. Like, hey. Let's build a framework that uses Nitro but for Angular. So he built his own Angular meta framework, and it uses Nitro under the hood. Very, very cool. That's that's how powerful and portable it is.

Dan Shappir [00:19:25]:
So it's really interesting that Vite came out of Vue, and now Nitro came out of Vue. So Vue is contributing a lot to the framework space way beyond Vue itself.

Tanner Lindsley [00:19:37]:
Yeah. Absolutely. There's there's a lot of things about Nuxt that have been pushing forward what we've been able to do outside of, like, Nuxt itself. It's it's pretty sweet. So Vinci Vinci is built by Nikhil Saraf, and Nikhil was working on a solid team for a little while. I think he still is technically started the part of the solid team. But before Vite six came out, there wasn't really a way for you to do kind of a unified, hey. I'm building a full stack application, like a unified config.

Tanner Lindsley [00:20:19]:
You would have to have had, like, one Vite configuration and build setup for your client, and then you'd have to have another setup with Nitro or something else for your back end, and you kinda merge those together, or you end up building something that something like that on your own, like Remix has done. But Nikhil wanted kind of this unified layer, and we also needed to do some multi environment things before Vite six came out. So he built VINXI, v I n x I. And VINXI is essentially a wrapper around that experience. So it uses Nitro directly and Veatch directly to coordinate this full stack dev and prod build experience. And it was phenomenal. Like, it it helped me get off the ground really quickly and just start focusing on building, like, the runtime and my my framework APIs. Now that we're getting closer to one dot o for a 10 stack start, we we want I want more control over what we're doing with Nitro and what we're doing with Vite.

Tanner Lindsley [00:21:32]:
And Nikhil is also just very busy with other things. In my opinion, more important things for him, and that's totally fine. So Ryan and I have decided that we're going to kind of slowly start to supplant this Vinci logic with, just a shared layer that we that we use between all the start projects.

Dan Shappir [00:21:55]:
Implemented in what, by the way?

Tanner Lindsley [00:21:58]:
Well, sorry. What do you mean?

Dan Shappir [00:22:00]:
What are you well, of course, I I of course, I assume it's Java well, TypeScript. But, like, what libraries are you using there? Is it, like, based on signals because it's Ryan? Or

Tanner Lindsley [00:22:13]:
No. So so this layer is mostly going to be a collection of Vite plug ins, that are very configurable, and they'll use Babel under the hood. And, really, it will all come together in, hopefully, what is going to be a very thin layer on top of Nitro. So, essentially, just feeding Nitro a unified config to say, here's here's what I want you to build for my server environment, for my SSR environment, and for my client environment. Those the bundles, particularly. And it's just to kind of make all that cohesive. Yeah. It'll just be TypeScript.

Tanner Lindsley [00:22:58]:
At the end of the day, what I would like to have it be is just a beat plug in itself, which kinda sounds weird. It's a it's a Vite plug in that would call into Nitro to produce many different environments and build even more Vite bundles. So but that's I think that's the the beautiful part about it is that if we can boil it down to just Vite plug ins, I think it's gonna be really powerful.

Dan Shappir [00:23:25]:
And that's basically gonna be, like, under some sort of a start monitor?

Tanner Lindsley [00:23:30]:
Yeah. Most likely. We'll probably just share internal packages privately for now, and each one of us will just export our own builders for it. So you'll still you know, you'll probably build something like, create 10 stack start Vite, will be, like, one of our packages. And you'll call that function, and it will produce all the Vite plug ins that you need to add to your build, essentially.

Dan Shappir [00:23:56]:
And They'll have those By the way, one thing that you said before, that, the 10 stack router was 90% of the way towards 10 stack start in terms of being a framework. I think Ryan Florence more or less said the same thing about, Remix and React Router. I think they even kind of merged the two projects together for that reason.

Tanner Lindsley [00:24:23]:
Yeah. I yeah. I don't I wish that maybe that had been recognized sooner so that they didn't have to go through, kind of the snip snap snip snap kind of a pattern because it's always been apparent that the router is what drives much of what you do. That's where all of the opinions are and where you're you're feeding, you know, it's calling into your code and scheduling its own things and doing its own things. So it very much is the framework. I, yeah, I don't have a whole lot to say there other than I just wish that they had maybe it it would have been better for their branding, I think, if they hadn't have, done, like, oh, it's Remix, and then they took React Router and put it into Remix. And now it's React Router and putting Remix back in there. It's very confusing.

Tanner Lindsley [00:25:19]:
It should have just been incremental from the beginning. They should have just built Remix as an add on to React router, but I I don't everybody has their reasons.

Dan Shappir [00:25:28]:
Oh, the reasons. And, also, like you said, people realize things as they built them.

Tanner Lindsley [00:25:34]:
Yeah. And, you know, I it was that was merely an idea that I had. I just wanted to build my own router, and I knew that I wanted it to be client side only and that server side features were gonna come later. I'm very, very grateful that they were willing to go guinea pig that process and probably find out the hard way that, it should've just been React router all along. So, I'm not complaining. They they have, they've done me a great favor in research and, yeah.

Dan Shappir [00:26:10]:
By the way, I'm curious. Do you think that maybe routing client side routing, I mean, should have been part of the platform in some way?

Tanner Lindsley [00:26:19]:
Which platform? Like, the web platform?

Dan Shappir [00:26:22]:
Yeah. Like, Dom APIs for client side routing beyond the the basic, history APIs? Or I

Tanner Lindsley [00:26:33]:
I don't know. I mean, it's easy to say, yeah, that would be great. But, where would those opinions come from, that would serve everyone? I don't I don't know. Because even for projects that look that look a lot alike, even for, like, like, React router and 10 stack router, like, I I took good ideas from React router. I took the loader pattern and, you know, a couple other patterns that I just thought, you know what? These guys really nailed these APIs. And then for other things, I just did things completely different.

Dan Shappir [00:27:09]:
So can you maybe talk a little bit about that? Can you elaborate a little bit about what is the loader pattern and also about some of the things that you've done differently?

Tanner Lindsley [00:27:18]:
For sure. So the loader pattern is just a really fancy way of saying, like, life cycle management for navigation. Basically, you're you click a link, and we know, hey. You're about to go to this next page. And before you even navigate, before we try and render, before we do anything about showing the next content, you have life cycle methods that will fire. This goes way, way back even to, like, knockout, and older older frameworks that were just like, oh, yeah. They're about to navigate to this new page. Here's a function that you can run before that happens and and potentially do some asynchronous work.

Tanner Lindsley [00:28:05]:
So that concept that's a core concept. And then the loader pattern is just applying that life cycle method to data loading specifically to say, before we navigate to this route, we need to make sure that we have this data. So when you hear people talk about loaders, that that's generally what they're talking about. It's just a life cycle method to ensure that data is present.

Dan Shappir [00:28:30]:
By asynchronous, by the way, in this context, you mean it's asynchronous to the operation of the browser, but it's not a synchronous to the actual navigation. I mean, you do need the data in order to display the quote, unquote new page.

Tanner Lindsley [00:28:43]:
Right. Yeah. You you might, then again, here's another reason why it doesn't really work to just have some universal web standard is some frameworks will even wait to change the URL, before, like, a month until the data is loaded. And and for me, for instance, I like, as soon as they navigate, the URL changes, synchronously. And then the side effect of rendering what the user wants to see, is asynchronous. So, yeah, there's there's lots of opinions there.

Dan Shappir [00:29:17]:
Interesting. So that's what is similar about, about what you've done in React Router. Can you talk a little bit about what is different? Because I also think that informs some of the differences between 10 stack and other frameworks.

Tanner Lindsley [00:29:31]:
Yeah. So, yeah, they they both have loaders. They both support I mean, let's not even limit it to Remix, but let's just say, like, modern routers. Kind of the expectations for all modern routers is that they have, nested routing, the ability to, like, nest, route matching segments inside of each other to do shared layouts.

Dan Shappir [00:29:54]:
So I I I apologize for interrupting you. Just to clarify, nested routing means that you click a link and you go into, let's say, call it a subpage or subresource in a sense or, like and part of the page stays the same and then part of the page changes, or is that something else and I'm explaining it wrong?

Tanner Lindsley [00:30:16]:
No. That's that's exactly right. And the it's the difference of, it's just encapsulation and reuse is what it is. You could write your entire router as a flat map to say this exact URL matches this exact component. And if you have components that share the same layout like a nav bar or a sidebar and this is back, like, with older versions of Next. JS. You would have to render that navbar and sidebar on every single page that you wanted it to be on. Right? And that has implications depending on the framework you're using that sometimes those components would unmount and remount even though they look like they're still there.

Tanner Lindsley [00:30:58]:
You know, they haven't changed. So

Dan Shappir [00:31:00]:
then lose date?

Tanner Lindsley [00:31:01]:
Yeah. Yeah. That's that's one of the things too. Yeah. There's lots of these shared things. Nested routing is is one of those things. But instead of having this flat list of URLs to components, you get to share those URL routes. So say you have, you have an admin slash admin.

Tanner Lindsley [00:31:18]:
Right? You might have a lot of subpages on that slash admin slash admin slash users or whatever. And instead of having to render, like, the admin sidebar for every single one of those subpages, you just render it once in the admin layout component. And then every single sub admin page below that will get inserted into that layout wherever you render an outlet or render children, essentially.

Dan Shappir [00:31:44]:
So you get you have this sort of a slot that where the sub pages, like, well, slotted in.

Tanner Lindsley [00:31:51]:
Yep. And that slot works for in index pages, which means, hey. We didn't match anything, so we're just on the index. And you can slot something in there, or you can slot in sub pages. Yeah. So nested routing is a big one. That's that was kind of that's that's one where React Router really nailed it. You know, Next.

Tanner Lindsley [00:32:12]:
Js didn't have that for a while, and it was really enraging. And and React Router has had that for a long time. When Next. Js finally added that, it was like, oh, wow. This is wonderful. And it's like, yeah. Why didn't you do that sooner? And that and that was a no brainer for us. It's like, yeah.

Tanner Lindsley [00:32:29]:
We're gonna support that. We're gonna do nested routes. Things like file based routing where you can, you know, create that tree using a file structure just to kind of have maintenance be nice and, have some opinions and convention around just moving quickly. Loaders, we talked about, kinda just your basic navigation APIs, being able to have links and, you know, imperative navigate calls to kinda move around your app. That all that stuff is pretty much the same. Where it starts to get different for from both Next. Js and Remix is, so TanStack router basically was re I rewrote it from the ground up with type safety, at the forefront. So every single decision that I made when I when I rewrote this router was so that we could have a % inferred type safety.

Tanner Lindsley [00:33:27]:
Essentially, the goal was I don't wanna have to write TypeScript syntax in my routing, but I want it all to be extremely type safe.

Dan Shappir [00:33:38]:
Type safe means that if I put in an invalid route, I get red squigglies. Is that what type safe means in this context?

Tanner Lindsley [00:33:45]:
Yeah. It I mean, it means a lot of things. That's one of them. And that's what I like to call that the that is the the basic level one type safety that I would expect out of a router is that, yeah, you don't let me navigate statically warn me that, hey. You're trying to navigate somewhere that doesn't exist. That's that's just the the basic bare bones. There's a lot more to it, though. I don't know how much you wanna go into that.

Tanner Lindsley [00:34:11]:
But

Dan Shappir [00:34:12]:
I I think we talked about it actually in the last time you were here, so I don't wanna go too deep because I wanna talk about the the 10 stack framework.

Tanner Lindsley [00:34:21]:
Right.

Dan Shappir [00:34:21]:
And some of the RPC work is really interesting for me.

Tanner Lindsley [00:34:24]:
Yeah. I

Dan Shappir [00:34:24]:
would love to

Tanner Lindsley [00:34:25]:
talk about that too.

Dan Shappir [00:34:26]:
So just in a few words, I just to mention it, as I recall, it's also type safety about URL parameters. So you can specify the type of a URL parameter, and and the value has to match that type.

Tanner Lindsley [00:34:39]:
Right. And that that applies to a lot of different areas of the API. So, search params is a big a big piece of TANSTACK router. All of our search parameters are validated and type safe, and have first class APIs built in to manage search parameters like you would, like, use state, essentially. Like, you're just managing state. That's that's a really big difference and something that really not many other routers, if any, that I know of have. That's a that's a big reason of why I wrote it as well. On top of that, there's there's type safety throughout all the other APIs that we have in there.

Tanner Lindsley [00:35:21]:
So there's things like route context and middleware. All of that stuff is type safe as well. There's the configuration itself, like being able to use, loader data inside of your components or use data from other routes from different files. It's all type safe. It it all works. It's all very magical. I don't know what else to say there other than you should try it because you're you're probably missing out if if you haven't tried it yet.

Dan Shappir [00:35:50]:
Let me put it this way. We are starting a new project. I I basically made it part of our standard starter kit at Sisense. So, you know, we might if it's if it's a project that needs, a full framework, like, we might debate between, let's say, Next JS or something else. But, if it's a project that's mostly going to be client side rendered, then I've made 10 stack, like, part of our standard config.

Tanner Lindsley [00:36:24]:
I would agree. Alright. So before we move on to start, there's the the one more thing I wanna mention. So, TanStack router has caching built into it, which is like a really, really lightweight version of React Query or TenStack Query built right into the router. So for very so for simple use cases, you may not even need TenStack Query. You just load the data you need in your routes, and it's managed for you there. And you have things like stale time, SWR, background refetching. It's all just built into the router.

Tanner Lindsley [00:36:59]:
So that's very important, a very a very important distinction. And, yeah, just generally managing state in the URL. If you're going to use search parameters, like, at all, if you're gonna use search parameters, you should use transact routers.

Dan Shappir [00:37:15]:
Oh, I I love it when, as many as as possible configuration values are in the URL. So for example, I use, Grafana. I've even spoken about it here on on, JavaScript Jabber. And one of the things I love about Grafana is that most of their configurations are URL parameters, which makes it very easy to share graphs.

Tanner Lindsley [00:37:37]:
Yep. More state should be in the URL. Not all state, but more of our state should be in the URL. And as soon as you wanna start doing that, you'll realize that the tools you have at your disposal are not that great. So come use 10 stack router, and you'll be much happier.

Dan Shappir [00:37:57]:
Okay then. 10 stack the framework. 10 stack start.

Tanner Lindsley [00:38:01]:
10 stack start. Yep. So I wasn't planning on building it initially.

Dan Shappir [00:38:11]:
You know what? I'm I'm not surprised. I mean, one person kind of taking on the whole Next. Js ecosystem in a sense?

Tanner Lindsley [00:38:21]:
It's a lot.

Dan Shappir [00:38:22]:
It's a lot.

Tanner Lindsley [00:38:23]:
It it is a lot. I was I I wasn't planning on building it initially because, one, I I didn't need it, personally, since building a lot of SPAs. But I'll be honest. I I nerd sniped myself on this one really, really bad. So I I had this idea, about a year basically, a year ago. And I was like, you know what? I wonder if I could rewrite tanstack.com and migrate it from Remix to just use tanstack router with a custom SSR setup. And I did that. It was really hard.

Tanner Lindsley [00:39:02]:
And I was like, man, that was really

Dan Shappir [00:39:04]:
By the way, as as an aside, when I worked at Wix, I used to work at Wix up to about five years ago. Time flies. Four or five. Yeah. Four four years ago, five years ago, something like that. Wix actually we when I was there, we built our own SSR, framework platform. And we did it for first of all, because none existed at the time. We we predated Next.

Dan Shappir [00:39:29]:
Js, I think. Also, the use case was very different. I mean, you know, hosting millions of websites on on one platform is is a different, you know, use case. So so I I know for a fact how difficult that can be.

Tanner Lindsley [00:39:45]:
It was

Dan Shappir [00:39:46]:
very challenging to do it efficiently.

Tanner Lindsley [00:39:49]:
It's enraging a lot of the time, to be honest, because, I mean, the first thing you're gonna realize is now you have hydration problems, anytime you're trying to do SSR with React. You just have to get really strict about hydration. But, yeah, it was it was difficult. And that's kind of what started TanStack start, because I was like, okay. I just did this manually, and it really, really sucked. How can I make that better? And I started talking to Ryan Carniato, and I was like, hey. What are you using for solid start? And he said, well, I'm using Vinci to kinda put all this together and make my life a little easier. And I tried VINCI out, and I just kinda again, just built it manually, but using VINCI and it made my life easier.

Tanner Lindsley [00:40:30]:
And so you could see it's sort of snowball at that point. Then I decided, you know what? This is this is gonna be pretty cool. And I showed it to some people that I trusted, and and they said, this is amazing, but I really wish it had server, like like, server loaders. How do I only do something on the server? And because in Remix, you have, you know, server side loaders. And even in Next. Js pages router, you have get server side props and and stuff like that. And so I was like, okay. So it's not really complete yet.

Tanner Lindsley [00:41:05]:
How can I how can I make this better? And that's when I started diving into server functions, and, initially, those were implemented with VINCI. But designing a proper API around server function RPCs has been, like, my last six months of work.

Dan Shappir [00:41:27]:
Very talk a little bit about RPC because, apparently, it's a subject that's close to your heart, and I know for a fact that it's close to mine. As I mentioned, we even had an episode about it. Can you talk a little bit about, first of all, about what is RPC?

Tanner Lindsley [00:41:44]:
Yeah. Pretty sure it stands for remote procedure call. Right? Am I am I wrong?

Dan Shappir [00:41:50]:
No. You're you're absolutely correct. And by the way, I used RPCs, by the way, as an aside, back in the early nineties. Yeah. Nothing nothing to do with web technologies. Yeah. Things like Korba or DCOM.

Tanner Lindsley [00:42:03]:
Mhmm. Yeah. They have a they have a really, like, rich history in in computer programming, and, I've read a little bit about that. Ryan has sent me Ryan Carniato sent me some stuff about them as well, and I just I I love when we can, like, find old tech and, you know, make it feel new and great. But this is one of those things where it's like, yeah, we've been doing this for a really long time. But the idea behind the RPC is that, you know, you you get to, you get to create this function, in a very generic sense talking about RPCs, this this function that can be called remotely. And And when it's called remotely, it has, you know, an underlying protocol implementation and and messaging implementation that sends those messages back and forth. But it creates a very, like, a very opaque interaction where you can just say, I need to call this function.

Tanner Lindsley [00:43:03]:
It may happen on your machine or it may happen on another machine. Right? But it's a remote procedure call. It's gonna happen remotely. And it it feels very different than calling into, say, a REST API or GraphQL or something like that.

Dan Shappir [00:43:20]:
Well, yes and no.

Tanner Lindsley [00:43:21]:
Because Similarities and differences. Yeah.

Dan Shappir [00:43:23]:
Yeah. Because putting aside yeah. Putting aside GraphQL for a second.

Tanner Lindsley [00:43:28]:
Yeah.

Dan Shappir [00:43:28]:
If we're talking about RESTful APIs, RESTful APIs, to some extent, you know, they're request response, which is the basic prerequisite for something that looks like a a function. Yeah. That you you send a message and you wait until you get a response Yeah. Basically.

Tanner Lindsley [00:43:46]:
Yeah. And and, you know, GraphQL even has a little bit of RPC vibes in it as well, where you you kind of you can you can and do kind of create these functions that you that you call through the GraphQL, like syntax and protocol. Right? So RPC is kind of in a lot of different things, and and we even kind of, implicitly create RPCs in rest environments all the time as well. You know, you have a rest API, and you just kinda need this one off, like, hey, you know, slash generate whatever, and and you call it, and it's gonna do something, and it's gonna come back. I think in the modern in our modern definition of RPCs though, I think a lot of it comes down to how you compose that logic. Right? Because, generally, when we're talking about, GraphQL procedures and functions and and HTTP like REST APIs, these are APIs that you you kinda have to design in separate places. You say, okay. I'm I'm building an API.

Tanner Lindsley [00:44:52]:
I'm building a GraphQL endpoint, and I'm going to build this function in in this place. And then in a completely separate location, either whether it's in your monorepo or a completely separate application, you're then constructing a way to call into that function through, you know, URL schema or GraphQL client that's been generated or something like that. So you creating that function and and, authoring that function and calling it are are seemingly very separate places. With an RPC, at least in in our model Often,

Dan Shappir [00:45:30]:
by the way, implemented by separate people. It might be the back end team that's creating the, the restful endpoints and then the front end teams that are putting some sort of facade on top of them.

Tanner Lindsley [00:45:42]:
And possibly in separate languages too. Right?

Dan Shappir [00:45:44]:
Usually, often in separate languages.

Tanner Lindsley [00:45:45]:
Yeah. Often. And so RPCs, at least the modern way we think about RPCs is more, it's more of like an integrated approach to creating that messaging layer. So for anybody listening who who could imagine you I'm just gonna tell you how we do it in 10 stack start. But, basically, in any file you want in your application, you can call a function called create server function. And you pass that call a function. And everything inside of that function is going to only run on the server.

Dan Shappir [00:46:25]:
Even only exist on the server?

Tanner Lindsley [00:46:27]:
It's only again, yeah, it's only going to exist on the server. So it like, when we bundle your application, we literally take that function that's inside of there, and we strip it away from the client. And what we do is we replace it with a fetch call. It's a fetch to, to, you know, an HTTP endpoint

Dan Shappir [00:46:49]:
with Used to be called the stub in the old RPC day.

Tanner Lindsley [00:46:53]:
Yeah. Stub. Right? We you stub it, and we implement that stub with with with fetch and with an HTTP endpoint. And then we extract that function into the server bundle. And on the server, we're listening to that same endpoint for that stub, for that fetch call. And when we receive that call, we take the request and we pipe it through to the function that we extracted. And so they they execute in completely different environments, but you author them in a full stack way. So, I mean, these functions can live right next to a React component that renders on the client, and they could even live next to things that are client only in the same file.

Dan Shappir [00:47:38]:
I think that's kind of the key. I think that, three things, I think, enabled RPC for the modern web. Because RPCs existed on the back end, like, forever. So, you know, you obviously I I mentioned the old technologies like CORBA and DECOM. Now you have gRPC. So all this stuff on the back end is is always been there. On on the web, I think three things that happened in recent years, let's call it this way, kind of enabled it. So one was the the full stack frameworks.

Dan Shappir [00:48:11]:
Yep. Because you you needed to be able to write code that builds or compiles to both sides for this mechanism to be truly seamless, and you kind of said it. It's it's intended for the full stack scenario. Yeah. So that's number one. Another one is TypeScript. Without typing, this whole thing would have been moot because you need to be able to specify the types of parameters that you're sending over the wire. Now you could have done it explicitly using something that kind of looks like Zod or something, but it would have been really uncomfortable, or or, you know, the old component props that we used to have in React.

Dan Shappir [00:48:52]:
It would have been really uncomfortable to do it that way. And the third thing that, in my opinion, and I wonder if you agree, that kind of enabled it are is a wait, a sync await. The fact that you can call a function and have it execute asynchronously, but with the function call semantics.

Tanner Lindsley [00:49:14]:
Yeah. I I don't know about the third. I feel like it definitely helps. It it definitely helps. We could have done it with callback functions. That wouldn't have been fun.

Dan Shappir [00:49:26]:
Yeah. It would have been fun, and it would have broken the function call semantics. I mean, it

Tanner Lindsley [00:49:31]:
Yeah.

Dan Shappir [00:49:32]:
One of the big things about RPC is that it feels like a function call. And Yeah. And when it doesn't, then then you're missing out on most of the fun.

Tanner Lindsley [00:49:42]:
Yeah. I I would agree. It it definitely async await elevates the experience to more of the traditional RPC feel. That definitely.

Dan Shappir [00:49:51]:
But how do you do that in React client side? I mean, you can't really do a sync await in in in client side React.

Tanner Lindsley [00:49:58]:
No. I mean, they would like to make you think that you can with the new use API. But, I mean, it's not in it's not really intended for, like, end user usage. So, and, again, that kind of falls back to, like that's why I built Handstack query is because React lacked and, honestly, to this day, still lacks a really well vetted, good client side, asynchronous primitive. And maybe they don't add it because React Query is there and it's good enough, or they don't or they just decided to skip it. But, really, if you ask somebody today from from React Purist land or Coreland, they'll say, oh, well, you know, you're just supposed to use, server components for data fetching and and just pass promises, and then you call the user or whatever. To that, I say, that's making big assumptions about the way you're authoring your application. So yeah.

Dan Shappir [00:51:03]:
Well, to be fair, it's part of their their vision of the, how do they call it, the unidirectional data flow that, RPC kinda kinda somewhat breaks that in a sense. Because with the the unidirectional data flow model, you've got the data flowing down as props, and you've got interactions flowing up as, you know, let's say, server actions. I don't know. Do they still call it server actions, or did they also call it server functions now?

Tanner Lindsley [00:51:38]:
Yeah. They call it server functions, which is kind of annoying, but that's fine.

Dan Shappir [00:51:42]:
Yeah. It's it's it's functions that are not supposed to return a value, though.

Tanner Lindsley [00:51:48]:
Yeah. And see, that's where that's where things differ for me. I I don't really think it breaks the React methodology, and most of that just comes down to how you're handling the responses, in my opinion. But, you know, for RPCs that are just aren't doing anything, I mean, look at the way Next. Js handles server functions right now. You call a server function, and and they basically just invalidate everything. They call they call back into the root, on the server, and they can rerender your whole app. Now there's ways

Dan Shappir [00:52:22]:
You need directional data flow. The the events flow bubble up. The data flows down.

Tanner Lindsley [00:52:28]:
It's just really not great for performance, though, especially the way the React is even designed. It it's it's kinda sucks to rerender your entire application from the top down.

Dan Shappir [00:52:40]:
Let's put it this way. It's not surprising that you created React Query rather than they.

Tanner Lindsley [00:52:46]:
Yeah. I know. I I agree. Like, I I really like React, and I like the syntax. I like the framework. It's it's really wonderful. If I had if I had a magic wand that I could wave, it would be that, that we just use Solid, but that's not gonna happen. So, for now, you know, I I have to ride on the on the shoulders of this giant that is React.

Tanner Lindsley [00:53:12]:
And that's fine, because it's it's really good and it's good enough, and and, and it's decent to work in.

Dan Shappir [00:53:20]:
And nobody got fired for using React.

Tanner Lindsley [00:53:23]:
No. Exactly. But, you know, it kinda goes back to the way that we're trying to build things with TANstack libraries is that it shouldn't matter really where you go. We just wanna we just wanna build great core functionality and bring it to all the frameworks. And, yeah, I I I worry a little bit about React's future with pushing server components so much, because it's a wonderful technology that is kind of derailing a lot of people. And from where I'm standing, there's it's very confusing for a lot of people. It's very difficult to implement as a framework, and it comes with a lot of new rules and overhead that just don't really apply to I'm gonna call it the more traditional way of building an SSR application that's just isomorphic and fully hydrated.

Dan Shappir [00:54:16]:
So So I'll derail us a little bit because I do wanna talk a little bit about that. From what so I've been looking at some statistics about, React usage and and meta framework usage. For those who don't know, more people are using React than all the other view view frameworks put together. So React is number one, Vue is number two, but Vue is less than half of React, and everything else is less than the remaining part.

Steve Edwards [00:54:44]:
Those stats are wrong. I know it. I can feel it.

Dan Shappir [00:54:48]:
And and in React land, approximately almost 20% are using Next. Js, and the rest are not. They're not using any meta framework. But if you look at new websites, it seems that almost all of them are being built using Next. Js. So any project there's a good chance that any project older than two or three years that started two or three years ago is probably not using Next. Js and may never use Next. Js.

Dan Shappir [00:55:18]:
But any project that's being started right now, there's a good chance that they're using Next. Js.

Tanner Lindsley [00:55:24]:
And it's a fair assumption.

Dan Shappir [00:55:26]:
The interesting question though, when they're using Next. Js, are they also using server components? And that I have no way to know. And I'm kind of curious about that. Like, what is the buy in for server components?

Tanner Lindsley [00:55:40]:
I don't know if it's easy to know the buy in. I mean, I we could we could go back and look. I've done tons of polls. I mean, it's obviously biased off of my audience. But I've done a lot of polls on Twitter about people how people feel about server components and Next. Js and and if they wanna use them or not, which framework they would use. And for the most part, what I've the conclusion that I've come to is that there are a lot of people coming into Next. Js who are who are using server components just because that is the happy path that they have designed for Next.

Tanner Lindsley [00:56:17]:
Js.

Dan Shappir [00:56:17]:
It's also the default. Unless you put in use client, it's it's a server component.

Tanner Lindsley [00:56:23]:
Yeah. And for me, it's it's not interesting for me, personally. Many, if not, almost all of the apps that I've ever built, I don't know if they would really directly benefit from from the capabilities of server components at this time. I mean, yes, they could benefit in terms of some bundle size, but the trade offs for me just are not worth it. One, I don't wanna have to reason about this new mental model of, you know, interweaving client and server components almost at every level of the component tree just to get, you know, trade offs that don't matter for me or really won't matter much for my users at this point.

Dan Shappir [00:57:13]:
By the way, I I'm going to interrupt because I need to I think I always like to give a bit more context to our listeners. So first of all, we had, two episodes with, Dan Abramov and Joe Savona talking about server components. So if anybody's really interesting in the nitty gritty of what they are, I highly recommend listening to those episodes. They were excellent. The key aspect about, server components is that they are components that only run on the server versus client components which run which can run both on the client and on the server, which is Yeah. An interesting

Tanner Lindsley [00:57:55]:
I'm even going to extend that to say that server components have the worst name ever. They should not be called server components. They should be called, like, static components or serializable JS

Dan Shappir [00:58:08]:
Server only components, maybe?

Tanner Lindsley [00:58:10]:
I mean, because you can technically generate server components at build time too, at bundle time. Really really all it is is you're just prerendering a component and producing, this output that is, like, stringified JSX. And then you're shipping that to the client from either the static build or dynamically during from the server, during run time. And then you're you're rendering that JSX stringified version. You're turning that into something you can

Dan Shappir [00:58:44]:
I prefer to to think about it as serialized virtual DOM?

Tanner Lindsley [00:58:49]:
Exactly what it is. It's serialized virtual DOM. And when you talk about it like that, it becomes much easier to reason about what you would actually gain from using them, which for me, out of the box, the things that I think are what are that are interesting about server components is that, you could you could import and render and do a lot of complex work with using really large bundles and libraries on the back end that produce a really small, JSX output. And you would only have to ship that to the client. And that's something that's that actually is very useful, thinking about it from that way. And that's something where, like, it it would be useful for, like, meta. You know? The that's the whole reason they built Relay, and the ability for Relay to send components down in chunks with certain GraphQL responses was so that they could only send down the code that they needed to render the thing at that exact moment. So it's very much like the next generation of of that idea, even though Meta is not using it, which is another topic.

Tanner Lindsley [01:00:02]:
But that's this is the next generation of that idea. It's only sending the code that's needed to run on the client to generate to produce that thing. It had it doesn't really have a whole lot to do with data loading other than you can load the data on the server and then produce the HTML on the server and send that HTML down to the client. So it's very much like using a traditional rendering framework, from, like, old back end days. You you produce the HTML. I'm air quoting here, but it's JSX, and you ship that down to the user instead of having to ship all of your data fetching logic and your rendering logic down to the client.

Dan Shappir [01:00:43]:
So does 10 stack actually support server components, or do you solely rely on server functions?

Tanner Lindsley [01:00:52]:
I will support them. So I I've actually written, all the code to proof of concept this out. It works. We're gonna support them in a very safe way. I can go into depth. And actually, I think it's worth talking about that. So, server components people look at server components through the lens of Next. Js right now because that's the only thing that we know.

Dan Shappir [01:01:16]:
And It's the only implementation, I think.

Tanner Lindsley [01:01:19]:
Yeah. Next. Js, their their entire router, like, the entire experience from the root of the of the application down is a large server component, essentially. It starts at the root, and it starts at the on the server, and it interweaves between client and server going all the way down. That has kind of skewed the way that people look at server components, I think. They they think that that's the only way that it can happen, and that all of their routing files and their layout files and all these other things are going to be written in this, like, use server, use client kind of hand off thinking about these rules. Well, similar to so if you caught Next JS comp this last year, Ryan Florence, they they demoed how it could be different. And it aligns it almost aligns exactly with how I was thinking about them as well is that, server components are really just another form of asynchronous state or data that you're getting from an API endpoint or some embedded static data that you have in your application.

Tanner Lindsley [01:02:32]:
And so, really, it can happen at network IO boundaries. Next. Js has those built into the entire system, so it's just kind of that's just what's happening all the time. But for 10 stack start, the way that we're gonna do it is if you want to use a server component, you simply return JSX or React in a server function, in an RPC.

Dan Shappir [01:02:58]:
That's I felt that that was where you were going.

Tanner Lindsley [01:03:01]:
That's it. And, you know, that fits right in with Remix too because so they don't really have RPCs, but they do have loaders, which is kind of like their hard coded, rest their kind of rest flavor of an RPC. Right? And they're doing the same thing. It's just you just return JavaScript or you just return React and JSX inside of a loader. It so server functions are really going to be the the place where you can use server.

Dan Shappir [01:03:30]:
So a a question about that. So first of all, it seems kind of almost like you're you might be returning a string and then injecting it if you're using, what's it called, unsafe, in dangerously unsafe insert HTML or whatever.

Tanner Lindsley [01:03:46]:
A little bit.

Dan Shappir [01:03:48]:
But, the question that I have about that, what prevents that server function from returning, JSX or virtual DOM that the client doesn't know what to do with, like using components that don't exist or whatever?

Tanner Lindsley [01:04:05]:
Lot of that just comes down to how it gets bundled. So the real feature if if you ever listen to Andrew from the React core team, is it Andrew Clark? I can't I think he has his name. Right? Andrew?

Dan Shappir [01:04:16]:
Yeah. I think so.

Tanner Lindsley [01:04:17]:
Yeah. And I like the way Andrew talks about it. He says the real the real feature of server components is not a framework feature. It's a It's a bundler. It's a bundler feature. And it allows you to basically serialize that component, everything that ran on the server is going to turn into JSX markup that's right there in that representation. And everything that can't run on the server that needs to run on the client is referenced through a manifest. And it gets a little tricky with how that works, but that manifest is just a mapping of client component references that come that can come down through server components to the actual modules and bundler modules that it can go out and grab if it needs to grab them.

Tanner Lindsley [01:05:19]:
So when you render something on the server, it comes down with this responses as here's all this server function, or the server component markup, and there might be some client components in there. And if they're already loaded into your app on the client, then they'll just render. And if they're not, then they will suspend while they go and pull that client side bundle chunk that they need to render, and then they will finally render.

Dan Shappir [01:05:44]:
So a key difference, it seems to me, and, again, correct me if I'm wrong, between the Next. Js way and your approach is that with Next. Js, the root is, like you said, a server component. Whereas in your case, the root is a quote, unquote client component even though it actually might run on the server.

Tanner Lindsley [01:06:10]:
Yeah. I think that's a good distinction. Is that, with Next. Js, everything's gonna be server first all the time no matter what?

Dan Shappir [01:06:18]:
Well, for sale.

Tanner Lindsley [01:06:20]:
Right. Of course. And then with ten sec start, even down to the way that the APIs are designed, everything's written to be isomorphic first. So if you don't do anything inside of a server function, what you write is just going to happen during SSR, and it's gonna happen on the client.

Dan Shappir [01:06:39]:
You know you know what I really like about your approach now that I'm thinking about it? So I I have this presentation, this talk that I gave about different ways to overcome the cost of hydration, the performance cost of hydration. And I show the different ways, and I for each such method, like, there's something like six or seven approaches. And for each one of them, I give both the upsides and the downsides of each approach. And one of the approaches that I mentioned towards the end are server components. And one of the downside of server components that I presented in my talk is that they require you to basically rearchitect your application. Yes, sir. Take an existing application and just throw in server components into it. You need to rethink your entire architecture.

Dan Shappir [01:07:26]:
You need to learn this this new tech not even new technology, but new approach and then architect your application accordingly. And what I really like sorry. Go on. Please.

Tanner Lindsley [01:07:37]:
I was gonna say I I agree, but I think there's some nuance there where with server but with server components, you can migrate incrementally, but you have to do it from the top down. You have to slowly move the server bound. So at the top, if you just say, I wanna render my whole app as a client component, you can do that. In Next. Js, you can even do that, I think. I hope. But you can render your entire app as a client component.

Dan Shappir [01:08:03]:
Well, you can have a really thin server component that basically just renders your

Tanner Lindsley [01:08:09]:
Right. And and the migration path is to slowly push that server boundary down through your component structure as far down as you can. That's the incremental migration strategy. And I don't like doing refactors from the root down. I in fact, I like doing my my my leaf node up.

Dan Shappir [01:08:28]:
Yeah. But you're absolutely correct. But if you if you basically do that, then you've not again, my presentation was in the context of of improving the the reducing the cost of hydration. And if you just do that, you basically have not eliminate did not reduce the cost of hydration at all. And Slowly. You're right. Yeah. Slowly.

Dan Shappir [01:08:50]:
But all it means is that you've slowly rearchitected your application.

Tanner Lindsley [01:08:54]:
Exactly.

Dan Shappir [01:08:56]:
But, and what I like about your approach, it seems to me, is that you can get these this value without rearchitecting your application. You want to you you can you think you have some components somewhere in the tree that could benefit from being a server rendered component because, I don't know, it uses some date, date and time functionality that would require you to download moment JS. Well, you just turn that into a server function that returns JSX.

Tanner Lindsley [01:09:28]:
Yeah. And, you know, you you bring up you you brought a cool thought into my head is that, talking about refactoring. Right? Let's imagine a lot a lot of people are on create react app. At the very least, it's it's not too difficult to get into Vite, at the very least. Just saying, hey. I wanna use Vite. But to be able to you what would it take for somebody at that point then to use server components? Right? Telling them that they would need to adopt an entirely new framework, is a big pill to swallow if they just wanna consume this new server component, you know, pattern, this new technology. It's a hard pill for them to swallow, and I would wager that a lot of people wouldn't do that.

Tanner Lindsley [01:10:13]:
But what if you could say, hey. All you need to do is just get off of create react app, which you should do anyway. Get into Vite. Right? All you need to do is get into Vite. And if you can do that, we can give you a Vite plug in that will let you call server functions and then let you return server components. And then you can just render those server components even in without refactoring really any other part of your application. Even if you're still using React router version four or five, you could still make an API call using whatever you want using React query even and and call into a server function, get back a server component, and render it. You would just need to migrate to Vite and be using React 19.

Tanner Lindsley [01:11:01]:
So that that's probably the the path of least resistance if, like, you're if you just wanna get your hands on server components, that's the path of least resistance that I'm trying to make possible. So I know I said that start is 90% router. That's if you're consuming the whole the whole framework. But, really, at the end of the day, what start is is just the ability to do SSR if you want and server functions. That's really

Dan Shappir [01:11:32]:
I I love that. And and, by the way, I told Dan Abramov when he was on the show that the the because, you know, they were they were getting huge pushback against React server components. And and, you know, and and I I know that it it the React team got a lot of pushback that they weren't use used to get. Let's put it this way. They were always they the last time they got such pushback from the community was, I think, more or less when they introduced JSX. Yeah. And and they had hoped that the reaction would have been similar to the reaction that they got when they introduced hooks, which were really quickly adopted by the community. Yeah.

Dan Shappir [01:12:21]:
And the key difference was that hooks, you could basically take it or leave it. You could use it on a per component basis. So when you could take an existing React application and decide that I'm not gonna touch any of the existing code

Tanner Lindsley [01:12:36]:
Yeah.

Dan Shappir [01:12:37]:
But new new components that I'm adding would use hooks and everything would just work.

Tanner Lindsley [01:12:43]:
And it didn't require an architectural overhaul.

Dan Shappir [01:12:46]:
Exactly. It was at the component level. And if you can do that for React server components, that would be amazing

Tanner Lindsley [01:12:56]:
in my opinion. It it's fine that it requires an architectural overhaul. It's gonna require something. If it involves a server, you're gonna have to do something architecturally. I just think that rolling up that architecture change into, hey. You have to adopt this entirely new framework. That's a hard pill to swallow. And, you know, that's both Next.

Tanner Lindsley [01:13:18]:
Js is in, and I think React Router's hope is that, hey. Just buy into our router, and we'll take care of the rest. Right? And, unfortunately, for me, that's that's the that's an even harder pill for me to swallow is because I don't really like the routers that I see out there. I don't like Next JS's router, and and I moderately enjoy React router, but it it lacks a lot of things for me. I'm definitely not happy using it anymore. And so knowing that other people are going to have to make that same sacrifice to say, oh, yes. I have to buy into Next. Js, all of it, or I have to buy into React router at least if I wanna get on a path to use these latest React features.

Tanner Lindsley [01:14:04]:
That's not something that I wanna have to do even myself, and I don't wanna have to make other people do that as well. So I'm trying my hardest to build start in a way that can be consumed without having to just turn your entire application upside down. There's always gonna be a little bit of buy in. You know? You have to buy in a beat. You're gonna have to buy into, servers in general. Like, I hope your company lets you run server code because a lot of a lot of front end devs are not allowed to provision servers. So

Dan Shappir [01:14:37]:
I'll put it this way. When while not so long ago, I was interviewing at a couple of companies. And and I was interviewing at a at a senior technical rank, so I one of the things that I was looking at during the interview process was actually the technologies and architectures that they were using for the front end. And what I saw is that all of them were using React, and almost none of them were was using SSR or any other and and a consequently, any meta framework. And if you could provide the ability for such companies to start leveraging the benefits of React on the server side in a way that does not disrupt their existing architecture and their existing code base, that that's a huge benefit.

Tanner Lindsley [01:15:35]:
Yeah. I agree. And, you know, I came from that world where, like, I I wasn't gonna start even on my small team, I didn't wanna have to provision servers. My team, we we had our APIs written in a different language, you know, distributed through very different means. Like, I wasn't gonna touch server code anytime soon. I mean, a lot a lot of very successful applications and enterprise companies, like, to even think about, oh, yeah. Our front end developers are gonna start running server side code is a big leap, because just the way that, you know, APIs need to scale. They get their own teams.

Tanner Lindsley [01:16:13]:
They turn into different languages. I just think that there's so many more benefits that we should be looking to give front end developers right now who work on these kinds of applications and large enterprise applications who, you know, so many of them won't even be able to touch server components until their company finally decides years from now to let them run server side code. So, yes, I'm I'm excited about, you know, the server, and I'm trying to to go down that path as much as I can, but I'm still so heavily invested in the client side tooling space. I think query has been phenomenal for the industry. I think table is great. I think TanStack router is still the most underrated part of what I'm building, because if you're if you're a client if you're a client side application and you're gonna stay a client side application, I really don't understand why you would even consider using Next. Js or React Router at this point. There there's just I if you're if you're questioning that, then you should DM me, and I'll talk to you about it.

Tanner Lindsley [01:17:26]:
Because I built Tansack router for enterprise routing use cases, and it truly shines. So, yeah, those in that in that part of our industry is very underrepresented and soft spoken, especially on places like social media and Twitter. There's very, very big successful applications being maintained by very smart people that we never hear from on Twitter or x or anywhere like that. So I know they exist, though. I talked to them offline. I talked to them in DMs, and I'm I'm trying to represent them as well.

Steve Edwards [01:18:02]:
Oh, for sure. Dan, we need to get wrapped up here because it's been a long time here. So let's do some last words from both you guys, and then we'll move on to pics.

Dan Shappir [01:18:10]:
No. One thing that I wanted to to talk about, but I don't think we have time. So we we can do it, say, in some future time is, but, like, like, some of the downsides of RPCs that existed, again, way back in the nineties. RPCs, for example, tended to be chatty protocols. They also attended to introduce a lot of endpoints and generally introduce various maintenance issues. But I I don't think we really have time to delve into this this time. So maybe we should bring you on to talk about RPC in-depth sometime.

Tanner Lindsley [01:18:47]:
I can give you a thirty second teaser on that if you want. I I think that there is some there's some chattiness that can happen, but, I think if you're using them for your actual source of truth on full stack stuff, it could there are some interesting things there, like, actually building full stack APIs. But if you're just using them to then, you know, do secure things on the server that communicate externally with your other API or back end, I I mean, I think that some of that chattiness, can be justified. And then, also, there's there's fun things about server functions that we didn't even get to talk about, but I we've added validation to our server function strategies. We've added, type safe middleware to our server functions, which is very, very powerful where you can wrap up client side and server side transactions through server functions and do really, really cool things. And then also being able to do public RPCs in the future is something that we're considering. So once you've written an RPC in TanStack, the only thing keeping it from becoming a a fully blown rest, like HTTP endpoint that's public, is just supplying a path, a static path. So we're we're considering allowing people to even build public rest endpoints like static paths that they'll be able to use, not just in their application side by side as an RPC, but even call into with, say, an RPC client that's generated for their React Native app or for a bunch of different projects, and kind of create some tooling around that.

Dan Shappir [01:20:27]:
You know what would be awesome? If we brought both you and Ryan on the show to talk about RPCs. I think that would be amazing.

Tanner Lindsley [01:20:34]:
Anytime you get me and Ryan together, it's gonna be a party. So I would love to I would love to come on with Ryan.

Dan Shappir [01:20:40]:
Okay. Ryan is a friend. I'll I'll I'll try to organize it.

Tanner Lindsley [01:20:44]:
K.

Steve Edwards [01:20:44]:
Sounds good. Well, thanks. Thanks, Tanner. If you wanna learn more about Canstack, canstack dot com is the place to go, docs and demos and all kinds of goodies. So with that, we'll move on to PIX. PIX is the part of the show where we get to talk about things that we wanna talk about that maybe aren't tech related, could be. Let's see. AJ, you've been quiet.

Steve Edwards [01:21:07]:
What do you got for us for PIX?

AJ O'Neil [01:21:11]:
So I was looking for something to play. Just I was in a video game mood, and I was very, very kinda disheartened that a lot of the games I really loved as a kid, they have not been recreated in a similar form like Goldeneye. I figured there's gotta be something like Goldeneye. But there aren't really any other games other than Goldeneye and Perfect Dark where you sneak around and assassinate people through a maze to accomplish some goal. And I ended up trying out something new. I'd I've never even heard of the genre of four x, but it's explore, extend, exploit, extinguish, something like that. It's like the Microsoft strategy.

Steve Edwards [01:21:54]:
That's what

AJ O'Neil [01:21:55]:
I was gonna say.

Steve Edwards [01:21:55]:
It sounds like Microsoft.

AJ O'Neil [01:21:58]:
Yeah. So civilization six is kind of like Age of Empires or Command and Conquer mixed with SimCity. And it is heavily, heavily, heavily discounted right now because Sim, or Civilization seven is about to come out. And so for all the different platforms for Nintendo Switch, you can check on gg.deals, g g as in good game, g g Deals or dekudeals.com, deku as in Deku Tree. And you can get either the premium package or just the base game for $2.03, $45. And it's, my warning is that it's addictive. If you have an addictive personality, if you like things where you have to min max and strategize to figure out the best route, it's every every time you play the game, the map is randomized and but you have a civilization that has certain benefits, like what it can build earlier or whatever. And you you get couple hours into the game, and then you're past or, I guess, past you you get into your next age and new things unlock, and you have other civilizations on the board.

AJ O'Neil [01:23:16]:
It's like it's also kinda like risk and that there's different civilizations on the board, and you're trying to basically gather more land before they do and and amass more points to some rule.

Dan Shappir [01:23:27]:
I'm I'm looking at the Gigi deals page right now, and they're selling them for under $3. Yeah. So It's a 95% discount for the next

AJ O'Neil [01:23:39]:
four weeks. My one caution would be don't buy it for Mac. Because

Dan Shappir [01:23:44]:
Why?

AJ O'Neil [01:23:45]:
They after I got it for Switch, I also got it for Mac. Basically, my it it doesn't work. It doesn't work. The game opens. It crashes. If you can keep it open long enough, you can't you can't move it from one monitor to another. All of the key bindings are Windows key bindings, like, with numpad and f f six and all that sort of stuff. You can change those key bindings, of course.

AJ O'Neil [01:24:11]:
But my assumption is that they never tested it on Mac whatsoever, that they use some sort of framework that allows it to compile on different operating systems. And they just hit the compile button. And they said, oh, the Mac build's finished. Okay. Put up the digital code. But I don't think that anyone I don't think any of the developers of the game have ever tested it on a Mac. And if you look at any of the reviews that are one star reviews, they're all mentioning Mac. It it doesn't run on Mac.

AJ O'Neil [01:24:41]:
It doesn't actually like, it will install. It will open. You can click two or three buttons, and then it crashes. So don't do that.

Dan Shappir [01:24:50]:
So you're basically saying if you've got a computer at home, get it for a PC, not for a Mac.

AJ O'Neil [01:24:57]:
Yeah. I I might even run on Linux. I don't remember if that was on there, but, yeah, Windows or Xbox or PlayStation. You know, the consoles are good because Microsoft and Nintendo and Sony will rip you a new one if your game just crashes when you start it, whereas Steam doesn't care. Steam's like, oh, game just crashes when you start it. Contact the publisher. We don't care. We just take the money.

Steve Edwards [01:25:22]:
Alrighty.

AJ O'Neil [01:25:23]:
That's my one thing.

Steve Edwards [01:25:24]:
Thank you. Dan, you got any picks for us?

Dan Shappir [01:25:27]:
Yeah. Not at all.

Tanner Lindsley [01:25:29]:
Yep. I, I have a I have a hard stop right now, and I don't I don't have any picks. So I'd I'd be happy to do my sign off, but I gotta run.

Steve Edwards [01:25:38]:
Okay. Thanks for coming, Tanner.

Tanner Lindsley [01:25:39]:
Thanks, guys, for having me. I do wanna come back on and talk about server stuff with Ryan Carniato, so let me know what you're

Dan Shappir [01:25:45]:
talking about. Make sure to organize that. Now you've given me extra incentive. That would be so awesome.

AJ O'Neil [01:25:50]:
I Cool.

Tanner Lindsley [01:25:52]:
Thank you so much.

Steve Edwards [01:25:53]:
Thank you.

Tanner Lindsley [01:25:54]:
Hey, Dan. Steve. Good to see you guys.

Dan Shappir [01:25:56]:
Awesome. Thank you very much. Again soon. Bye. So my pick is I've I've been an Anthony Jeselnik fan for a long time. You guys know who he is? He's like this edgy, stand up comic. And, I really have enjoyed this material over the years. We even had this one really pleasant surprise where when we went to this, stand up club in, LA, and he made a surprise appearance there to try out new stuff, new material.

Dan Shappir [01:26:31]:
So that was really awesome. And I really loved his shows that he did in the past, thoughts and prayers and, fire in the maternity ward. And now he's recently come out with a new show called Bones and All, and it's okay. I watched it, and I enjoyed it, but it wasn't as good as his old shows. So, if you're an Anthony Jeselnik fan and you haven't watched it yet, you know, you should, but don't expect it to be as great as his pre as his past stuff. I don't know why. That's that's just my take on it. But, anyway, that would be my pick for today.

Steve Edwards [01:27:17]:
Alrighty. I will go last year since I'm the my picks are always the high point. First pick is a reference to something that Tanner said during the, when he was talking earlier, and he talked about how we got nerd sniped. Reminds me of one of my favorite x k c d cartoons called nerd sniping. It's number three five six. So, considering where things are right now, it's a very early early one. And, it's called Nerd Sniping, and it's it describes it perfectly, makes me laugh every time I I read this cartoon. But, I go check it out.

Steve Edwards [01:27:58]:
Nerds, x k CD number three five six. And for the dad jokes of the week, it's been a while. So, so I I have a plethora to choose from. The other day, I was talking to a friend of mine, and I told him, hey. I took my wife to The Caribbean last month, and he said Jamaica? I said, no. She wanted to go. Also, did you know that you're actually born with four kidneys? When you grow up, two of them become adult knees. And finally, it really annoys me when people get well known phrases wrong.

Steve Edwards [01:28:37]:
I mean, seriously, it's not like it's rocket surgery. Anyway, those are the dad jokes of the week. We'll say thanks to Tanner for coming on and talking about Stan Stack. Sounds like we're gonna get another episode scheduled with him and Ryan Carniato courtesy

Dan Shappir [01:28:55]:
of you. Hope so. I'll do my I can only promise to do my best.

Steve Edwards [01:28:59]:
Dan has connections everywhere, man. Let's see. If we wanna get somebody on, just talk to Dan. He knows. Thanks, guys, for coming on. Thanks to, Tanner for coming on, and we'll talk with y'all next time on Jobs with Jabber.
Album Art
TanStack: A Deep Dive into Server Functions and Routing with Tanner Linsley - JsJ 667
0:00
1:29:15
Playback Speed: