Make React faster with Million
Can you get better performance than React offers without switching frameworks? Million says you can, and Chance Strickland will show us how it works.
Links & Resources
- https://twitter.com/chancethedev
- https://www.fronttoback.dev/
- https://million.dev/
- https://www.streamtext.net/player?event=LearnWithJason
- https://web.dev/
- https://react.dev/learn/render-and-commit#optimizing-performance
- https://developer.chrome.com/docs/devtools
- https://developer.chrome.com/docs/devtools/performance
- https://youtu.be/95B8mnhzoCM?si=L_wj_K8j73EsvKxg
- https://www.learnwithjason.dev/schedule/
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hey, everyone. It's your friend Jason and I'm back with another episode of Learn with Jason. We're bringing ton one of my favorite people in the day, the one and only Chance. How are you doing, Chance?
CHANCE: Great, how you?
JASON: I'm doing great. I'm excited to have you on the show. We have had the chance to work on a couple things in the past and it's always been fun. And today you're bringing on something really interesting that I've heard about kind of on the periphery and haven't really talked about. But for those who aren't familiar with you and your work, do you want to give us a bit of a background?
CHANCE: Sure, my name is Chance, last name Strickland, Chance Strickland. Chance the Dev on the Internet. And I work at a startup called Replo. We're building a page builder app for Shopify stores to ship landing pages without writing any code. We are also -- we're just building out a really -- we have a really grandiose vision for what this thing is going to be. We are trying to improve the eCommerce space for people who don't know how to write code. That's what I do in my day job. My history, a lot of the people on the Internet know me for my work before. I have done a fair bit of open source work, worked on the rate UI for modules and RE2I. And I have a history in lower level components and a lot of experience and bringing a lot to the table for those projects, getting a lot of exposure and also worked on the Remix Core team. I think I was employee number three on that team. Pretty early in helping build out Remix. Maintained React Router on that team. A lot of exposure to open source prior to my current job. That's probably what, if anyone is familiar with me, what they know me from and otherwise, I just shitpost a lot on Twitter and I'm here to hang. Really excited to talk about something somewhat new to me as well. But it's a project that I have been looking at for quite some time and just really excited to dig in and talk more about it.
JASON: Excellent. Yeah. People are excited. What's up, everyone? Thank you for coming in. Sinanya, what's going on? Nikki, hello. So, we're talking about -- so, most of your experience in open source has been around React libraries, right? And so, you've done incredible work, Reach UI was so good. I wish -- I wish it had gotten all the way to fruition because I loved it so much. And, you know, I've always loved that you've put such a heavy focus on building things that feel good to use and are also fully accessible. That has been, you know, a common thread through all your work. How did you -- like how did that become something that you were focused on? Because it's clearly something that shows up everywhere you go.
CHANCE: Sure, yeah. I mean, I have a storied history beyond just web development. Web development is like my number four career, I think. I'm a serial career switcher. Finally found one that I like and I will stick with for a little while. Before that, I have a history and background in design. I studied architecture in college. Went on to be not an architect, but a graphic designer. But I've always dabbled with the web, I made websites in high school and college for bands I was in at the time. I think that's a pretty common background story from what I can tell over the years, a lot of overlap between musicians and web developers. Who unknowingly became web developers because their band needed a website. That's how we did it. I had that in the background, but I was very design-focused early on. When I caught wind of design systems and the whole idea of design systems, I was just fascinated. It brought together two of my favorite things: Design and systems. And how to systemize design in such a way and components that -- componentize? Is that a word?
JASON: Works for me.
CHANCE: Go with it. Roll into it. Turn these design -- these frequently-used design patterns into components that brought me into React. Before React, building a lot of WordPress sites, built a few apps with Laravel. But as far as design was, it was rolling my own quote, unquote systems which are really just me going in adding styles everywhere and not understanding design systems. But design systems and components were fascinating to me. And those things drew me to React, and the more I dug in and started to get familiar with some of the ecosystem, that's when I stumbled into Reach UI at the time in the early phases and they had a few components that I thought looked really, really interesting. Really loved the patterns that they introduced. And, you know, I also kind of wish that Reach UI reached its full potential. But in some way, I think it did. Because it inspired a new generation of libraries to come after it.
JASON: Right.
CHANCE: That have sort of adopted and ran with a lot of the patterns that Reach UI, I don't know if I would say "Established," but really helped submit into the psyche of how you compose these design components.
JASON: That's an interesting -- like this is kind of a side point. Like a little tangent. But the more I have been in this industry and just in general, the less I'm convinced that anybody invents anything, right?
CHANCE: Sure.
JASON: It seems like we're all remixing each other's ideas, riffing on each other's ideas. So, the claim isn't necessarily that you invented it. The claim is that you popularized it. Or that you reintroduced it to a group as opposed to this came fully formed out of my brain.
CHANCE: Sure.
JASON: Which I guess is true of all ideas. But I I think you're right that the Reach UI stuff put this sort of thinking on the radar of so many developers who maybe previously had never considered it at all -- or were even aware that it was a thing they needed to think about.
CHANCE: Yeah. Absolutely. And a lot of the patterns that Reach UI sort of put out into the world were always kind of the intended patterns that the React team had when they, you know, open sourced React in the first place. It was just that we -- we didn't really understand composition to the degree that it -- how powerful that it truly was. And Reach UI kind of exposed people to that I think in a way that really caught on.
JASON: Yeah.
CHANCE: And that's kind of what I think inspired so many libraries after it. Even teams after it. Like all these design system, closed source work I have done too, I have seen those patterns come up again and again and again. And I've also seen the old patterns come back to bite people so often, it's important to teach and remind people how composition works. And at the end of the day, it all goes bark to the core programming model behind React which I really, really love. And I still think it has so much untapped potential. And one of the reasons I love Million.js so much is you have now all of these competing frameworks that talk about performance and how React flows. And there's some truth to that. But I don't believe you have to throw the baby out with the bath water. Really lean into that core programming model that React officer. How can we have the best of both worlds? I think Million.js is going to inspire people to think about how to pull this thing even further.
JASON: Absolutely. And get props in the chat for how absolutely flawless that segue was.
CHANCE: Thanks. Practicing that. Yeah.
JASON: Wonderfully done. Okay. So, let's talk a little bit about Million.js. The hype on it, if you look at their site, the headline on Million.js is just make React 70% faster. What the heck does that mean?
CHANCE: That's what got me interested. Well done to the Million team who decided to run with that. I wish it were that simple. But it's a good way to get your attention and get you interested in diving in deeper. Fundamentally what Million is, it's a way to make one particular aspect of React faster and that is rendering. React is a lot of people are doing to say one of two things: React is slow. Or React is fast enough. I don't think anyone out there is really saying React is fast. Which is unfortunate. I think fast enough is for a lot of apps. But when it does become a bottleneck, it can be really, really painful to isolate and figure out what those bottlenecks are and optimize those things. React has a lot of tools for this, but for anyone who has gone down the use memo rabbit hole, it's not always that straightforward. Not only that, I just think there's more we can do to keep people from truly having to think about this at such a deep level when they're building highly-interactive apps. And so, I think having something like Million that it's -- we'll talk about what it is, I'm sure. But it really is a compile their changes how rendering works in React. And it does so in a way that it can in many cases vastly improve the rendering performance and the reconciliation performance in React. And so --
JASON: Go ahead.
CHANCE: I was just gonna say, when it says make React 70% faster. It doesn't mean it's going to make your React app 70% faster just because you drop it in place.
JASON: Sure.
CHANCE: There are nuances and tradeoffs like anything else. Some of the decisions in the way of how it does its rendering is going to impact the different components in different ways. And so, there is a will the more nuance -- and I'm still honestly learning a lot about it. I came on here, I Tweeted a couple weeks ago that I was excited about this project. But I had a service-level understanding at the time and I'm still learning and hopefully gonna learn a lot in real-time together. What I have seen and read so far, I think there's a lot of potential here. And I don't think Million has reached their own fullest potential yet. Yeah. Really excited to dig into the performance thing.
JASON: Yeah. And so, I think like you're talking about rendering. And in rendering in React is kind of a hot topic right now. There's -- I think it's been especially a hot topic since the introduction of hooks. And the good or bad, depending on your outlook of useEffect. It didn't change how rendering worked, but changed how much we knew of what was happening in rendering in React. The part -- I'm gonna make a statement and you can tell me if I'm wrong here. But my feeling about it is that what makes rendering in React hard is that there are enough places where you as the developer need to know what's rendering and why. And you have to trace that through different parts of your codebase in a way that can be really, really challenging. Especially, as you said, as something that's complex. Where you end up with a situation where you have like -- this thing changes. Now, that thing has data that will get passed down to lots of other components. All of which have different useEffects and things that get triggered. And you have to decide whether or not those components need to re-render when that data gets passed down. And, you know, whether the type of data that was changed or in what way it was changed matters. And so, if you're not really, really clear on how that data flow works and how the rendering model in React works, you can very easily accidently set up some extraordinarily heavy compute in a complex app.
CHANCE: Sure.
JASON: So, the premise here is that Million is trying to mitigate that in a way that doesn't require us to throw out programming model of React.
CHANCE: Yeah, absolutely.
JASON: Got it. Okay. Well, that's exciting. I'm very interested in that. So, you know, I'm -- I probably, if I need to do a follow-up episode with the creator of million.js who if I remember correctly is a teenager.
CHANCE: I had no idea that have by the way. When I first stumbled into it, it was a really awesome library. But when I heard the guy was -- I think he was like 16, 17, when he started writing it.
JASON: Wild.
CHANCE: Absolutely blew my mind. How is this kid doing work that the Core React team in all of their amazing abilities and knowledge -- not to talk down the React team. They have a lot of things going on too that they're working on. I mean, there's a lot of good stuff happening behind the scenes that we're not looking at. But just the fact that this kid like just sort of blew past all of that and was like, I'm gonna make React faster.
JASON: I mean --
CHANCE: What are you doing?
JASON: It is always really -- like I love the -- just the willingness to believe that you can. Right? Like I --
CHANCE: Absolutely.
JASON: There's this part of me that these days when I look at something like that. There's probably a good reason they did it that way. That's enough for me to not bother.
CHANCE: Right.
JASON: For somebody who still has that optimism. I believe it can be better and I don't care if it's hard, I'm gonna do it anyways. That's the kind of stuff that pushes the whole industry forward.
CHANCE: Absolutely.
JASON: Definitely need to do a follow-up. But let's talk a little bit about what we want to accomplish today. What do you have in mind?
CHANCE: Yeah, I just really wanted to build a very simple app that showcases how Million works, at least from the point of view of the developer who is using it. I always wanted to -- before we do that, I kind of wanted to start with a demo that the Million team put together. I'm gonna try and pull this up. I think it's demo.million.dev. Yeah, that's the one. And so, I just want to -- to start here. And it looks like posting links in the chat is no bueno.
JASON: Might have to post it in the private chat.
CHANCE: That's a good rule, actually. Probably. Just everyone post links to the chat. It could go bad real fast. Yeah. So, this demo, it's just a benchmark demo. It's not like -- always keep in mind with these things that this is not reflective of a real world app. This is not gonna be one-on-one comparable with your app. This is just a benchmarking tool. And it's useful to provide some insight. But it's not necessarily the indicator that your app is gonna work exactly the same way because there's always tradeoffs, right? And so, I assume you are -- you're doing pretty well for yourself. You're probably running on a pretty high-end machine if I had to guess?
JASON: This is an M1 Max. It was once a very high end machine. Now it's on the struggle bus.
CHANCE: The M1s are still pretty fire. I think you're doing all right. The reason I ask is because the performance bench marks we're looking at have a lot to do with CPU.
JASON: Yes.
CHANCE: When we talk about performance in React, obviously there's a lot of different factors. We're not talking about -- we're not talking about like the rendering performance of the -- of like -- this has everything to do with not only React vendors, but how the browser is going to render as well. So, trying to figure out how to frame that. So, where this is going to be really powerful is I think very large apps with lots and lots of data. Which will cause bottlenecks in pretty much any system. But more broadly for people who are running on lower end devices. So, the demo here is pretty straightforward. We have three different tabs. The nodes -- that's just the number of nodes that we're rendering in this large table in the bottom. It's a one-to-one-just representation of that's how many list items we have, right? So, we're rendering a thousand list items and then you have options to select how we're going to render those. You can render them using React out of the box, we can use regular React state updates. You can render -- you can see how it performs rendering with React fiber, they are wrapped in a start transition which is going to unblock the UI. And then you can see how that all works with Million. And so, for anyone who is not familiar with the performance indicator here, the little spinning wheel thing, what that's supposed to represent is blocking. So, when a script is executing, it blocks the UI. When you see that thing start to slow down and really sputter and turn orange and red, that means that the UI is blocked, essentially. That's what that is telling us. And so, if you're just calling set state to update all of these nodes, that's what happens if you click on the React tab. Also just because FYI, these are vastly different rendering engines. Every time you switch tabs, it takes a second for your machine to catch up. Keep that in mind. With React Fiber, when you wrap an update and start transition, it unblocks the UI, but the update itself for each of the DOM nodes might take a little bit longer. That's just sort of a tradeoff there.
JASON: Right.
CHANCE: And then Million is supposed to be somewhere in between and better at unblocking the UI and updating the UI. It's like -- and again, in different scenarios, they might have different performance benchmarks. But we should start to notice the difference as we start -- especially as we start throttling. Right now you can play with it. When you press the increment button, that's going to create state updates that updates each one of the nodes in the UI. And so, what I expect you to see in Million is for the blocking indicator to be relatively smooth. When you press the increment button, I would also expect to see that the UI, both the tables -- the table of rows and the -- the number and the button itself -- should update pretty quickly. And it should be a one-to-one-update with a number of clicks.
JASON: Yeah.
CHANCE: And so, if you click really fast ten times, you should see the number go up by ten. Same thing in the React tab, if you're just rendering without concurrent rendering, you should see the tab does eventually catch up. But it's a little slower to catch up because things are blocked behind the scenes. With the Core React rendering, this is the problem. It can block UI and cause this noticeable lag in performance. So, React Fiber or concurrent rendering, it sort of came about to solve this problem. But it introduced, like I said, some tradeoffs. So, even though it does unblock the UI faster --
JASON: Oh!
CHANCE: If you press the button ten times, it doesn't necessarily update ten times.
JASON: I clicked ten times, and it only did two. One, two, three, four, five, six, seven, eight, nine, ten.
CHANCE: They don't get scheduled because it blocks the UI. It's slicing the different parts of work and doesn't necessarily Capture that because the UI hasn't caught up to React's rendering. It's a tradeoff, right?
JASON: Yeah.
CHANCE: But with a lot of data, I would argue this tradeoff is almost worst. You're not getting the feedback you expect. When you have a small amount of data, it's fine. When you wrap smaller pieces and you never notice these things. In fact, you might see an improvement there. It's a behavior to be cognizant of. Million tries to remove that for both blocking and updating the UI. And so, that's kind of like -- that's the thing that you would be looking for when you are comparing performance in your app between Million and React, right?
JASON: Yeah. I'm definitely starting to chug this page.
CHANCE: Yeah. And it will get really, really noticeable if you open up DevTools. If you open up the performance tab and you choke your CPU a little bit. You should see...
JASON: Wait, how does one do this? CPU...
CHANCE: Go 4X. If you go 6X, nothing is gonna happen. Million also, if you're throttling your CPU, doesn't matter what you're using. If you have a low-powered device, might take a little bit of time. Click on that React tab.
JASON: I'm trying.
CHANCE: Yeah, good luck. Yeah. It will take a second.
JASON: Okay. Let me get to the React tab.
CHANCE: Yeah, yeah. So, really effective CPU throttle.
JASON: It is -- it is doing great. Do I need to like un-throttle this to get me...
CHANCE: Is red spinner good? No, red spinner: Very bad.
JASON: Okay. So, we're in the React tab.
CHANCE: There we go.
JASON: I am incrementing.
CHANCE: Yeah, it's gonna chug. It's gonna really chug. So, UI is blocked for the entirety of that cycle while the spinner is red. That's blocking the cycle. It can be really bad on low-powered devices. And again, this example has a lot of data. I want to throw out there too, a lot of people say React is fast enough. What they mean, it's fast enough for most applications. That's largely generally true for rendering. For most applications, rendering is not the performance bottleneck. But when it becomes the bottleneck, it can be really, really painful to fix. I want to call that out. This is not a -- first of all, this does not mean that your app is gonna be this slow. Like we have a thousand rows here of DOM updates to perform. And the DOM update itself is a pretty slow process. Which is why people do virtualization, right?
JASON: Right.
CHANCE: So, just stuff to keep in mind. And also, this is not a silver bullet either. And we'll talk little bit more about that as we dive into how Million actually worked.
JASON: All right. Before we dive that, a quick shoutout, we have this episode and every episode closed captioned, we have Amanda with us here today from White Coat Captioning. Thank you very much. That is made possible through the support of our sponsors: Netlify, Vets Who Code -- and just signed up, Nx. Thank you to everyone who has taken the time to response they are show. And a quick shoutout to the new channel members. Signing up to support the channel makes such a big difference to me. Thank you Roger and thank you Adam for signing up and becoming members. Really do appreciate that. So, let's dive into --
CHANCE: Can I say something really fast?
JASON: Yes.
CHANCE: I've always wanted to say this. I don't have a YouTube channel. I want to make sure everyone smashes that like and subscribe button. That's all I got. Smash that like and subscribe.
JASON: Ring that bell!
CHANCE: Boops flying, baby.
JASON: Let's dig in. I'm very excited to learn about this. I shared a link to your profile earlier. Let me share that again. This is Chance on the Twitter. There somewhere else I should send people? It was so obvious a while ago, it should be your Twitter profile. It's just not that anymore.
CHANCE: Yeah, it's still the main place I hang out on the Internet. But working on from front to back -- the link in the Twitter bio. FrontToBack.dev. I started working on it a year and a half ago. And essentially this course is for people like myself. For frontend developer who is really struggled on the backend or didn't understand the backend for a long time. I've made strides in that area, and hoping to share that. It's for people who are competent frontend developers. Because we have a certain way of thinking about web development. And I think there are ways to make these concepts connect better if you already have that understanding. So, that's kind of how I'm focusing this course. And if you're -- if you fit that description, I would love to have you along. And so, yeah, there's a sign up at the bottom. You can sign up and get updates and little mini courses as we start to build this out.
JASON: Awesome. So, go check that out. Because I feel like -- this is one of those things, like learning a little bit of backend as a frontend Dev is -- it's such a superpower because all --
CHANCE: Absolutely.
JASON: -- of a sudden any of those ideas you have, you can just build them. And that feels really, really good.
CHANCE: Yeah. Even if you don't to want build those things. If you're on a team and looking to upgrade your career game, you will fit in better as a frontend developer if you can jump into the other side confidently and understand how things work. Yeah, I think there's a lot of benefits to that.
JASON: Yeah. And this is sort of that -- I talk about being a generalist a lot. And having a broad set of skills or what I've heard described as a paint drip developer where you have -- you have broad experience in like varying levels of depth in different topics. It just -- it means you can -- you can jump into any part of any project and be high-contributing. And that's gonna have so many good things for your career, for your ability to get the job you want. And, you know, from a standpoint of like, I always make the joke that a career is a pie eating contest where the prize for winning is more pie. So, if you want to do -- if you want to be doing something, do that thing and people will reward you by having you do more of that thing, right? So what about it broad base of experience allows you to direct yourself a little bit more by being able to do the things that you wish people would hire you to do.
CHANCE: And now I want pie. [ Laughter ] Didn't have that hankering before. But yeah. Kind of want some pie.
JASON: All right. Let's dig in here. We have the Million.js site. Let me toss this into the chat for everyone. I'm ready and excited. Let's give it this a shot.
CHANCE: Let's do it.
JASON: What should I do first?
CHANCE: Just a little bit of background: Million is a compiler first and foremost. Because it changes fundamentally how React works. It needs to have a little bit more knowledge into the overall application that you write. So, the only way it can really dos it optimizations correctly is by digging into the compiler and acting as sort of a... a complete rethinking of how React works. Like you shouldn't -- if you use Million, you shouldn't have to change anything about the code you write in most cases. You should just be able to set up a compiler and go and so, they have a way to do that which we're gonna use Vite. Although it has ways to plug into different compilers. If you go to the docs, you'll see, there's like a getting started section.
JASON: Whoops. Let me actually get to the docs here. Docs.
CHANCE: Yeah. We can skip the intro and go right to installation. You'll have a few things. First thing we need to do is set up a project. We're gonna use Vite.
JASON: I had something open here. So, let me -- so, yeah, what do we do? We do npm create Vite?
CHANCE: I think it's create -- yeah, that sounds right. And I would say @latest to be sure you don't have a cache thing hanging around. It's going ask a bunch of stuff. Go ahead and go through the prompts. I think it should ask for a template, you can use React or React.js, whatever you prepare. Just the React, yeah.
JASON: We want React, we want TypeScript. Okay. So, let me open this up and...
CHANCE: Right on. So, I would also go ahead and just install your dependencies. So, we can spin this thing up.
JASON: Okay. And if you have never seen a Vite project before pretty -- they keep it pretty simple along with the standard entry file. They have an app file that shows demo stuff just showing how the use state works. A little bit of styles. Some global styles and then we've got a logo here. And everything else is kind of -- not super-relevant to what we're working on today. So, ultimately, I'm guessing we're probably gonna dump most of what's here. But...
CHANCE: Yeah.
JASON: All right. Did you want me to start this?
CHANCE: Before you do, go ahead -- let's go ahead and do the install real quick of Million. Just npm install million.
JASON: Okay. And now I'm just gonna --
CHANCE: Yep.
JASON: Keep this open so we can see what we're doing. There is Million.
CHANCE: Before you start it up, go into the Vite config. Like I said, this is compiler. We need to make sure we integrate it with Vite. You're going to import Million from million/compiler. And --
JASON: Okay.
CHANCE: -- in the plugins, right before the React plugin, we're going to initiate the Million plugin. This will be million.vite, and the function. And that function is going to take some arguments as an object. So, you have two modes you can use here. You have auto, and you have manual. And so, there's an auto key. So, just go ahead and set -- for now let's just set that to true. And this is how the Million docs recommend you get started with Million. Is just set it to auto mode. Now we can -- we should be able to save this and run our app and everything should be able to work the same way it worked without it, right?
JASON: And it does.
CHANCE: So, you're not gonna see anything different. This is obviously a very small app without a lot of data. So, you're not gonna really notice anything different. But I just want to illustrate that this -- it just works. It's essentially a drop-in replacement for what React was doing under-the-hood. And everything should work most of the time. I think they made a lot of really interesting changes in the latest version in v3. I know with server side rendering in particular, there were issues with the versions they made lots of improvements on. So, ideally, there should be a large degree of compatibility with the React ecosystem. And I think -- don't quote me on this, I haven't benchmarked every React app in the world -- but it should work for most React apps as a drop-in doing something like this. That said, I have no idea how auto mode actually works. There's a bunch of different things you can use to -- well, a few different things you can pass in here to help configure it. There's like a threshold prop. I don't actually know how it works. And I think that's the idea. They don't want you to have to think too hard about how it works. They want you to understand at a high level how it works and what the tradeoffs are for using Million to hands rendering a component versus React's Core engine. But if you understand those, you shouldn't have to do too much configuration to make auto mode work for your application. Essentially what's happening here when you're running in auto, your components are optimized, the rendering of the components are optimized by Million and you shouldn't have to think about it. But in some cases, and there are the cases that are in the Million docs that do a good job of diving into the components here. There are some components, depending on the data, where Million might actually be slower. And so, in those cases, you might have a component where you have a lot of data that changes between render cycles and that could slow down Million. And in that case, you might want to bail and use React's Core rendering. You can do that with a comment at the top of the component. It's just slash, slash million-ignore. And million, it sees the component and will not optimize that component for you and lets React do what it always does in that case. It's like a reverse -- like an opt-out if you're in auto mode.
JASON: Okay.
CHANCE: So, someone -- yeah. So, someone asked when Million could be slower? So, to understand this, I think it's helpful to understand some of the -- I don't want to get too in the weeds about how the rendering differences work. But essentially, when React renders your application, what it does is it goes through and it -- when data changes and state changes, it is going to re-render your entire -- not the entire tree, but the parts of the tree that have changed or the parts of the tree that depend on the data that have changed. And then it's going through a process of reconciliation where it reconciles the difference between the components in the tree. And that I think is really where things start to slow down in React. Or they can start to slow down in React. Because it's not just diffing the data that's changed, it's diffing the entire tree. And so, Million takes a slightly different approach. It doesn't diff the entire tree, it diffs the data. It's a compiler so it can see into your components. It understands where the data is being used. And instead of diffing the entire tree, it just diffs the data. It can be more hyper-focused on which things it has to update throughout the tree. I think Svelte has something similar, dirty diffing or dirty checking is maybe it.
JASON: I think dirty diffing is it.
CHANCE: When can it be slower? If the bottleneck in the component is the data and not the tree, then in that particular case Million might be slower because it's diffing the data and not the tree. If you have a really high-compute piece of data that's wrapped in useMemo because it's expensive and that updates and Million has to diff that in that process, it could technically be slower. Always, always, always profile these things before you make assumptions.
JASON: Right.
CHANCE: That's the idea. Because it's diffing the tree, not the data, where is the bottleneck in your component? If it's the data, Million might not be the best for that component.
JASON: And I think the scenario that you're talking about where the issue is the data, I think that is one of those things that I consider to be just -- it's like a core architectural thing is trying not to put intensive data into the frontend. Like your JavaScript probably shouldn't be doing big computed data calls anyways, right? Like if it is, maybe consider trying to move that somewhere else? Move it to an API, move it to, you know, something else. Because what you're always doing is getting back the same derived data, you're making a lot of people's browsers do that work instead of having one centralized server doing that work. So, like a serverless function with a cache is a really great way to solve that problem. Obviously, there are exceptions like dashboards where the data is per user. But even then one you can still put that like on a server that's like -- on US East 2 right next to the database where it's pulling the data from and you're probably gonna have a better time than making the user's browser deal with that.
CHANCE: Yeah. And that's a really good point and I think one that we really have to hammer home when we talk about this. When you talk about performance by any metric, React or any other framework, there are so many pieces to this puzzle. It's not a silver bullet. Million is not a silver bullet. Moving data is not a silver bullet. It's not necessarily going to be better performance, there's always tradeoffs and you have to always be measuring. Knowing how these things work at a high level gives you a really good head start when things start to get slow as to where you need to look to fix them and so, you're absolutely correct. If you can remove some of the that compute from the computer to the server or to a serverless function, that could very well improve performance more than moving to Million would. But it really just depends on what you need and what you're building. And so, yeah. I think that's a great point. So I'm just gonna jump into -- sorry, go ahead.
JASON: There were a couple questions that I wanted to pull up here. The first one is, is there a restriction to use it? It looks like there is not. Because they have docs for Next, Gatsby, Vite, Cathy React app -- and I think that's the gamut. Because they have a Vite setup, anything that's not listed here is probably running on Vite. You should be in pretty solid shape wherever you want to use it. And then the other question can is you can opt out? They have options -- you were just saying, they have the million ignore like a TS ignore. As well as you have this straight up skip where you can tell it to skip different components. Like if it's using a certain thing, you can skip that whole component. So, this would be a way to sort of get, you know, however you want to do it. So, there's the million ignore. Lots of -- lots of options here. Very configurable. Right out of the gate, this sounds pretty promising. But as you said, a quote that I love from snowpie, I'm being told that silver bullets only work on werewolf-shaped problems. I love that. It's very much like this -- none of this stuff, no piece of code, no framework, no tool is going to replace the critical thinking that goes into looking at how your particular app serves your particular set of users and making sure that the way that you're putting things together is getting them the best possible result. And that you just can't automate that. That has to be a process of you thinking through how do things move? Where is the work done? Where are the places where we could do less work or combine work or any of those things? That's the job. Like our job is not to write code. Our job is to make computers do the things in the best way. Code is only a part of that. Most of it is thinking.
CHANCE: Absolutely. Which is why I think our job is safe as far as AI is concerned, at least for the moment.
JASON: Yes.
CHANCE: Still not great at actually thinking.
JASON: 100%. Okay. We've got -- I mean, this might just be a really short demo. We're done.
CHANCE: No, we're not done. Not done. Thankfully, there's more. I mean, I thought about that actually when you suggested this, I was like, it's pretty easy. Might take ten minutes. I want to dive in a little bit. Because like I said, this is automatic mode. But if you flip auto to false, we have now entered manual mode. Which as the name suggests means you have to do more manual work to get things. This is where I've dived in a bit more. Magic to me is kind of confusing. I like to try to at least understand at a high level how certain things work. The main difference between auto and manual is that instead of opting out of Million optimizations, you now get to opt into Million optimizations.
JASON: Okay. So, we're still running -- the server restarted. I come back out here. We're in manual mode.
CHANCE: Yep.
JASON: But now this is all running in React's compiler.
CHANCE: Exactly. React is doing all the rendering now because we have opted out of manual mode -- opted into manual mode, out of auto. If you want to optimize in your app, you need to do so manually with some of the tools that Million provides. There are only a few tools. Essentially at a high level, Million -- what Million does, is it gives you this concept of a block. And so, each component -- when you're in auto mode, the components that are optimized get converted into what Million calls a block. And it's basically like a React component that is hyper-optimized for rendering speed, right? And so, while automatic mode gives you these by default, you don't have to think about it, in manual mode, you do, and it's a higher order component function "like" block. It's a wrapping the component in the block function and it's going to give you instead of the underlying React renderer, it's going to give you a component that's rendered by Million. This is the opt into Million essentially at the component level. And so, if you had a component that you wanted to -- let's go ahead and create a couple things. Because I want to actually create some components where this might be useful.
JASON: Okay.
CHANCE: So, in your app --
JASON: Empty this out?
CHANCE: You can keep it for now. Create a new file. Just call it -- I don't know. Call it "Table." We'll do like the Million demo, make a little table with a bunch of rows.
JASON: Okay.
CHANCE: You can go ahead and create a component. We'll call it -- yeah, we'll call it "Table." And inside that component, let's go ahead and create some state.
JASON: Okay.
CHANCE: Yeah, you can return anything too. It's not a -- we just want to create some state. And we'll just say in this particular case we're going to -- we're gonna just be adding rows, right? So, go and initialize this, let's say "Rows." And let's start with like a hundred rows.
JASON: Okay. And how do you want to do that?
CHANCE: Oh, yeah, just initialize your state with a hundred.
JASON: Okay.
CHANCE: And then return here. Let's just return -- wrap it in a div. And we'll say... so, instead of rendering the table here, what I want to actually do is I want to use this -- and maybe table was a bad name, but we're just YOLOing here. Go ahead and say -- how do we want to do this? What I want to do is utilize suspense a little bit. Because suspense is going to help us managing the unblocking of the UI while this is managing.
JASON: Okay.
CHANCE: Before we do this, another component. Because I did a bad job of naming this, we'll call this one "Actual table."
JASON: Okay.
CHANCE: I never said I was good at naming things. So, in this particular table, again, we're going to make an actual table. So, you can return a table element. And just give it like a header with -- we'll just say like two -- we'll just have two random headings.
JASON: How does this work? Yeah. Wait, no, that's not it. TD? I can do this.
CHANCE: The head --
JASON: Damn it! All right.
CHANCE: No, we can teach HTML too, it's fine. There you go.
JASON: Hey, I remember that a T-head existed. I'm gonna take the win.
CHANCE: Yeah.
JASON: For each of these -- have a td, that's like thing.
CHANCE: There you go.
JASON: And then we'll have a value of like whatever.
CHANCE: Yep.
JASON: And I assume this is gonna be looped on the rows?
CHANCE: Yep. You can go ahead and say this takes -- we're just gonna take a set of props. One of the props is rows. And the number of rows. The actual thing can be randomized. Doesn't really matter what we render. We can even just create a random array of rows. If you wanted to install Faker or something to come up with some names or something. You could do that. But we can -- let's just say like math -- for each one of the rows, say math.random times the index or whatever and put that in the value.
JASON: Okay.
CHANCE: It can be whatever you want it to be.
JASON: All right. So, this one is gonna be thing. We'll just straight up throw the index in. And that's easy enough. If I can remember how to type. And then this one, we were going to do math. Not F math. I've got to turn off all these extra helpers. They're helping too much. So, math.random times...
CHANCE: .5. It could be math.random. Doesn't matter.
JASON: Yes, math.random, easy enough. Somewhere in here I messed things up. And what's -- property row --
CHANCE: Yeah, it needs to be an array of numbers. Also, Vite has gotten very aggressive with its linting. You don't have to pay too much attention. But you did forget a key. We can go ahead and throw a key on the TR. Because you will get a lint error from that. Index is fine. Even though that what's it would use by default if you didn't have one. But we can just use the index in this particular case.
JASON: That's fine.
CHANCE: Yeah.
JASON: And I just add these little prefixes because theoretically I would be putting something else that was looped and you would get the same index.
CHANCE: With actual data, you would have the ID and the whole point of the key is to prevent React from struggling to diff the entire tree if nothing changes. So, yeah, now we've got our table. And let's see... we can also -- let's just go back into our -- go back into our other component. Now we'll actually use this thing. And what I want to do here is because when we get this thing -- when we actually start doing some heavy lifting with this thing, instead of just importing actual table, let's do a lazy import. Using React.lazy.
JASON: Okay. I have never actually used this. Do you want to tell me how it works.
CHANCE: Yeah. Import lazy from React. What we're doing is lazy loading this component. The component -- it's like code splitting. Whether you lazy load a component, it's not going to load until the parent component that actually has to render it is rendered. It prevents you from bringing in extremely large bundles potentially. You want to move this out of the component, actually.
JASON: You do move it out of the component. Okay.
CHANCE: Yep. And it's actually -- needs to be a default export. This is one of the things about React lazy I don't actually like. Because I hate default exports.
JASON: Oh, it has to be --
CHANCE: Okay. I'll show you the work around real quick. Inside lazy load, there's a function. And that function is going to return an import statement. Return import function. So, we are lazily importing this thing. So, go ahead and import it. And since you don't have a default export here, what you can do is this is a promise. You can go -- you can say .then. And actually what you're gonna return is an object here. Sorry, then is gonna take a function. Yep. There you go. And just return an object where the default key says actual table. This is a dumb little thing you kind of have to do because React lazy expects...
JASON: Oh! Like this.
CHANCE: Yeah. It just expects an object with a default, which is how a default export is like.
JASON: What am I doing wrong?
CHANCE: Let's see -- oh, you haven't used it.
JASON: Wrap it --
CHANCE: Maybe.
JASON: Declared value is never used. Declaration or -- oh!
CHANCE: Oh, it's not wrapped in -- yeah, you got to wrap it in parens. Yeah.
JASON: And then you're mad because what?
CHANCE: You have an extra parens --
JASON: Default is missing...
CHANCE: You have an extra parens, you're calling then on lazy instead of the promise. You need an extra.
JASON: We did it.
CHANCE: All dumb, because it should have -- it could have -- this is fine. I don't like this Default exports. I end up doing this. Sorry, we're not quite done.
JASON: We did -- we were setting a money and now it's an array.
CHANCE: We can fix it. Leave it as it is. We can go -- another feature when you are rendering components that are lazy imported like this, you need to wrap them in suspense with a fallback. Since they're lazy, they're not available immediately. The component needs to render first and deal with that rendering. And so, inside suspense, we can render a fallback. And that can just be some text that says "Loading" if you want for now. And now it should be fine. Go back into an actual table and fix this problem. We don't need to make this an array. Instead, we can have just like -- create like an empty array out of this. So, call array.from length rows, okay?
JASON: Okay. Yeah. So, we'll...well do it like this. And we'll do array from rows. Wait. That doesn't work.
CHANCE: No, that has to be an object where it says "Length."
JASON: Length. Right. Oh, yeah, I've done this before.
CHANCE: Nice little trick for those who aren't familiar. Essentially, because arrays have a length property, when you create an array from that, it's going to create an empty array with that link. Now map to the array and it should be happy.
JASON: Yeah, good. Okay.
CHANCE: Cool.
JASON: So, do we -- should we just -- maybe we can get to that in a minute?
CHANCE: Yeah, we'll get to that in a minute. Since we have this set up, let's render the table in our app.
JASON: Throw it at the top.
CHANCE: Yeah. And you can get rid of all the other crap at this point if you want. Sorry, you want to import the table. Not the actual table.
JASON: Oh, right.
CHANCE: This is not confusing at all.
JASON: And then...
CHANCE: From table. Boom.
JASON: Everything's happy. We're going back.
CHANCE: Good work.
JASON: Back here and look at it go!
CHANCE: We have a hundred rows and look how freaking slow it's going to be potentially. It's not that slow, it's only a hundred. If you change that to a thousand, it could be. Let's go to the table component and add a button to increment that by say 10.
JASON: Okay. So, this will be -- I guess we can actually just do --
CHANCE: Throw it on top of suspense, yeah.
JASON: Button and that will be an onClick. And that will set rows... current. Current plus equals --
CHANCE: Say 10.
JASON: -- 10. I guess we don't need so say plus equals.
CHANCE: Exactly.
JASON: You don't explicitly have.
CHANCE: What does it say?
JASON: It's because I haven't declared this yes. It's not remembering how things worked because why would it? Let's see... add 10.
CHANCE: Beautiful.
JASON: Okay.
CHANCE: And everything is going to re-render because we're calling math.render in there. Yeah, just something to keep in mind. All right. So, now we have this table. And let's just -- just click add 10 a bunch more times. Oh, actually, I was going to say create a Fibonnaci function so this thing gets really, really slow.
JASON: If that crashes my browser, the whole stream ends. We probably shouldn't do that.
CHANCE: I've made that mistake before. Make it at a hundred. I want to see it here.
JASON: Okay. And we're going to add 100.
CHANCE: There you go. Yeah, just keep pressing that button. You should start to see --
JASON: You see it chugging.
CHANCE: It should feel pretty laggy at some point.
JASON: That's a mess.
CHANCE: Yeah, yeah.
JASON: We're now at -- how many? 4,000 roughly. And now when I click, watch it chug.
CHANCE: There you go.
JASON: Like there's a notable they when I'm doing this now. It feels very -- this is janky.
CHANCE: What we're going to do now is we're going to use Million. And so, I would -- let's go ahead and open up the -- so, we've got the table array. What we've got here is the actual table. We want to make some changes to the actual table. And so, what we're gonna do here -- so, the expensive stuff are all of these rows that we're rendering, right? So, let's extract all of that. Not the each -- let's keep that where it is. But where just take the TR element, we're gonna create a new component for this.
JASON: Okay.
CHANCE: And go ahead and at the top, anywhere, just outside of the component here, go ahead and create a new one. Call it "Row." And then -- yeah. Just return the thing that we had. And so --
JASON: Okay. It's just gonna need one of these for now.
CHANCE: Sorry, you don't need a key. Remember, you passed the key once you iterate. So, we don't need the key here. Just get rid of that.
JASON: Don't need the thing, okay. But we'll still need the name.
CHANCE: Yeah. Just call it name and then call it value.
JASON: Okay. And do you want these -- we don't to want calculate this inside anymore? We want to pass it?
CHANCE: Correct. Pass it in and name value.
JASON: Okay. Name value. And value is going to be, we'll just make it a number.
CHANCE: Yeah, doesn't matter, any number, string.
JASON: And this will be value. This will be name. And this will be our component. So, then we've got our row. And down here we will say row key equals I. And then we need the name. Which will be this. And the value. Which will be this. Okay. Then we can drop this.
CHANCE: Yep. And right now we haven't changed anything. We've just moved this to the separate component. We're rendering it exactly the same.
JASON: Right.
CHANCE: What we want to do is we want to use Million to handle this for us so that things start to get faster. Remember that the reason -- the primary reason that React gets so slow here is because you're handling a ton of DOM nodes. And the DOM updates themselves are gonna take a long time. But you're handling a ton of React nodes in the React tree. For React to deal with this, it needs to go through and, again, it has to diff all of those nodes. And as you have more nodes, there's a certain point where there's more work for the browser to do. And again, we don't necessarily want to diff the nodes, we want to diff the data. We can use Million for something like this. What we're gonna do is with our row, do a couple things. But the first thing we're gonna do is wrap it in the higher order function block that we import from Million.
JASON: Okay. So, we're gonna -- sorry, I was answering a question in the chat. We're gonna import block --
CHANCE: From million/react.
JASON: And million/react.
CHANCE: And wrap our row in a block function. And you've now opted into rendering this row with Million. However, we're not quite done. Million has another tool that we get for handling large lists called Fors. Capital F for that you can import as well from Million. And this is a component.
JASON: Okay.
CHANCE: And this is essentially a component that million gives you for large blocks.
JASON: Is this like a control flow function?
CHANCE: Yeah, kind of.
JASON: Okay.
CHANCE: If you're used to -- I think Solid has similar functions.
JASON: Yeah.
CHANCE: It's gonna work similarly. Yeah, you're gonna render for, and pass in the data. I think it's forEach I want to say is the prop name.
JASON: For each array.
CHANCE: Yep, pass in an array. The children is actually going to be just a function. That's a render prop, essentially --
JASON: Got it.
CHANCE: It's going to give the item.
JASON: So, it's gonna --
CHANCE: No index, just the item.
JASON: Just the item?
CHANCE: Yep. Actually what I think we want here is I think we need... let me see here... I had some notes on this. I think the random -- math.random thing. We need to extract that out a little bit too. The actual array of data that we want, we -- we need to -- we need to pull up that array and actually create an array of random numbers. Instead of an empty array, we need to fill it with random numbers. No, map also totally works.
JASON: Fill value. And we would just do a math.random.
CHANCE: Yeah. I don't think that's gonna work. That's gonna generate the same number for every item. We want them to be different. Actually, let's use map. There you go. Now each item is actually -- now it's our array of data.
JASON: Okay.
CHANCE: Each item in the function is the random number. You don't need the key, you can pull that out. We're not looping anything. That's going to be handled under-the-hood for us.
JASON: Okay.
CHANCE: So, we should be able to -- yeah. Get rid of that. Yep, exactly. Same thing with thing, it just needs to be thing. Item.
JASON: Okay. And then drop this out. Oh, it can be thing...
CHANCE: Yeah. Or you can -- when you map through, you can also just make it an object that has the index if you want to maintain the same. Doesn't really matter. Yeah, they can be the same.
JASON: Okay.
CHANCE: Great. And now you have optimized this rendering with Million. And so, it will --
JASON: Match --
CHANCE: It will still feel laggy because all things do as you add data. But it should feel noticeably less laggy than before. It's not diffing the entire tree, it's just diffing the data, and the data in this case are just numbers.
JASON: Right. This definitely feels -- I don't know how many -- I think we're at about 5,000 again.
CHANCE: Yeah, we could probably log it or render it somewhere just so that we know.
JASON: Yeah. Maybe what we should do --
CHANCE: Actually --
JASON: Let's do the thing. So, we'll set up a count will be i + 1. And value. And then down here we can do a thing. Item.count. And this will be item.value. Okay. So, then we can add a bunch. It's going along just nice and easy. 5600.
CHANCE: Oh, wow, that's a lot.
JASON: We're at -- I can feel it chugging a little bit.
CHANCE: Well, 5,000 things in the DOM is gonna be slow no matter what you do. That's the DOM. It's not fast.
JASON: And also just running a loop 5,000 times, it is what it is. There's only so much you can do there.
CHANCE: Yep.
JASON: If you have 5,000 items, you would start looking into virtualized lists or things like this. But the fact that this -- and it does feel -- I mean, this is something you have to try on your own to actually feel it. But it is -- it is still chuggy at 5,000, but it is noticeably less so than plain React.
CHANCE: Yeah.
JASON: So, that's very interesting.
CHANCE: Yeah, I would say if you ever have 5,000 rows, we're doing something way wrong with actual DOM elements.
JASON: Because also this just sucks to use. This would be awful.
CHANCE: Even when you're not rendering, you have to scroll and the browser has to catch up with all that. At a certain point the browser becomes the bottleneck. But yeah, if you started over and started with a thousand, it should be relatively quick.
JASON: Great. Okay. So, let's start it over. There's a hundred. And we go one, two, three, four, five, six, seven, eight, nine, ten. And it's like instantaneous.
CHANCE: Yep.
JASON: Feels really... it feels good. Like this does actually feel like a notable improvement in terms what have it feels like for me as the user to work with in website that's doing a lot of intense work.
CHANCE: Yeah. And there's a couple of different interactions I like to use for testing this sort of thing. One, you want to actually look at the UI update because that's going to be an immediate visual sign that things are happening or things are laggy. That's going to measure the UI update, but not necessarily tell you about render blocking. Something I like to do -- actual profiling is helpful. But just a shortcut, when you click an update, try to immediately scroll after that, that's going to show you if the scroll jumps around while it's render, that's going to show UI blocking in action. If you have scroll pretty much immediately after you click that button, the blocking should be okay. As soon as that scroll feels laggy after pressing that button, then you know things are being blocked. There's other ways to do, but that's a quick and dirty shortcut I like to use.
JASON: Okay, add another ten, that's another thousand items. I don't know how this is coming through on the screen. But when I start to go, it starts to jag a little bit. But we're at -- for it to get there, we got to about 2,000. I think 1500 was when it started. But right out of the gate, like as fast as I can go. It -- there's no -- no hang and we're at 600 items? So, it does -- yeah. I think the render blocking things is huge. And I saw somebody was talking about this on Twitter, I think yesterday. Where they were saying that they -- their partner was trying to use a website and they thought it was broken because there was a button. And they would open the web page. They would try to click the button and the button wouldn't do anything. But they had to weight 8 seconds or something for the page to become interactive. And they didn't know that because why would you know that? They kept thinking the site was broken and they would refresh. So, they never got to an interactive page. This is really interesting to me when you talk about it from that standpoint. Because a lot of times we're thinking about, how can I get UI on screen as fast as possible? How can I, you know, how can I make the JavaScript-JavaScript as fast as possible. But not thinking about how that fits together in user experience. In render blocking and interactivity, that's what actually matters on a website. Because if we deliver a beautiful UI that's not interactive, the site feels very broken. Whereas if you deliver a site that shows a loading spinner for a second and as soon as everything pops in it's clickable, is that ideal? Probably not.
CHANCE: Depends on what you're building.
JASON: Right? So, yeah, no. Definitely something to keep in mind as you're building is like the -- the way we measure speed matters.
CHANCE: Absolutely. Yeah. Just to reiterate all of this. There are many ways to optimize your React components. Rendering is just but one of them. And there are even probably better ways to optimize rendering before the point where you need to rip out your compiler. But the idea behind Million that I think is so powerful, it is something you can drop in and start adding optimizations as you need them. Or drop it in and put it on auto mode and opt out of things where you figure out things are slower or worse, potentially. It's a very flexible system. And it shouldn't make you change the way you think about writing your code. Which is really what I'm after at the end of the day. Is something that doesn't get rid of the React programming model that I love. But let's me write faster applications. And so, if Million can do that for us, I'm in love with it. And it can help. But it's not the only thing. Like you said, you can move a lot of the compute off the machine and on to a server potentially. Or in a serverless function. There's different ways you can optimize different things. But having this as a tool in your toolkit I think is really, really powerful. And I don't think it's the last of its kind. I'm really excited to see like -- we've all been working for React for get, which itself is going to be a compiler. And I'm sure it will have lots and lots of performance optimizations that we'll get to experience and enjoy. So, I think this is just kind of like -- this is -- it's like an opening shot to a call to arms to make React faster.
JASON: And I think --
CHANCE: I'm really excited about it.
JASON: To me, this is the sort of thing that... I don't ever want to imply that anybody is doing anything wrong. So, take this with a -- with the spirit of love that it's intended in. In open source, the thing that tends to dictate whether or not a Community is thriving, in my opinion, is whether or not people are challenging the space. And what I mean by that --
CHANCE: Absolutely agree.
JASON: We saw -- we saw this explosion of innovation around the time that like jQuery came out, there was jQuery, MooTools, trying to solve the same thing, and eventually jQuery was the best for this iteration. We decided that was the one that won. We adopted the best parts of that into the browser, then a moment of quiet. Then the explosion of Backbone to Angular to React and Svelte and Vue and all these others that came out and another big change of the space. It sort of felt like over the last couple of years or the last five years or so, we had just sort of given up. Well, React is as good as we're gonna do. And I know that anybody who is a Vue or Svelte or Angular maintain is angry at that. I'm not saying nothing else mattered. But there was a tacit decision that React was okay. Now we're seeing the innovation come in and seeing people challenge it, like, hey, what if Preact forks away from React as opposed to being a lighter version? What if Million replaces the compiler? What if we don't need the compiler and rely on something like Astro? All of a sudden it's an interesting challenge to the space, it could be better. That could lead to the React team building far better code. People are seeing what they don't like and how they would like it to be done. And making the decisions that will ultimately lead to everybody getting better experiences. Whether you stick with Million or React Forget, or that's another third thing that we haven't heard about yet.
CHANCE: Yeah, I couldn't agree more. Like everything is a rising tide that lifts all boats. I'm just like -- React made, I think Angular stronger. I think the advent of things like Svelte and Vue and eventually Solid are going to continue to make React stronger. I think the React team itself is working on solutions that we don't even know exist yet with React Forget and hopefully some other secrets cooking in the lab over at Facebook. So, I think -- I think this is just a really beneficial -- just the fact that we're thinking more about like Core performance. Because I don't know if you've noticed, the Internet is kind of bad. Like we've built -- we've kind of built a bad Internet in a lot of ways. Like every day I have to use banking apps. I have to use like all of these -- these SaaS services. All these things I have to use for work or personal use. It's like, kind of sucks, honestly. And like, we can do so much better. And some of that is going to require us thinking very purposefully about the code that we write. But a lot of it doesn't have to. Like a lot of that we can offload on to compilers and tools and things that can just give us the DX that we move and the mental models that we love. But it's gonna -- like I think stuff like this is great because it takes a lot of that off of our immediate purview and puts that into something like the compile tool. And I think this is just really powerful. I'm excited to see -- honestly, just looking for a better website. I'm tired of shitty websites. There's so many tools we can use to do that. Million is just one thing in the toolbox. And I encourage people to dive deep, if you haven't already, into the world of performance optimization. React, Solid. You're just YOLOing with web components. Think about performance. If you measure performance and you get an idea of why these things are slow, then you start to realize that maybe they could be better. You just have to think about it. I -- I think that's just the secret code at the end of the day. Think about it and spend a lot of time understanding it. And from there, you're just gonna build better stuff all the way around.
JASON: Yeah. And I think the thing that I am most excited about is that it -- it feels to me that, you know, in the same way that we used to have big conversations about mystery meat navigation. I don't know if anybody but me is old enough to remember that section of the Internet. But there were these big conversations about like, you know, don't hide your buttons. Don't make the NAV hard to find, whatever. And we sort of converged on a, like, standard for what -- what a lot of the components should be. And the way that we approach that led to things are more predictable. You kind of know there's gonna be a hamburger NAV. You kind of know things are at the top or the left most of the time. You kind of know what a button looks like and most of the time things are true. That wasn't the case 20 years ago. People were making things up going along. What it feels like, we have hit critical mass for what a JavaScript-powered app can be. And we're start to be see consensus, not necessarily in implementation, but in measurement, of like how do we make this good? You know? We've got stuff like the Core Web Vitals coming out. Time to interactive is a big deal. And we're starting to accept that it doesn't really matter what the developer experience is if the user experience is terrible. And that is leading to the library authors and the framework authors really focusing down on improving those metrics. Like make it good for the users. And hopefully don't damage the developer experience along the way. And I think that is the sort of focus that the base level that we need so that we as individual developers when we're focusing on making something really good for our users, we don't have to understand the entire science of the browser to make this work, right? We don't need a Master's degree in computer science to build a good website. We can do it by using the defaults because the frameworks are giving us good defaults. I think this is so exciting about if you ship a Preact site, it's a good experience by default. Ship Astro or Qwik, it's a good experience by default. And hopefully that will become more true about frameworks like Next and others where it's not necessarily true by default, but you can do it with a little bit of work. I think they're putting the effort in to make it so it will be good by default. So, yes, as developers we can never stop learning or expanding our own understanding of making things better. But put the pressure on the tools to make decisions that are good for the users. And make sure that those decisions are baked into the framework as defaults. It's really interesting to see -- I don't know. It feels like we're going that way again.
CHANCE: Preach. I'm excited that we're thinking about it. Someone asked about resources. I was going to say, web.dev is great. There's so much great content around performance, around everything. If you want to get into the weeds about how the browser works and how it optimizes ins it own right, that's a really great start. The React docs have added some performance documentation too. If you are building on React. There's a lot of good stuff there. Probably the biggest recommendation I can make is learning how your DevTools performance tools work. That was something I didn't really understand for a long time. But the network tab and the performance tab are highly, highly under-utilized for measuring core performance.
JASON: Where should somebody go for that?
CHANCE: The Chrome -- I think web.dev even has some documentation on this. I don't have anything off the top of my head. But let me see if I can find something.
JASON: Let's see if there's... it does look like there's some DevTools stuff on the Chrome docs.
CHANCE: Yeah, they should have some docs.
JASON: I feel like -- there are people who are really good at using them. But I don't know if they've written up a lot of how to use them. Does Harry Roberts have DevTools stuff?
CHANCE: Okay. So, there is a blog article in -- on the Chrome for Developers blog called "Analyze Runtime Performance." And this one appears to dive into the performance tab. So, I think that might be a good place to start. Again, I'm sorry, I wish I had these at the ready. But I would say probably everything you're gonna need to know on the DevTools are, A, in the DevTools themselves if you just play with them. I think some of it's pretty intuitive even. You can sort of play around and figure out how it works. But as you start to see these really complex graphs and flame charts, that's where you're going to need to dig into the docs a bit.
JASON: Absolutely. And don't get overwhelmed by this stuff. There are a million things it can do. The firebrick instinct when you see it is to run away screaming. I know that's what mine was. But ultimately, a lot of this information is useful if you're looking for it. But you can kind of ignore it to look for other key things to see what's happening. And so, looking at a page like this that will kind of talk about what each of these sections is and why it matters can be helpful for ignoring the things that aren't relevant for the thing you're trying to solve right now.
CHANCE: Yeah. And this isn't maybe relevant to the performance DevTools, but performance just in general. Like I said, there's a lot to think about. And Ryan Florence has a really great talk that he gave at ink it was ReactConf, I just dropped it into the chat. You can look it up. It's called "When to Fetch," and everything that has to do with data fetching as it relates to performance. And data waterfalls and things that are probably slowing down your app more than rendering is. Especially if you're using a component-based system and you don't have -- you're not using tools like either React Query or some framework that handles and optimizes fetching for you. This is a really great sort of lower level intro to how we should think about data fetching. And I think that's a huge, huge part of performance. So, yeah. There's a lot of different angles. But if you really want to learn, like I said, the first step is just acknowledging and thinking about it. And finding resources that dive into the topics. Because they're -- it's really important that we get this right if we want to really make a better web.
JASON: Awesome. All right. Well, Chance, I think that's about all we have time for today. So, let me drop another link to your Twitter. Let me drop another link to FrontToBack. Anywhere to go to follow up more on Million or more on you?
CHANCE: Come down to San Diego and we'll talk about it over burgers and beer. That's about all I got though, in the meantime.
JASON: Yes. All right. Well, thank you so much for hanging out. Y'all, this has been a ton of fun. And this episode, like every episode, has been live captioned. We've had Amanda from White Coat Captioning with us all day. Made possible through our sponsors, Netlify, Vets Who Code, and brand new to the team, Nx, thank you very much. And on the site, check out the schedule. We have a whole bunch of fun coming up. We are going to be learning about how -- I don't know what GenAI is. People keep saying that word and I finally decided to ask. Adam Cowley is going to teach me what it means. It's going to be a lot of fun. I have got other episodes that I forgot to put up in time. I will get those up soon. Keep your eyes peeled. And make sure to check out the Learn with Jason YouTube as well. Because we've got a lot more than just the livestreams that were on today. We've got a ton of fun stuff happening on there. So, make sure you go and check that out. This one in particular was a whole loft fun. I got a chance to film an interview in Portland over lunch with Adam Argyle. He's a wonderful person. I learned a lot. You will too.
CHANCE: Love that guy.
JASON: So, Chance, thank you and appreciate you taking the time. Hopefully next time we will have you in person. Our own version of burgers, but in Portland.
CHANCE: Portland is a great town. Smash that like, smash that subscribe, keep that man alive, let's do there. Smash it.
JASON: Smash it. If you do join the channel, extended cuts, behind the scenes. I'm trying to make this stuff work. I'm doing this as my full-time job. Any support is greatly appreciated. And with that, thank you all very much. Have a great weekend. we will see you all next time.
CHANCE: Thanks, guys. Thanks, Jason.
Learn With Jason is made possible by our sponsors: