Qwik Part II With Misko Hevery - JSJ 563
Misko Hevery is the Chief Technology Officer at Builder.io. He is also the creator of Angular.io, known for zone.js, and helped co-create karma. He returns to the show to discuss "Qwik" in greater detail alongside AJ and Steve. No matter how complex your website is, Qwik provides the fastest possible page load times. In contrast to other frameworks, Qwik has special features that make it more user-friendly.
Special Guests:
Misko Hevery
Show Notes
Misko Hevery is the Chief Technology Officer at Builder.io. He is also the creator of Angular.io, known for zone.js, and helped co-create karma. He returns to the show to discuss "Qwik" in greater detail alongside AJ and Steve. No matter how complex your website is, Qwik provides the fastest possible page load times. In contrast to other frameworks, Qwik has special features that make it more user-friendly.
About This Episode
- How Qwik addresses any issue
- Different Qwik features that make it convenient and efficient to use
- Overview of precision lazy-loading
- Introduction to Mitosis
On YouTube
Sponsors
- Chuck's Resume Template
- Developer Book Club starting with Clean Architecture by Robert C. Martin
- Become a Top 1% Dev with a Top End Devs Membership
Links
Picks
- AJ - Vornado heaters
- AJ - Replacement Parts for Office Chairs
- Misko - Flux | Where the world builds hardware
Transcript
Steve:
Hello everybody and welcome to another episode of JavaScript Jabber. Sorry, I'm laughing because AJ was just playing a sound effect that made me laugh. Um, my name is Steve Edwards. I am the host with the face for radio and the voice for being a mime, but I'm still your host and with me today on our panel, we have AJ. How you doing AJ?
Aj:
I'm doing good. I'm coming at you. Wait. Oh dang it. Hmm. You asked me a question
Hello everybody and welcome to another episode of JavaScript Jabber. Sorry, I'm laughing because AJ was just playing a sound effect that made me laugh. Um, my name is Steve Edwards. I am the host with the face for radio and the voice for being a mime, but I'm still your host and with me today on our panel, we have AJ. How you doing AJ?
Aj:
I'm doing good. I'm coming at you. Wait. Oh dang it. Hmm. You asked me a question
Steve:
Well,
Aj:
Yo,
Steve:
I was
Aj:
yo
Steve:
waiting.
Aj:
yo coming
Steve:
There you
Aj:
at
Steve:
go.
Aj:
you live
Steve:
Yes.
Aj:
from Power tools!
Steve:
coming live from Power Tools. That's a... The land to power tools, is that it?
Aj:
It doesn't really have to be a place. I can
Steve:
Oh,
Aj:
just
Steve:
okay.
Aj:
say coming at you live and then I could say jello. I could say running.
Steve:
Okay, AJ's got his own world of where he's coming from. That's fine.
Aj:
Yeah.
Steve:
And as our special returning guest, we have the one and only Mishko Hevery. How are you doing, Mishko?
Misko_Hevery:
I am doing well, thank you for having me again. You guys haven't
Steve:
No,
Misko_Hevery:
gotten bored of
Steve:
not
Misko_Hevery:
me yet,
Steve:
yet,
Misko_Hevery:
huh?
Steve:
not yet. Well, yet being the keyword. No, I'm kidding, I'm kidding. But seriously, and before I forget, we always need to welcome in our studio audience. How you doing everybody? It's always nice to have the studio audience. They give you that feedback and that validation that what you're saying is really awesome. So before we get going, we've had Mishko on before. And I'm sure all of you know who he is. He is quite the luminary in the web development world. But give us a quick background on yourself, Mishko, who you are, what you do, why you're famous, et cetera.
Misko_Hevery:
Ah, yeah, so hi, I'm a CTO of Builder.io. It's a place where we allow you to add visual editing into your website. But yeah, I'm known for this thing called AngularJS, and then later Angular. And I had something to do with Karma, the test runner.
Steve:
Karma, OK. Yes, we have had, just by way of background, we had Steve Sewell from Builder IO on episode 540 of JavaScript Jabber. And then we've also had Mishko on previously to talk about Build Quick on episode 549. So we will put those links in the show notes for you. So in our previous episode, we were talking about Quick. And we wanted to continue talking There were some questions we had and there was more to talk about obviously So before we get off running down that path Mishko if you can just give us a quick overview of what I guess what quick is and what the problem is that it is Trying to solve
Misko_Hevery:
So QUIC is a framework, front-end framework for building websites. And its specific goal that it's trying to solve is the amount of JavaScript that's being downloaded into the websites is way too much at the beginning. And so instead of downloading all the JavaScript, eagerly QUIC tries to be very intelligent about how it streams the JavaScript into the client. So if you've come to a site that has been slow on startup performance, in other words, you come particular button and it takes 15, 20, 30 seconds to get it going, especially on a mobile device and you get frustrated, then quick is the answer, hopefully, for that problem space.
Steve:
So I got a million questions going through my head again. So this is, I guess, the problem coming from a server rendered PHP world in my initial years. The idea with fixing this was that you quickly load everything that comes from the server. So you're HTML. And then you reserve space, I guess, for things that come to be loaded later, such as the JavaScript in the browser, or maybe ads, so that the user is able to see visually, okay, yes, there is a page here, it's not stuck, the website isn't down or something, I at least have something here and I'm waiting for everything else to fill in. So the idea of quick as I understand it is that you can have it all at once and have it load quickly, inefficiently, or am I describing that wrong?
Misko_Hevery:
No, I think it's a reasonable description. Actually, I'm glad you started with a PHP, because I think PHP is just one of many ways that we used to render
Steve:
Sure.
Misko_Hevery:
HTML on a server. And I think what's unique is that it's different than JavaScript. And because it's different than JavaScript, the mental model we had is that we would render HTML on a server, send it to the client. And actually, this was very performant, because clients, the browsers are really, really good at displaying HTML. But the problem we would have is that we have any interactivity, right? So any kind of interactivity that you wanted to have on a page would have to be through JavaScript. And so things like jQuery, where we would pick and choose individual parts. And so because jQuery kind of made it possible to have interactivity, but it wasn't easy in the sense that you had to think about it, right? You had to write half of your code in server-side language, like PHP, and the other half of the code in JavaScript, like in jQuery. interactivity was always kind of limited only when it was necessary. And so these sites actually performed rather well because HTML is fast to render. And the amount of jQuery we could throw out the problem would be always limited because it wasn't trivial to add it. And so the friction was relatively high. And so you would only add the interactivity when it was absolutely necessary. And we went through this transition. We went from what we used to call multi-page applications. to single-page applications. And when we transitioned to SPAs, the mental model was like, you know what? Let's just render everything in JavaScript from the very beginning. And so the way that would work is we would send essentially a blank HTML page, which just contained a bunch of script tags. And these script tags would then execute and render the whole application. And the reason why developers love this is because the mental model got simplified greatly. Like, all of a sudden, you don't have to think about the server language and the client-side language or attaching listeners like that. It's just like one thing, which is the JavaScript app. And inside of the JavaScript app, you can do whatever you want. And voila, it's a beautiful developer experience. And I think this is the reason why SBA is kind of took off. But the problem with this particular approach is that, well, you're sending a blank HTML page to the user. And so the user navigates the page and they don't see anything. And so now you have to wait the whatever, however it takes to run the application until the application is up and running. And so it could be multiple seconds, like, again, 10, 15, 30 seconds if it's a slow connection kind of a thing. And so people said, like, you know, that's not a good experience for the developer, for the users. What can we do to improve? And the solution was, well, we're just going to show them the picture of the site until the application gets ready. And so the idea is you show them essentially the same page that the application eventually renders. We call it a prerendering. And then the application renders normally like it always did. And essentially, at some point, it just throws away the loading page and replaces it with the actual application. And now you have the application running. And hopefully, if the page that you originally showed you replacing with, they look identical, then the user hopefully never even notices, right? And of course, people did improvements on it, saying, well, instead of throwing it away completely, how about we reuse the DOM nodes, and different tricks like that. But fundamentally, that's kind of what's happening, is that everything's just happening in a client, and you're just showing a user a pre-rendered page to entertain them while the real thing actually gets ready. And so the problem with that particular approach is that now you're sending, you're not actually improving the speed, you're just kind of making it look like it's faster. Because you can't really click on anything faster. As a matter of fact, you can make an argument that the page is now slower because sending the HTML was extra data that you have to send. And so now you're sending this stuff twice, once as HTML, once as JavaScript, that knows how to render the same exact HTML. And so this is kind of the world where we've been it. for a very long time for the last, I don't know, 10, 15 years, where we've just been sending essentially everything twice. And we're just kind of hoping that the developer doesn't click on anything, sorry, the user doesn't click on anything until it's actually ready. And Google has kind of noticed this particular trend, and they've been pushing hard on the things like clover web vitals, light speed tests, et cetera. These are all different basically measurements fast your page comes up. And they're trying to influence the developer environments, the developers who say, hey, you need to kind of get better at this. This isn't good enough, especially on the developing markets where the internet might be the fastest and the mobile devices are slow. This is a problem. We need to do better. Sorry, I went off on a tangent over here, I think.
Steve:
No, no, I was just letting you go.
Aj:
That's
Steve:
No
Aj:
good.
Steve:
worries. We can edit out the pause here later. Trying to think where to go from all this. OK, so. How do we say?
Misko_Hevery:
I can talk about how
Steve:
Yeah,
Misko_Hevery:
quick is
Steve:
yeah,
Misko_Hevery:
different
Steve:
that's where I was going to go. OK,
Misko_Hevery:
in this particular
Steve:
so this
Misko_Hevery:
thing.
Steve:
is
Misko_Hevery:
Okay.
Steve:
what we're
Misko_Hevery:
Okay.
Steve:
doing now. How are you trying to address it with quick? OK, here,
Misko_Hevery:
Yeah,
Steve:
let me jump into
Misko_Hevery:
so.
Steve:
the question. I'll do it that way, and then we can go from there. OK, into the edit here. So OK, so you did a great job of describing the way it's been, what people have tried to do, and how to basically get your page more quickly so that the user is not sitting there waiting and waiting. So now that we've identified the problem, how is QUIC trying to address this?
Misko_Hevery:
Yeah, so the quick insight is that we're sending same information twice, you know, once in the form of HTML, and then again, in the form of JavaScript, which knows how to build the HTML. And so this duplication is what we're trying to remove. And the duplication really isn't the problem from the point of view of the amount of code on a wire, right? The amount of bytes we have to send on a wire. I mean, it's a sum of the problem, but that's not really the main thing. The main thing we're going after is the expense of actually executing the code produces the HTML. So what QUIC is trying to do is say, hey, there is all these things that are duplicated. There are things that are already shown up once in the HTML. And then again, they're showing up again inside of the JavaScript. And the problem is that I have to re-execute the JavaScript in order to rebuild what's actually already in the HTML. Can we skip that bit somehow? Can we not do the work that we have already done? If you think about it, the application already ran on a server or during the build time or it's cached in a CDN or whatever. already executed once. And therefore, all of the information is already present in the HTML. Can we just figure out the bits that need to have interactivity and just ignore everything else? Because, well, we don't need to re-render the page. It's already rendered. We just have to be intelligent about how we can attach to the page that's already rendered. And so the quick kind of a trick here is figuring out how not to re-execute code that's already been executed on a server. And so we call this resumability because if you think about it, the way it works is really just like VMs work. When you first launch a VM in a host machine, the VM goes through a boot up process. You can watch the bios come up and the boot up and log in screen and everything. And at some point, you can just save it and ship the saved VM into a different machine. machine. And when you resume it, you're exactly where you're left off. You don't go through the boot up process again. And so the same exact thing is what we're trying to apply to frameworks, which is that if you're thinking about it, the initial rendering of a page is kind of like the boot up process. And the fact that we re-rendered the whole thing on the client again, even though the server just did it, is basically what I call replayability. We're replaying what the server where we were when the server took a snapshot. And so, reasonability is about being able to take that snapshot and then continue where you left off. And as a result, you get to skip huge amount of code. And again, the skipping is really not as much about sending less JavaScript over, which is important. It is more about the fact that you don't actually get to execute all that code, right? And so, huge parts of the application just never execute again on the client. are coming.
Steve:
So the speed is that you're not duplicating yourself. You're keeping, I guess you could say you're adhering to the dry principle, D-R-Y, right? Don't repeat yourself. Just
Misko_Hevery:
Yeah, so...
Steve:
from an HTML delivery standpoint.
Misko_Hevery:
That's exactly it. And I think the speed actually is kind of interesting to talk about speed because when you come to a page, the application has to run from the beginning. It has to render everything, et cetera. And so it's a huge amount of JavaScript that has to execute. The interesting thing about resumability is that no matter how complicated the application is, when you resume it, there is actually nothing to do. The amount of code to run is essentially nothing. doesn't have any code associated with it. The only code that is associated is when the interaction actually happens. So when I click on a button, then I have to execute the code that's associated with the button. But the act of setting up the listener for that button and re-rendering and figuring out what the listener is and all that stuff, all of that stuff is just skipped. And so this is why we oftentimes say that reasonable frameworks have 001 startup performance, meaning like it doesn't matter how complicated the JavaScript that the page is, when you resume it, there is always essentially no work to be
Steve:
OK,
Misko_Hevery:
done.
Steve:
so you talk about resuming. Resuming from what? Resuming from changing a page? Resuming from reloading? So for instance, if
Misko_Hevery:
Ah, so.
Steve:
I bring up a quick page, and you've sent me everything, and I've got all the JavaScript and HTML I need, and we can get into the details of that in a bit, if I refresh the page, is it keeping everything that
Misko_Hevery:
Mm-hmm.
Steve:
was sent the first time so that when you resume, you're where you left off? Or is a refresh actually reloading from the server as normal? where we're keeping this resumability.
Misko_Hevery:
Yeah, yeah, that's a good question. So again, let's go back to a PHP example. When you navigate to a particular URL, we would like to show you HTML, because that's the fastest way to get pixels on a screen for you is to just send you HTML. And so that HTML has to be created. And so it could either be created dynamically as per request, as you navigate, every time you do a navigation that it's created. Or it was done once and it's cached in a CDN, as part of a build process or if you have an SSG website. But the point is somewhere along the line, the application that you have written was executed to build the page, right? And so when we serialize the application into the HTML, so we can send it to the client or maybe store it in a cache or a CDN or something like that, when we do that, we essentially are pausing the application. And so when we get to the client, on the client, from wherever we paused it from. Right? So you can also have a situation. Like, if you navigate to a page and a server renders the page and then you continue where you left off, that's one way to think about it. But you can also think about it like, oh, I navigated to a page and I actually server rendered it once, but it saved it in the CDN. And now the subsequent 10,000 navigations are all just getting the CDN. So you can essentially have free copies of it. Right? So it's not like a one-to-one that you of a server present, you can just resume out of a copy inside of a CDN as well.
Steve:
OK, so I assume that somewhere in your quick code or your quick configuration, however it works, and I apologize because I haven't had a chance to play with quick yet. I'm not very quick on the draw, shall we say. But sorry, I should have thrown a rim shot in there. So you're telling it in your configuration, OK, I have a CDN somewhere that's the front end that's being cached from this. How is it that the app is knowing, OK, CDN so I'm just going to pull from that and that's been cached. Is quick taking care of that or is that something you have to configure within your application?
Misko_Hevery:
So the CDN is not specifically something Qwik cares about. It's just that typically when we deploy our sites, we have CDN to return. If you take your Next.js application and you prerender stuff or you render on the fly as needed, CDN is oftentimes used in front so that every single request is not a separate request
Steve:
Right.
Misko_Hevery:
to the backend. That's a configuration thing that you would do for your application. It has nothing really to do with the framework itself. that framework provides is this capability of, you know, it can run. And at any point you can say, hey, pause right here. In other words, serialize everything you have into the HTML in such a way that if I take this HTML and put it in a different browser, different tab, different, you know, virtual machine, so to speak, I can just continue exactly where I left off. I guess one of the things we should probably talk about is what kind of work do browsers have to do on hydration, right? Like, why do we have hydration? what exactly
Steve:
Well, yeah,
Misko_Hevery:
is happening over there.
Steve:
along the questions, you talk about storing the serialized HTML. Where are we storing it? Are we talking like, you know, local storage? Are we talking, it's all serialized and stored in data attributes and HTML elements? Is it some other storage? Where is all this stuff being stored to be able to pick it up?
Misko_Hevery:
Yeah, so it's a combination of attributes in HTML and a script tag that has a special tag on it, meaning don't execute it, right? Which contains a JSON that contains basically the state of the system, right? So if you look at, maybe we can look at existing systems to kind of compare how they work. So if you look at something like Next.js and React, right? When you navigate to a page, and let's say it's cached in a CDN, it comes to the browser. And so one of the things that you have is that you have a script tag that's called underscore underscore next underscore data, I believe. And that contains the state of the application so that when the application continues on a client, it doesn't have to refetch all the data from the server. That's a form of resumability.
Steve:
Okay.
Misko_Hevery:
The problem with is that it's insufficient. Like yes, that data object prevents the client from having to go to the server to refetch all of the state of the application, so to speak, right? But it doesn't help the framework because the framework also has a state of the state that it cares about. It, for example, cares about things like where are the component boundaries? Where inside of the component are the listeners? What is the relationship between the data bindings in the UI. In other words, if I mutate a particular data or state of the application, what particular pieces do I have to re-render? That's a state of the system as well that typically people don't think about, but it is part of what frameworks need. Usually we think of frameworks as a black box that frameworks does its magic, but if you think about it, the framework has to have this information somewhere. And so the problem we have is that how to serialize themselves. It was not part of the requirements when they were designed. They still need to have a way of recovering this information. Framework can't respond to a click event unless it knows that there is a click listener somewhere and it knows to attach a listener to the DOM. Unless that happens, the page isn't really interactive. And so the question becomes, well, how do the frameworks recover this information? And the answer is, well, they recover it by re-executing the application root component. And therein lies the problem, right? The re-execution of the application from the root component is expensive. And so what reasonability entails is a way for a framework to serialize all this stuff in the form of like additional attributes or additional something inside of the HTML so that when the framework wakes up and says, ah, you clicked on this particular button, it component or something like that without having to execute any sort of, re-execute the application, right? Like you can just directly be like, you clicked on this button, therefore I know I have to do this. But before you can even do that, the framework has to know that there is a button to be clicked on, right? So all of this information basically has to be stored somehow inside of the HTML so that the framework can do its job, right? Just like in Next.js serializes the state of the application inside of the element inside of the HTML. The framework also needs to store its information so that it can just continue where it left off. So it can prep, you know, in the case of an application, what we're preventing is an, is a additional fetch to fetch the data. In the case of a framework, what we're trying to prevent is the need to re-execute the application to figure out where the listeners are.
Steve:
OK, so this brings up another classic web development question. And it said that, you know, the old adage that the two hardest things in computer science are naming things, cache and validation, and off by one errors. So you have
Misko_Hevery:
Yes.
Steve:
all this data in your browser. How do you know or how does it determine when to go back and get more from the server if something was updated in your data or something or the other? Because it seems like, as I understand it, OK, you've rendered this page. You've serialized all this content. state you have all this stuff serialized in the browser somewhere. So the next time it wakes up, they can just run all this code and do its thing. How is it known or determined or is quick told, OK, we've got to refresh this and get this from the server.
Misko_Hevery:
So the answer to that is exactly the same way as you would do it in all the existing frameworks, right? So the way you use QUIC and the way you think about it and the way you build applications is really very similar to just about any other framework that's currently out there, right? That's not the difference. The difference is what happens on kind of the wake-up process. How does the system wake up to get it going? And so that's the unique part of resumability. But the way you would do that is, you'd have a button or something that you would click on and then that executes code that developer wrote and that code says, oh yeah, I need you to go fetch this new data set and this data set has to be stored inside of this data storage location. And then the framework's like, oh yeah, but this reactive data storage location is actually tied to these components and now I have to re-render those components and so on. So that's pretty straightforward. From a developer's point of view, the way you used to, you know, you, you, you call the fetch to fetch data from the server at convenient point of time. You update the storage or the state of the system, and then you expect that the framework will just rerender appropriate parts.
Steve:
Okay, so another question running around the back of my mind here that I've been sitting on is, uh, going back to the idea that you're providing everything that the page needs in order to be interactive most quickly. So with something like an Astro, something I'm familiar with just cause I've been using it myself. Uh,
Misko_Hevery:
Mm-hmm.
Steve:
and we've talked to Fred shot here a time or two, uh, is. You know, Astro generates all your server rendered HTML. And if you want to plug in JavaScript, then you add that component into your page structure, and it adds it as you need it. Now, if I'm understanding you correctly, the idea is that you're sending everything possible from Quicks. So is Quicks sending serialized JavaScript from the front end as part of the initial page load, and then somehow that's being converted? At what point is the JavaScript code enabled run after the page is, is, you know, everything is loaded from the server side.
Misko_Hevery:
It's
Steve:
Yes,
Misko_Hevery:
a lot of questions
Steve:
many.
Misko_Hevery:
in there. OK.
Steve:
That way you can talk for a while.
Misko_Hevery:
So we already have a way of serializing JavaScript. It's just.js file. So that in itself is pretty straightforward. And we don't have to do anything special. And Quick just loads JavaScript in the same exact way as everybody else does. There's a URL, which ends in.js. And that's what browser loads. And everything works. The unique thing about it is that what differentiates Quick solve a particular problem. And that is the problem trying to solve is the framework wants to know where are all the listeners in the HTML. And it wants to know that without executing any sort of client code, because executing the problem with existing frameworks have is that they don't know where the listeners are and so the way you find them is that you literally do an exhaustive search of visiting every single component to see like, do you have a listener? Do you have a listener? Right. And that takes time. And so what Quik needs to solve of like, okay, I have an HTML page. No JavaScript is executing just yet. Where are all the listeners? Like I need to know where to attach the listeners. And the way Quicks solves that is it says, well, I'm just gonna set up a global listener on the root. And I would rely on the fact that, you know, when you click on something, the bubbling of the events will eventually cross the root listener. And therefore that's how I know that you clicked on something. But now you have a set next problem, which is like, great. So I can attach a listener, you know, in the form of an HTML attribute saying, like, there's a button and this button has a listener. But how do I know what code do I have to execute? And so the answer is like, well, that, you know, the attribute itself, you can just leave a URL to the code that needs to execute. So great. Now you click on that. But now there is a next problem, which is let's say you have a button that says add to shopping cart, you click on the button and you know which code to the add to shopping cart button, except that that code has what I would call amnesia, in a sense is like, right, but what item do you want to add? I have no idea. I know how to add items to shopping cart, but you have to tell me where is the shopping cart? What does the shopping cart already have? What item are you trying to add? What price of the item? There's data that is not inside of JavaScript that needs to be stored. And the way existing frameworks kind of deal with this is that if you think about it, the The thing that you attach to the listener is a closure. And closure contains both the data as well as JavaScript. Now JavaScript is easy to download. That's just the.js file. I just need to have a URL for it. That's easy. But the data is hard because it's not like you can take a closure and run JSON.stringify on it. You can't just get the data out of a closure. It's hidden. It's hard to get to. the cool, the amazing, I don't know what the adjective you want to use, the unique part of quick is that we figured out how to serialize the closure. And the reason why that is important is because once you can serialize closure, what you can have is you can have a button that you click on, right? Saying like out to the shopping cart. And that button can execute without the existing, the rest of the application to execute. Because the button just says, well, I need to know what the shopping cart is and I need to know what item you want to add. And I need to know the price and description and all these things. right? But because it's a closure and it already has serialized and captured that information, it can just continue on the client. So on a server, when the initial thing got rendered into the HTML, the code executed that says like, oh, I am rendering a product A, which is like, you know, 995. And the current user has a shopping cart that already has three items in it. And so when it got to the point where the listener got attached to the HTML or to the DOM, it said, ah, okay, and I have to serialize the state of the system. The state of the system is like the name of the product and the price of the product and the shopping cart. And so it serializes all of that. And so when you actually click on a client, it doesn't have to rerun anything. It just says like, oh, there is this closure that contains the information about the shopping cart state as well as the product I wanna add. And so you just have to execute that piece of code and nothing else. And this is where the savings comes from, right? because you didn't have to rebuild closures. You, I mean, the code just said like, oh, I know what the closure is. I'm just continue where it left off. It's kind of a hard thing to get your head around,
Steve:
Yes.
Misko_Hevery:
right? Because we're used to thinking about the problem in a particular way. And this is different. This is very fundamentally different. The best way to think about it is that when you have a closure, which is both data and behavior, QUIC knows how to serialize it in such a way that it basically separates it out. Data goes into the HTML, and the code goes into the JS file. And it can just continue on the client. So for example, attaching a listener, like when most people talk about attaching a listener to a download when you have a button, you want to attach a listener. For most people, the idea that you could attach a listener on a server is preposterous. What do you mean attaching a listener on a server? That makes no sense. You can't attach a listener on a server. But that's literally the thing that's happening in Quik. In Quik, when a server is running It comes across a button and it says like, oh, this button has a listener, great. This button has a listener that goes and increments accounts. The current value of the account is let's say three. So it serializes the three into it and it serializes the information that like this closure is attached to this button. And so when you get to the client, the client can just, doesn't have to do anything because it just waits for you to click the button. And the moment you click the button, the button, you know, the event propagates up, captures the event and says, great, so what was the state of the system on a server when this button got registered, when you registered the listener? And the answer is, well, the count was three. And therefore, if I restore the function with the initial closure value of three, then the code can just execute. I didn't have to pre-render anything else. I didn't have to re-execute anything else on the client.
Aj:
So I mean, this sounds like what we were trying to do back in the day with just jQuery and onClick handlers and the data attribute, right? I mean, that's, that's the whole reason the data attribute was
Misko_Hevery:
Yes.
Aj:
invented so that we could render truth that, you know, that the buzzword, the buzzword was truth and dom.
Misko_Hevery:
Yes, that's an excellent way of looking at it. And I would say that QUIC is basically the runtime performance or runtime characteristics of the jQuery and the data property, but the developer experience of a modern framework.
Aj:
That bad, huh?
Misko_Hevery:
Right, so that's the thing we're bridging.
Aj:
I said that
Misko_Hevery:
Huh?
Aj:
bad, huh?
Misko_Hevery:
Well, the modern frameworks are pretty popular in terms of the developer experience. So like, yes, there's always rooms for improvement, but for the most part, they serve as well. And so my point is like, yes, it's a developer experience of a modern framework that you're used to. So all the bells and whistles and enjoyment and the mental model of building an app is there. But instead of having this slow startup performance due to hydration, due to the fact that the framework has to recover all this information. we take the good old jQuery, put the state inside of data. I mean, it's more complicated than that. I mean, it's not actually in the data and more nuance in there, but that's a good way of thinking about it.
Steve:
Okay, so I'm confused. So when I asked you earlier about loading of the JavaScript, you said, okay, we're loading the JavaScript the same way every other framework does. But you say you're sending an event listener from the server side. So to me, that seems to
Aj:
He's
Steve:
be a little
Aj:
setting
Steve:
of a contradiction.
Aj:
he's
Steve:
Am I missing
Aj:
setting
Steve:
something?
Aj:
the
Steve:
Okay.
Aj:
event listener. So he's doing on click. So there's on click equals. Mega
Steve:
Gotcha.
Aj:
root function and then mega root function has some some data is in the DOM itself, and then it sounds like it's also duplicated and basically a JSON that gets inserted into the script. So the script is being dynamically generated as well as that. The mechanics of it.
Misko_Hevery:
Yes, so the JSON has a state of the system. It's similar to like next underscore data JSON, but it contains more information, not just the state of the application, it also contains state of the framework as well. But yeah, in that sense, it's the same. Now I did say that we load JavaScript in the same way as other frameworks. That's not 100% true. I mean, loading code is just URL and you load code. But the thing that's unique with Quick is that Quick is very good at breaking up your monolithic code base into lots and lots of small chunks. And the reason why that is important is because it's very easy to concatenate chunks together. If you decide that you have too many chunks, it's easy to, you know, up bigger chunks out of it. But the opposite isn't true. If you have one big monolithic chunk and you want to break it up into pieces, that is extremely difficult. And so one of the things that Quik does out of the box is its goal is to create as many chunks as you can possibly imagine. Like the more chunks, the better. Because we can always concatenate them together into a single file if we want to, but the opposite isn't so easy. The reason this matters is because a lot of the, if you, if you think about it, a lot that sends to the client is a duplicate of the HTML that's already in there. Many components on a page are components that execute exactly once. Their purpose is to set up the layout or location of the menu or something like that. There's a huge amount of code in your application that runs exactly once. And guess what? If you have a reasonable framework, then that code still runs exactly once, but it runs exactly once on a server. And if it doesn't have to run on a client, now we have a problem of like, well, why are we wasting time sending the JavaScript to something that will never execute on the client? And so this is where the fine grain chunking comes in so that we can like break apart pieces that are unneeded and don't even bother shipping them to the client. To put it differently, if you think about classical frameworks, they usually have some kind of a root component. And that root component is what's exported in your bundle. And then that root component has references to the child components, which they have references to more children and more children, and so on and so forth. So if you hold the root, you essentially are holding the whole tree. There are tricks for lazy loading so that we don't have to load all the routes at the same time. But if you're holding a root, you're that are currently in the render tree. And that's unnecessary because we know that many of these components will never ever re-render on the client ever again.
Aj:
Now, if I remember correctly, you're doing this like the key thing is that everything is asynchronous, right? And that's, that's
Misko_Hevery:
Yes.
Aj:
why this is so great. Cause you've got this event system that's got central routing for lack of a better term, and then it's going to go and it's going to fetch the pieces that it needs. And a lot of them are going to be in cash. Uh, so, you know, your first load performance is, is better. I guess it's as good as it can get in terms of time to interactive the interactivity on each first click that's never ever ever been clicked before is going to have some sort of latency.
Misko_Hevery:
It's not, because we have prefetching.
Aj:
Well, I, okay. But still, you know, I don't know how the average person uses the web. Maybe they do click on the page, go and get a coffee, come back and then continue. But for me, as soon as I can click the button, I'm hammering it. And then if it breaks, then I'll hit
Misko_Hevery:
Yes.
Aj:
refresh and then I'll wait for all the ads to load and then I'll click the button.
Misko_Hevery:
Well, the beauty of reasonable systems is that the moment you see the button you
Aj:
Yeah,
Misko_Hevery:
can click
Aj:
I know
Misko_Hevery:
on
Aj:
that
Misko_Hevery:
it
Aj:
I know that now,
Misko_Hevery:
now
Aj:
but what about do you do you have some mechanism that disables the button so I can't rage click it or that gives me feedback to let me know that the component that handles that click is loading is that part of the the initial route pack that's always downloaded?
Misko_Hevery:
We're thinking about adding some kind of a CSS when this is happening, so you could do something like that. But the idea is that when you navigate to a page, we know all possible listeners that exist on a page, right? Because it was server-side rendered, and so the server, when it was serializing, is like, oh, I know you can click on this button, then you can hover over this button, then you can scroll over here, whatever. So it knows all the possible things you can interact with the page. And so when it gets downloaded to the client, thing the client does is starts fetching the code associated with those listeners. The advantage is that that code is significantly smaller than the overall application, right? Huge swaths of code were kind of excluded from this because we know that we will not re-render these components and so on and so forth, right? And so as a result, the amount of JavaScript we have to download is So you might end up with a situation where a resumable framework will have one-tenth of the JavaScript that it downloads on initial navigation. And then when you click it, maybe one-tenth of that JavaScript even executes. So it's a huge difference in terms of the amount of JavaScript that has to run. But I want to make a point that no point do you get in a situation where you click on something and you have to wait for JavaScript to load, have are eagerly prefetched as soon as you navigate, right? Or if you go to a tunnel or the standard argument over here doesn't apply because we have this piece of code that does the prefetching. It doesn't execute it, but it does
Aj:
But
Misko_Hevery:
prefetch it.
Aj:
prefetching takes time, right? So unless you're in an office building where you're connected to a nice, juicy fiber connection, when you load a page, that page, every, every request, it has DNS lookup time, and then it has the actual request round trip time. And in the ideal scenario, when you're sitting at a desk connected to fiber, you know, it's, it's countable milliseconds to the point where literally you blink. That, that, about 300 milliseconds to complete a blink. Right. And
Misko_Hevery:
Sure.
Aj:
so literally within a blink, you've got the stuff. But when you're, you know, out at the store, and you need to look up some information about a product or when you're in the car, and you need to, you know, get some information about where you're going or whatever, you know, in the real world scenario, that's not sitting at a desk connected to fiber, or just you're on Wi Fi where the router is, you're, you know, instead of being in the living room, you're in
Misko_Hevery:
Mm-hmm.
Aj:
the bathroom, right? In all of these situations,
Misko_Hevery:
Okay.
Aj:
that round trip time is significant and real.
Misko_Hevery:
So let's kind of go through this and see how this would play out. Let's say we have an application that has a one megabyte worth of JavaScript.
Aj:
Heaven help us.
Misko_Hevery:
If
Aj:
We're
Misko_Hevery:
you had
Aj:
off
Misko_Hevery:
a
Aj:
to
Misko_Hevery:
classical,
Aj:
a bad start.
Misko_Hevery:
what? But it's kind of the app, most of the apps out
Aj:
Oh,
Misko_Hevery:
there,
Aj:
yeah,
Misko_Hevery:
right?
Aj:
yeah, but I think
Misko_Hevery:
So
Aj:
that's
Misko_Hevery:
let's say
Aj:
part
Misko_Hevery:
you have
Aj:
of
Misko_Hevery:
an application.
Aj:
the problem you're trying to solve, though, right? Is that, you know... Yeah.
Misko_Hevery:
Right, so let's go through it. So let's say we start with 1 megabyte worth of JavaScript. Most frameworks that are out there need to do hydration, and therefore they will download 1 megabyte worth of JavaScript. And let's say 1 megabyte worth of JavaScript takes 10 seconds to download. We're a super slow network, right? Let's just go with that thing. So we will pay 10 seconds to download it, and then we have to pay I
Aj:
It would
Misko_Hevery:
don't
Aj:
be
Misko_Hevery:
know how
Aj:
great
Misko_Hevery:
many seconds
Aj:
if
Misko_Hevery:
to
Aj:
it
Misko_Hevery:
actually
Aj:
only took
Misko_Hevery:
execute
Aj:
10 seconds.
Misko_Hevery:
this. Right, so let's say it's a 10 seconds for download and let's say it takes 10 seconds to execute that code, right? So a classical system, from the point you visit the page, the point you get the HTML, there's an additional 20 seconds you have to wait before you can interact with it. Right, so any click before then would be lost, meaning if you click and it hasn't executed yet, that click just
Aj:
Agreed.
Misko_Hevery:
goes into ether, like it's gone. Okay, so now let's go and see what happens in the Quick Vault. So first of all, we talked about this idea recognizes the fact that many of these components are not actually interactable for you. And so as a result, it never sends that code down. And so what we see in the wild is that it's easily 10% of the original size. So instead of downloading a megabyte, QUIC only has to download 100 kilobytes. And the other difference is that it doesn't have to execute it eagerly. So you're not paying now this extra 10 seconds So literally the only thing you have to do is you have to download one-tenth of the JavaScript. So if the other one was 10 seconds, now it takes an extra one second for us to download the JavaScript. Now, imagine you have an HTML that has a button. So you see the button, the moment you see the button, you click on that thing, right?
Aj:
That's how I do
Misko_Hevery:
Because
Aj:
it every time
Misko_Hevery:
we have a global
Aj:
in
Misko_Hevery:
listener.
Aj:
the face.
Misko_Hevery:
Yeah, okay, you should, you should, you should. This is the goal we want, right? So you come and you click on it. So at this point, the event has been registered, the button, the button was interactable. Now, we haven't yet downloaded JavaScript, right? But whether you click on the button or not, the code eagerly starts downloading that 100 kilobytes. Right? And so let's say it takes one second. So after one second, your click listener is now being processed. So there's two things going
Aj:
And there's
Misko_Hevery:
on that are
Aj:
about
Misko_Hevery:
different.
Aj:
four
Misko_Hevery:
First
Aj:
or
Misko_Hevery:
of
Aj:
five
Misko_Hevery:
all,
Aj:
clicks
Misko_Hevery:
at no point does
Aj:
on
Misko_Hevery:
your...
Aj:
that listener right now.
Misko_Hevery:
Right, they're queued
Aj:
I'm
Misko_Hevery:
up
Aj:
rage
Misko_Hevery:
in
Aj:
clicking.
Misko_Hevery:
sequence. But the point is, you cannot... First of all, let's agree that it's already miles ahead of the
Aj:
Oh
Misko_Hevery:
other
Aj:
yeah,
Misko_Hevery:
solution.
Aj:
sure.
Misko_Hevery:
The other solution was
Aj:
Sure.
Misko_Hevery:
20 seconds of
Aj:
Yeah, yeah, yeah.
Misko_Hevery:
misery.
Aj:
I'm not debating
Misko_Hevery:
So we were
Aj:
that.
Misko_Hevery:
way ahead
Aj:
I'm
Misko_Hevery:
of
Aj:
not
Misko_Hevery:
already.
Aj:
debating
Misko_Hevery:
Okay,
Aj:
that.
Misko_Hevery:
so now we're down to 100 kilobytes, which is taking one second. And so you may see a delay for processing, but you're guaranteed when you click that it will be processed.
Aj:
This is
Misko_Hevery:
The reason
Aj:
beautiful.
Misko_Hevery:
why you click 10 times sure, right? If you were in the world where you know that you clicked already and you know that it's going to get processed, you are less likely to click on it multiple times. But let's just go this even further. And that is, we have 100 kilobytes. The problem is we can't do anything until all the 100 kilobytes gets downloaded. One of the things that QUIC can do is break the 100 kilobytes down even further to, let's say, 10 kilobyte chunks. And now we're down to 100 You know, we know from statistical past experience that you are likely to click on this particular button and so we eagerly
Aj:
Where
Misko_Hevery:
will
Aj:
does the
Misko_Hevery:
prioritize.
Aj:
statistics come from? Is that a?
Misko_Hevery:
from existing users actually
Aj:
But is
Misko_Hevery:
using
Aj:
that,
Misko_Hevery:
the site. So as
Aj:
is
Misko_Hevery:
the
Aj:
that
Misko_Hevery:
existing
Aj:
a module
Misko_Hevery:
users.
Aj:
that's a node or is that something that's an Apache plugin?
Misko_Hevery:
Um...
Aj:
Where do these statistics live?
Misko_Hevery:
It's done all on the client. So every time the quick code in the JavaScript runs, it fires a event inside on a DOM. It's a custom event. And then you can listen to it. This is not something that's available out of the box, but it's relatively easy to do, is you can listen on these events. And based on that, you can build up a statistical model
Aj:
But this
Misko_Hevery:
of
Aj:
statistical
Misko_Hevery:
like,
Aj:
model
Misko_Hevery:
what
Aj:
does
Misko_Hevery:
are
Aj:
not
Misko_Hevery:
the...
Aj:
exist presently. I mean, this tool doesn't exist presently. I can't just go include a script tag and then have it and, and require a module and
Misko_Hevery:
We,
Aj:
have it work.
Misko_Hevery:
it exists in the sense that we have it working. It doesn't exist in the sense that we haven't yet released it. So it is something that's coming and we already have it working. So the idea is gonna be that it's just an event and we will provide you with a default service that will collect these events. But if you don't wanna use our service, use your own. I like
Aj:
Well, this
Misko_Hevery:
that
Aj:
was
Misko_Hevery:
you don't
Aj:
the
Misko_Hevery:
have
Aj:
promise
Misko_Hevery:
to use
Aj:
of
Misko_Hevery:
ours.
Aj:
HTTP two, right? HTTP two is supposed to allow the web server to do the analytics and then to be able to proactively push the smallest chunks of data that
Misko_Hevery:
Yeah.
Aj:
the client was going to need and because it was such a good solution and it worked, it would have worked so well and solve so many problems. It was completely ignored. I think it was implemented by one Tom cat module or something. And, and.
Misko_Hevery:
The problem is that the server doesn't have the information. Like, you cannot collect the statistical information on a server. You need to collect it on a
Aj:
Well, but
Misko_Hevery:
client.
Aj:
you can collect
Misko_Hevery:
Because
Aj:
it on the server.
Misko_Hevery:
the...
Aj:
It could, because if you just break everything down in those 10 kilobyte chunks, like you're talking about, you know, if everything is independent, then the server would get on the first request ever, it would get 200 requests, but on the very next request, it would be able to push down a whole bunch of stuff and then only need to get three.
Misko_Hevery:
Well, yeah, but there's a lot more to it than that because first of all, the server just sees requests. It doesn't know what you actually clicked on. So it cannot differentiate whether you clicked on a button or you just hover over it and the client is not proactively trying to fetch the data. It also server cannot really, I mean, it can sort of concatenate things together but it can't do it as well as the framework. The problem here is that you need to have an end-to-end solution. You can't just say like, and therefore the problem is solved. It's like, no, no, no. Server has collected some data. The framework has to know how to generate the data. It has to know how to create the correct bundles. There are many things that have to align before the whole solution works. And I think the problem is that you can't just
Aj:
I
Misko_Hevery:
look
Aj:
think
Misko_Hevery:
at
Aj:
if
Misko_Hevery:
it
Aj:
we
Misko_Hevery:
as
Aj:
took
Misko_Hevery:
one thing.
Aj:
the events from Quick and fed them into ChatGPT, it could do a pretty good job of generating the bundles for us.
Misko_Hevery:
So yes, that's exactly what we want to do, right? Is that we want to take this 100 kilobyte bundle, right? And then break it up into pieces, and then basically say, like, look, there are certain pieces that are more likely to be needed than others. And then, therefore, we can prefetch them in that order. And what that means now is that we can, you know, instead of waiting the 100 kilobytes to download, we just have to wait for 10 kilobytes to download. And now we can process the particular event, right? And so notice how what we're doing here is that, like, we are constantly pushing the amount of JavaScript required for you to process it into a smaller and smaller piece until hopefully we've ended up with the absolute bare minimum that is necessary to process your request. And again, this JavaScript is eagerly downloaded. So yes, if you are immediately clicking the button, then the first time you might have a slight delay, which would always be way, way, way better than what you have in the current systems. But if you take any, the code starts preloading immediately. If you have any hesitation in clicking, by the time you click, the code is already downloaded and we're ready to go.
Steve:
Thank you. Thank you.
Misko_Hevery:
And so this is what makes it both all of one, meaning that the startup performance is really constant for us. It doesn't matter how complicated your page becomes or et cetera, the amount of work we have to do is always the same, which is like, well, set up the global listener. It's always the same thing. We just have to set up a global listener. That's all we need to do. Everything else is just telling the browser, go prefetch all this JavaScript. You may or may not need it. I don't know. But we've already subdivided it into chunks and we already removed all the code that we know you're not going to need because it only runs exactly once on the server. And so the amount of code is less and we don't have to execute anything eagerly. All the code that executes, executes lazily as a reaction to user doing an action.
Steve:
OK, so
Aj:
Thanks for watching!
Steve:
my head is spinning with all of the nitty-gritty details, although I admit I love getting into the details like this. But before we wrap up, as we're getting low on time here, from a big picture, we talked about the server and the client. What are we writing in when we're creating a quick app? Are we writing server-side code in Node and front-end templates in React? Or I think it's JSX, if I remember correctly.
Misko_Hevery:
Mm-hmm.
Steve:
How much code are we writing in? Is it all server, all client? How does that work?
Misko_Hevery:
Yeah, so you're writing JavaScript. You're writing JavaScript that looks very similar to other JSX network frameworks. So JSX frameworks like React or SolidJS or anybody else who uses JSX is very, very similar. We have hooks like use methods, et cetera. The only kind of the big difference from React is we, the resumability requires true reactivity, fine-grained reactivity. So we have reactive primitives to kind of store your data. But other than that, it's very similar. And that's kind of the point is that you can take your existing knowledge of building framework or building applications and just transfer them over to QUIC and you'd be very familiar. You create components, the components of props, use methods to create store, you use JSX to explain the thing. You attach listeners to the JSX to have behavior. And so the way you would develop is very natural. for people, especially for people coming from React or SolidJS, they would just look at it and be like, yeah, very familiar with this. The kind of the innovation is not in how you write, the innovation is what happens underneath. And what's happening underneath is basically a very clever way of breaking up your code into tiny pieces, and then using statistical models to concatenate these pieces into the least amount of code necessary to get the application up and running. and then trying to delay running any sort of JavaScript on the client for as long as possible and not trying to delay it like in a sense of, Astro, which has islands and the moment you wanna interact with an island, you have to run hydration, delay it in a sense of like, we completely skip hydration, we just do reason mobility, right? Like, so what you're delaying is the effect of clicking the button. You're not delaying the code necessary to set up the button.
Steve:
Okay, so but we're talking about the server. So what is the server? Is the server, so if you deploy, do you need to deploy somewhere that sits
Misko_Hevery:
Oh,
Steve:
on a Node.js server?
Misko_Hevery:
yeah. So the only requirement is it has to be JavaScript, right? So any server running JavaScript. So that could be Node, that could be Dano, that could be any of the edge functions. So you have a large selection of things that you can choose from. The key thing over there is that we are sticking to just the bare bones API, like fetch, so that it can run inside of a server's worker, right? So we don't have any API that is Node-specific that We have what these things called adapters, and adapters kind of do the bridging. So we have an adapter for node, adapter for Deno, adapter for Cloudflare, Netlify, and so on. Versel is also on the list.
Steve:
Right, right. Render, I think it was render one of your options.
Misko_Hevery:
I'm not sure it could
Steve:
under
Misko_Hevery:
be, but the community's being, doing a very good job of adding more and more adapters as we
Steve:
Right.
Misko_Hevery:
speak.
Steve:
So speaking of community, that's, you know, that's generally one of the, um, things that can either help or hinder the adoption of a new framework, right? Is how well does the community, uh, how fast does it grow and evolve and how, how quickly is no pun intended is the community contributing things? Because obviously a core team can only do so much, right? So you're dependent upon the community
Misko_Hevery:
Yes,
Steve:
for plugins
Misko_Hevery:
yes.
Steve:
and themes and whatever you want to call it. opinion on the quick community and how it's growing.
Misko_Hevery:
I think the community has been on fire personally. For example, people come in and they brought in vanilla extract, they added adapters for Tailwind.
Steve:
Ooh.
Misko_Hevery:
We're talking about the community right now to designing typed routes so that your URLs are typed with JavaScript as well. And so I think a lot of amazing work is happening with the community. I think Quik has a very different mental model in terms of the execution, not in terms of how you build an application, but in terms of how it executes. I think once people understand it, they become very like, oh my gosh, this is so much better. Why haven't we done this forever? And so they become a very excited community members. And I think we have a lot of those. And so they're paying back by adding lots of adapters, lots of features, et cetera. So I'm super excited about the community. It's actually growing really, really nicely.
Steve:
Alrighty, so if people want to learn more about quick, I believe the URL since quick is part of Builder's quick.qwik by the way, sort of a new age spelling. It's quick.builder.io. Is there any other resource or place that should go for quick resources?
Misko_Hevery:
Now that's the place, from there you can go check out the GitHub URL, the Discord channel, showcase of apps, presentations we've done. This is a good place to start.
Steve:
Excellent. All right. Well, Dejai, do you have any questions before I wrap up?
Aj:
Yeah, yeah, yeah, yeah I do.
Steve:
Sorry, what was I thinking?
Aj:
Yeah, what were you thinking? So... This is why I want to get to this. I don't care if it takes us a little longer as long as we've got time personally. Um, but it quick is solving part of the problem that is, um, I think the most obvious, right? Like you should be able to await a component. This is something that should have been done back when React was created. The fact that React was created and maybe it's because promises weren't standardized yet. I don't know, but the fact that React components are not asynchronous. It just is just mind blowing, right?
Misko_Hevery:
It's not just React, right? It's
Aj:
Yes.
Misko_Hevery:
all of the
Aj:
Yes.
Misko_Hevery:
frameworks
Aj:
But it's,
Misko_Hevery:
don't
Aj:
it's
Misko_Hevery:
have async.
Aj:
mind blowing that where the key feature of JavaScript is async ready that none of the major frameworks have ever done even a half job of, of trying to manage that at all. So this quick is kind of doing the most obvious thing that should have been fairly easy and simple other than the part about the whole statistical analysis. But I understand that. But there's the other part, which is why do we have one megabytes of JavaScript in the first place? Right? Why? And it's not one megabyte. It's three, four, five, 10 megabytes. Right? That's the real situation. One megabyte is highly conservative. We're talking about somebody has an input form to collect email addresses on a landing page. That's one megabyte of JavaScript. And
Misko_Hevery:
Yep.
Aj:
so this is where I wanted to ask you about the the component dot kitchen, the Elix component kitchen, I guess that's the right name for Elix component kitchen. So Elix is this project that I don't know if you click the link on it while I was put it in the chat, but it's this project that's entirely based on UX. There's no UI. It's it's a black and white wire frames, but the UX is a black and white wire frame that's going to be used to connect the components to the computer. And, but the problem is again, you know, whenever, whenever we solve a problem in this, in this world of computers and programming, it's like we only attack one tiny piece of it, and then we re event, reinvent all of the problems that we already knew existed for, for no reason. Right. You know, Dino did this with his package manager. Elix did this by, And so I'm wondering what about something like that? Not just, okay, let's make the load experience great, but let's actually provide, you know, for example, most people don't know that HTML has native combo boxes now and they work. There are some things that Elix does that are a little bit more and we have native calendar widgets that work. Some people don't like using platform tools because they, you know, they would want to deploy an Android and an iPhone app. that disobey both the Android and the iPhone user guidelines to bribe their own custom experience. And they kind of, you know, do the same thing between the browsers where ignore the Chrome UI guidelines, ignore the Firefox UI guidelines, ignore the Safari UI guidelines, and just create something that violates them all equally. That's the calendar widget. End of rant there, sorry, that was a tangent, but I hate the calendar widget story. But there's a lot of things that Elix Component Kitchen gets every possible user interaction and experience that you're going to have in 99.9% of all your sites could quick provide something like that so that we have good components that are built asynchronously and that work correctly using the native platform where possible.
Misko_Hevery:
It's a very complicated long question. I think our philosophy is that we, Framework's job is to make it easy to build things. And so, to easy to build things such as the Elix component kitchen, right? So our job necessarily isn't to have a better component library, it is to provide it easy for somebody else to build something like component kitchen and make sure that it doesn't end up Right? I think that's
Aj:
it's still
Misko_Hevery:
it.
Aj:
going to end up with
Misko_Hevery:
Yeah.
Aj:
one megabyte of download because someone we don't we don't need 100 million implementations of these things we need a few experts to build good implementations that work and that have you know you've got you've got the history and the clout to back it up you know if you if you push something i mean you don't
Misko_Hevery:
Wait.
Aj:
have billions of dollars like microsoft but you've got
Misko_Hevery:
But I'm confused, hold on. I mean, the point of the framework is to make sure that it can break up your application to tiny little pieces. That includes the component widgets. So even if the component library in question is a megabyte by itself, QUIC will make sure that only the absolute bare minimum of that code gets downloaded to the client as necessary. That's kind of the point and the promise
Aj:
So,
Misko_Hevery:
of QUIC.
Aj:
but, but I could use a react component and quick is going to figure out how to break it up even though I didn't build it with quick.
Misko_Hevery:
Well,
Aj:
Well,
Misko_Hevery:
no, it has to
Aj:
that
Misko_Hevery:
be in
Aj:
that's
Misko_Hevery:
quick,
Aj:
what I'm
Misko_Hevery:
right?
Aj:
saying is if we have to go back to the drawing bar board on everything, except for the one problem that's being solved, how much better off are we really?
Misko_Hevery:
So then we should really look into tools such as Mitosis, which allows you to write something once and generate the native code for all the different platforms. So the idea with Mitosis is that you can write
Aj:
Wait, wait, wait, nobody
Misko_Hevery:
such a
Aj:
knows
Misko_Hevery:
thing
Aj:
what
Misko_Hevery:
like
Aj:
mitosis
Misko_Hevery:
component library.
Aj:
is, especially not me. What's mitosis?
Misko_Hevery:
mitosis.builder.io. And the idea is that you describe declaratively your component and it creates a quick implementation, the React implementation, the Angular implementation, the Svelte implementation, and so on and so forth. So that you get native components for all of these different platforms.
Aj:
I mean, I'm skeptical because look at Xamarin. And the other attempts to do this, usually trying to do everything generically rather than doing one horizontally trying to do everything generically versus vertically trying to do one system perfectly vertical systems tend towards perfection horizontal systems tend towards well by definition fragmentation.
Misko_Hevery:
Are you describing like, you know, Apple is vertically integrated and so they own everything and as a result they have a really smooth UIs? Is that kind of
Aj:
Well,
Misko_Hevery:
what
Aj:
yeah,
Misko_Hevery:
you're getting
Aj:
sure.
Misko_Hevery:
at?
Aj:
I mean, if, if you, if you say, okay, well, we have mitosis, but it means a bunch of inexperienced people that don't know what they're doing can use a tool that generates kind of wonky, uh, components for lots of different frameworks that don't take advantage of the specifics of the framework. I mean, maybe you do, maybe for every single one of these frameworks, you've figured out every possible way to fine tune, you know, translate, but, so Xamarin for those that don't know was the iOS Android toolkit for So you write C sharp code and it was going to build you your Windows phone. That was the idea behind it back when there was the Windows phone. It was to get people migrated over to C sharp. So it was going to build your Windows phone, your Android phone, your iPhone. But the thing is you, you, whenever you have a system like this and you see this with SDKs, right? You go on GitHub and you want to get an SDK for node for something. It turns out it was generated from an XML schema. You look at the code. It's all nonsense generated stuff. You don't get good quality.
Misko_Hevery:
Mm-hmm.
Aj:
Idiomatic code when you're using something that's generating horizontally And this could be an exception to
Misko_Hevery:
So.
Aj:
that. I just I haven't seen that
Misko_Hevery:
So I think my point is that like the component library is outside of the scope of the framework, right? So like frameworks need to provide the primitives and then you build other things on top of it. However, you're talking about this vertical integration and I actually wanna make a point about that, which is that if you look at existing systems, like for example, React and Next.js, React knows how to render the UI and Next.js knows how to do the meta frameworks and do server-side rendering. isn't a system that knows how to do the whole thing end to end. Right?
Aj:
Look
Misko_Hevery:
So
Aj:
at
Misko_Hevery:
like
Aj:
the
Misko_Hevery:
React
Aj:
state of
Misko_Hevery:
is...
Aj:
modern web development try to load any
Misko_Hevery:
Yes,
Aj:
web page
Misko_Hevery:
and so...
Aj:
other than Twitter Twitter is the only web page that works these days
Misko_Hevery:
But the point is that React has no opinions about bundling. Neither does Next.js. And because of that, you can't take advantage of clever ways of doing bundling. Whereas if you look at something like QUIC, QUIC doesn't just say, oh, we only care about rendering. QUIC is like, no, we care about rendering. We also care about server-side rendering. We also care about bundles and optimizing those bundles. And we also care about code splitting. and reasonability, like we basically by owning the whole problem end to end, you can get to much better
Aj:
3
Misko_Hevery:
solutions. So I think the trouble with the current ecosystems is that the existing frameworks due to historical reasons, they basically said, we only care about rendering and not about bundling and not about server separate rendering and not about restoring the state from the HTML or any of those things. all these things. It can do things that other frameworks cannot achieve because the bundler knows how the runtime works. And as a result, the bundler can do things that can't be done in other places because certain assumptions can't be verified unless the runtime is in on it, so to speak, on being able to consume these bundles.
Aj:
Yeah, I mean, I agree with you. I just
Misko_Hevery:
So
Aj:
think.
Misko_Hevery:
I'm just arguing for
Aj:
I
Misko_Hevery:
vertical
Aj:
just,
Misko_Hevery:
integration.
Aj:
I just think, take it, take it the next step. I mean, take, take what elix components did and then fix it so that, that, that there it's asynchronous and it fits into the model, but, but take that, you know, perfection, take that we don't need 600 million inputs created out of devs. We need inputs first and foremost to be using inputs because that's how the that it works as opposed to everything created out of divs and then your input doesn't work. Right? If you don't provide people with something, they're going to recreate the same problems. Now granted, that one megabyte or five megabytes is going to be a lot more palatable, but you still have this problem of, okay, now the page loads, it still doesn't work.
Misko_Hevery:
one problem at a time,
Aj:
I,
Misko_Hevery:
sir.
Aj:
I, you know, I, I just, I'm, I'm, I want what you're saying is exciting. And I'm just, I don't like react. I hate react. I think it's a terrible design pattern. I mean, I think you maybe kind of get that coming from the angular world where, you know, the design pattern is
Misko_Hevery:
I actually think
Aj:
better.
Misko_Hevery:
React has lots of cool things going for it. I actually am kind of a fan of React. One thing that's going for it is it's very simple. The mental model is extremely simple in React. And that's
Aj:
is
Misko_Hevery:
a good thing.
Aj:
this whatever okay okay but it not now I've lost what my actual
Misko_Hevery:
Now I derailed you.
Aj:
no no I derailed myself but but um Hold on, give me two seconds or three or
Steve:
Hey,
Aj:
five.
Steve:
edit quick edit here. AJ, I gotta get going on about 10 minutes. So
Aj:
OK, OK, I'll.
Steve:
considering how long you do picks, we need to go in here pretty quick.
Aj:
All right. I'm, I'm, uh, pretty, pretty close to today. Oh, okay. So what I was saying is that I hate react, but I love the idea of quick. I wish it was something more like arrow or like view, but I love the idea of it. And the warts of reactor may be worth getting over for this benefit, except that one still has to go re-implement all of the components. So if I saw something that was, you know, my, my perfect, I think would be something like arrow, elix and quick. It has the build concerns and latency performance concerns of quick. It has the UX that is guaranteed to work of elix components and has the super easy intuitive syntax of arrow. And if you could mix those three things together or view, If you could mix those three things together, that would be perfect. But if I could only pick two, I want to pick perfection, right? So I want to have the loading be perfect, which is what quick is trying to do. And probably will do, especially with the statistical analysis. And I want the page to actually be guaranteed to work that when a user clicks something and the JavaScript is there, that it actually does the thing that it looks like it would do and that the developer wanted it to do, which is what Elix components gets perfectly. cannot use an, an Elix component and have a bug because every component is atomic unit tested and the components will work. So unless you style it, you know, when you layer the UI on top of it, if you style it terribly, you could probably get it so that things visually appear, not where they are in such a way that you could cause a bug. But if you just put colors and shadows on it, you, it will behave perfectly. And that perfection is what I want. teed works every time in the face.
Misko_Hevery:
I was just gonna mention that there is a project that kind of was trying to do this called papanasci.js.org. I pasted it in a chat for you. And the idea is that it's a widget library that through my TOSOS basically generates for all of the common frameworks out there. And so, you know, my
Aj:
does
Misko_Hevery:
hope
Aj:
do they
Misko_Hevery:
is that
Aj:
work
Misko_Hevery:
we can...
Aj:
because elix components
Misko_Hevery:
Believe they work, yes.
Aj:
work and that's that's what's exciting about it is that they are they're proven to work but go on
Misko_Hevery:
Right. No, I was just gonna say that like, I think this is the future, right? Where we are, I think we're kind of stuck in terms of innovation because of all the existing ecosystems that are already out there, right? And one of the biggest ones is widget library. By the way, as a side note, QUIC can use React widgets, but that's a separate discussion. And so building our widgets in a way that is not dependent on a specific framework, I think would really help being able to have a lot more innovation happening in our industry. Because right now innovation is stifled by the fact that, right, but the thing that you have to undertake is not just a framework, you have to undertake many, many other pieces as well. And so having projects such as Papanasio.js and Mitosis kind of help with that.
Aj:
Well, this is interesting. So I'm gonna take a look at this. But how in the world are they making it so that it's both asynchronous for QUIC, but synchronous for React?
Misko_Hevery:
That's details. I mean, if you're asynchronous, if you write something synchronously, then let me say I have to play. You don't have to change your mental model when you develop code in QUIC. QUIC just naturally inserts the asynchronicity into the system. And so, yes, you can have that. Sorry, I'm not really explaining it, but
Aj:
But things
Misko_Hevery:
yes,
Aj:
have
Misko_Hevery:
it's
Aj:
to
Misko_Hevery:
possible.
Aj:
be decoupled enough,
Misko_Hevery:
It
Aj:
right?
Misko_Hevery:
kind
Aj:
Because
Misko_Hevery:
of does it.
Aj:
if it's not decoupled, if you don't have good solid, you know, the solid principle design code, then you can't you quick isn't going to be able to solidify non solid code. It's not going to be able to de spaghetti spaghetti components.
Misko_Hevery:
Yes, but keep in mind that QUIC controls the components. And so QUIC can force a lot of asynchronously through the components. It might not be able to dis-bagatify the rest of the application, but it can certainly make sure that the components are lazy loaded. And so that alone significantly reduces the number of monoliths you have in your system. And so yes, you can still do things to mess things up, but you're in a much better position
Aj:
Yeah, if you
Misko_Hevery:
out of
Aj:
build
Misko_Hevery:
the box.
Aj:
with quick, then you won't be able to create the kind of intra dependencies that cause components to not be coupleable because you're choosing quick, so you're choosing decouple ability
Misko_Hevery:
Yes.
Aj:
by default.
Misko_Hevery:
I'm actually going to say it slightly differently, which is that if you choose existing frameworks, because they're synchronous, they tend to cause coupled code. And so it's kind of the frameworks that need to fix themselves first before the developers can fix their code.
Aj:
Cool.
Steve:
All right, so with that, we're going to wrap this up. I have a hard stop coming up here. And thank Mishko once again for coming to talk about QUIC in incredible detail. So we'll move on to PICS. PICS are part of the show where we get to talk about things we like that may have absolutely nothing to do with tech or web development, or could have. We'll leave that up to the picker. So AJ, we'll start with you.
Aj:
Wait, I thought you said you had a hard stop.
Steve:
Yes, I do, but I'm gonna, we gotta get it done anyway. I can put it off for a little bit.
Aj:
Okay.
Steve:
It's a semi-hard stop, let's put it that way. End edit.
Aj:
All right, let me let me pull up here what I've got. So, um, Oh, I did not mention the tornado heater, uh, last time, but I, I actually forgot to turn it on and just getting a little bit chilly in here, but I am in love with the tornado heater because it's really quiet. So for example, it's on right now. It's heating up the room. Can you hear it? No, you can't. If I put it on high, I still don't think you'd be able to hear it through the microphone. I can hear it as the ambient noise in the room on, on low. I can't hear it as ambient noise in the room and it works great. Yeah. It's five times more expensive than the cheapo, you know, Walmart heater, but the Walmart heater, whether it's on high or low, it's like, you know, you can't record a podcast with that on, but the tornado space heater. I just, I'm just absolutely in love with it. I can't believe that it is so effective at heating up this space. It's a 10 by 18. the limits of what it can heat up and I do have an oil heater that I keep on low but between but but anyway the tornado just makes a huge difference I'm super excited about tornado I did get the one with the remote but I got it open box so I didn't pay the exorbitant price for it also for for people who have office chairs which is probably just about everybody that's listening to this podcast or that aspires to be someone who uses an even more of everybody, if the previous didn't. There is this place called officereplacementparts.com and they can give you a cylinder for a chair that actually has a warranty. So unlike Amazon, where all of the sellers pop up, are there for three weeks, claim a lifetime warranty, and then aren't there in six months when you're like, hey, this thing doesn't work anymore. So the actual website for officereplacementparts.com com is horrendous. It is so terrible. You would never use it if you didn't have to. But if you call their phone or it doesn't even have the right information on the website, but if you call their phone number, you can talk to a real human. And the real human has the catalog with all of the actual information that's important for someone who's tall or fat or tall and fat. Like how many pounds is the cylinder rated for? How tall is it? What's its offset? Which if you want to be able And so the Amazon's cylinder suck because as you know, after six months, maybe a year, if you're lucky, they start, you know, decompressing and they don't work anymore. And then you got to replace them again. And so I'm just, I'm super stoked about the, um, the stuff that I've been able to get that the, the replacement I was able to get from this place, because maybe it won't last more than six months, but it has a warranty. and a person I can call and that I've actually had an email with to confirm that this is the right cylinder for this chair for my weight and height and so you know even if it does break I get one for free next time so I'm stoked about that stoked
Steve:
Oh, I so need to call this place. I need a cylinder in a bad way for my chair. It's about 12
Misko_Hevery:
Thanks for
Steve:
years
Misko_Hevery:
watching!
Steve:
old. So yeah, I definitely need one. Half the time I'm picking myself up again because it keeps dropping
Aj:
Well, the
Steve:
down.
Aj:
other thing that you need to know about is the I don't know what they call it. It's like cylinder separator or something. The one I got was the office owl cylinder removal tool. It's it's 14 bucks and it includes a crappy cylinder that you probably don't want to use, but it makes it so you don't have to use the pipe wrench. And if you don't have to use the pipe wrench, then you don't have to damage the cylinder that you're taking out further just in case you do have to put it back in. Once you use the pipe wrench on your chair cylinder, you can't use it anymore because it creates marks in the metal that then it won't attach to the chair properly and won't decompress properly down into the base. So this little kit is pretty easy and simple to use. You just put the top one on all the way at the top and keep it loose, twist it so the screws don't align, and then put the bottom one on tight and then you put screws through it. And if you see it, you'll understand. And then the chair pops off. So you're just creating pressure by, you know, using the hex tool to screw a screw on either side until the chair pops off, makes it really easy, doesn't damage it. And then if your replacement cylinder has a nub, that's a different size where it's either too short or too tall so that it's either hitting the nub and then causing the chair to go down or it doesn't hit the nub and when you hit the release, then nothing happens. You have to take the new cylinder off. I've become an expert on office cylinders and the, and the last, well, on Saturday. So if you need any help, just, you know, give me a call, but, um, yeah, super stoked about that stuff. And then as per usual, um, if you want to, uh, follow my no nonsense, um, uh, hopefully good software engineer. Well, I, I know it's good software engineering advice, but hopefully you'll like it, um, underscore, I'm sorry, I'm sorry, I'm sorry, I'm sorry. score beyond code on Twitter. If you want to follow the rants and whatnot, live streams are cool. AJ 86 on YouTube and Twitch.
Steve:
So CoolAgeA6 is where they can contact you for help with chair cylinders too, right?
Aj:
Um, it doesn't matter how, how they contact me for help with chair cylinders. I think I'm, I think I'm going to take, I'd made a little video when I did it. It's about five minutes long. I think I'm going to upload it on YouTube after some light jump cut editing. But, um, yeah, and you can follow if you want the hot takes, you can follow me on Twitter, but I don't recommend you do that because you'll probably be offended and just unfollow me.
Steve:
All right, so my turn next. I will go with the dad jokes of the week, which are, as I always like to think of, the high point of any podcast episode I'm on. So, when I was 16, I got one of my first jobs and he was telling me about one of his first jobs and he said, when I was your age, my first job I worked at, I had over 500 people under me. And I said, wow, did you work in a big corporation? He said, no, I mowed the lawn in a cemetery.
Misko_Hevery:
you
Aj:
That was perfect.
Misko_Hevery:
Very nice. I'm gonna add that to my list. I got a dad riddle for
Steve:
Yes,
Misko_Hevery:
you.
Steve:
yes, please.
Misko_Hevery:
It has wheels and flies. What is it?
Aj:
flying
Steve:
I'm.
Aj:
saucer.
Misko_Hevery:
A garbage truck.
Steve:
Very good, very good. I have heard that before, but I could not recall that. Thank you.
Misko_Hevery:
Ha ha
Steve:
I always
Misko_Hevery:
ha.
Steve:
love it when people bring the dad jokes. And then yesterday, I gorged on 14 cans of alphabet soup. Don't ask me why. I ended up having a crippling bowel movement.
Aj:
vowel movement is that
Steve:
Yes,
Aj:
we said vowel
Steve:
yes, vowel, yes, rhymes with
Misko_Hevery:
Ha
Steve:
bowel.
Misko_Hevery:
ha ha!
Steve:
And then finally, you know, we always talk about having side hustles. And so I recently opened a school to teach people the art of clairvoyance, but it was shut down due to unforeseen circumstances.
Aj:
Ha!
Steve:
You know, that's like the one where I went to see a clairvoyant, there's another term I'm thinking of, a mind reader, or somebody who can see the future. What's the term? Anyway, I knocked on the door and she said, "'Who is it?' So I left."
Aj:
A medium.
Steve:
Right? Because she didn't know who it was.
Misko_Hevery:
Yeah,
Steve:
OK.
Misko_Hevery:
I get it. I get it.
Steve:
All
Misko_Hevery:
I
Steve:
right.
Misko_Hevery:
get it.
Steve:
So moving on, MISH code. Do you have any picks for us?
Misko_Hevery:
I do. Believe it or not, I'm actually originally a hardware engineer by trade. I studied computer engineering. And so every once in a while, I like to tinker with hardware. And I discovered this cool website called flux.ai, which kind of is like the Google Docs of hardware design, where you get to put your chips on, you design a PCB, lay out the parts, you can emulate everything. So it's a pretty cool way of designing your simple hardware which I think is fun.
Steve:
Cool, yeah, that's a pretty neat looking site. Oh yeah, that would be fun. I am completely ignorant when it comes to hardware, stuff like that. I think a Raspberry Pi scares me, although I haven't tried to mess with one. So yeah, that looks like fun. Looks like a nice little drag and drop UI that you can do all kinds of stuff.
Misko_Hevery:
Yeah,
Steve:
All
Misko_Hevery:
check
Steve:
right.
Misko_Hevery:
it out.
Steve:
All righty, so with that, we will wrap this episode up, another long one, but tons of great nitty gritty info. Before we go, Mishko, if people want to contact you and yell at you or give you money or ask you questions, where's the best place to do that?
Misko_Hevery:
I think Twitter at at M. Hevery. M-H-E-V-E-R-Y.
Steve:
Alrighty, we will put that in the show notes for your viewing and clicking pleasure. With that, we'll wrap it up. Thank you once again for coming, Mishko. It's been a pleasure talking to you and learning all about Quik. And as we mentioned, we'll put in the show notes all the places to learn about Quik. And with that, we will wrap it up and we'll talk at you next time on JavaScript Jabber.
Qwik Part II With Misko Hevery - JSJ 563
0:00
Playback Speed: