Qwik for Instant-Loading Websites & Apps

Qwik Demonstrations

Miško Hevery

Miško Hevery

Qwik Creator (Previously Angular)
Qwik for Instant-Loading Websites & Apps

Check out a free preview of the full Qwik for Instant-Loading Websites & Apps course

The "Qwik Demonstrations" Lesson is part of the full, Qwik for Instant-Loading Websites & Apps course featured in this preview video. Here's what you'd learn in this lesson:

Miško demonstrates how Qwik renders an application without sending JavaScript over the network. Based on user interactions, required JavaScript bundles are delivered to the client as needed.


Transcript from the "Qwik Demonstrations" Lesson

>> Let's do a kind of a quick demo of what Qwik is. First of all, this is a site that has many demos on it, but you can think of this site as a cohesive single application, right? So it's a single app that has many, many different sites on it, many different pages on it.

And the reason I want to point this out is because there are many components on a page. So in this particular case, there is a component that does the header, that does the footer. Let me scroll, there's a footer on the bottom. There's a component that renders these things and you can see all these components in the DOM.

Every time there's a component, there is a qv. Let me get the font bigger here, how's that? So every time you see a qv in the DOM, that means there's a component in that location. And this is what we mean by the framework serializes sufficient amount of information into the HTML so that you can reason about the application, right?

So by looking at these comments, the framework knows where the components started. And so we will have to re-render something, it knows, don't go there, that's a separate component, or go here cuz that's the same component. And all this information is present. Now, what's interesting about it, let's go to the Network tab.

So I have vite filtered out. So let me refresh this. This is running in dev mode and so there's hot module reloading and so the beach shows up. So I'm just gonna filter out vite and say pretend vite is not here. And I'm only interested in the JavaScript.

And so the thing to kind of see is that, the framework kinda looked at this page and says, you don't need JavaScript for this page, there's nothing here that's interactive. And so no JavaScript got sent, the state of the system, this is the serialization, right, is basically serialized nothing.

This is for prefetching. This is div that doesn't count. Let's see what else is in here. This is for dev mode error handling, this doesn't count. This is also error handling for, okay, so a bunch of these scripts here are only for dev mode and they're actually not doing anything in, these three scripts would not be in production.

And the vite wouldn't be in production and this is just prefetching of code that is needed. But as far as everything else, there is no JavaScript in here. So let's go to Hello World and Network tab, same exact thing, no JavaScript, right? Now, let's go to a Counter.

So a Counter requires an alert. So if I click on Alert, an Alert comes in. And if I hit Increment, I can increment the number over here, right? And that's kinda cool because, notice what happened, there was no JavaScript. And then when I hit Increment, the JavaScript showed up.

And it's kinda the magic of it, right? Which is that, let's see, can we show preview? Here we go. The only thing that showed up is the code for incrementing and then the framework itself. And again, this is a dev mode, and so the framework here is huge, I think it's like two megabytes or something.

In production, the framework is only about 20 kilobytes. But because of all the comments and docs, and etc, it's pretty big. But it's about 20 kilobytes in production. And so when I click on the second button, more JavaScript shows up. And in this particular case, let's look at the button by itself.

If I click on the Alert, the only code that showed up is literally just the alert. The framework looked at that and said, as a developer, you asked me to do an alert. And so the only code I need to ship to the client is just the alert.

And in this particular case, the framework just basically said, not only do you just need an alert, you don't even need the framework. So when I click Alert, the framework doesn't even show up. The framework only shows up once I hit Increment, and now the items go up.

This is one of my favorite demos which shows, again, no JavaScript. And if you scroll to the bottom, there is a clock that updates every one second. And notice, the moment I scrolled it into the position, the clock showed up. Let me show this again, so no JavaScript.

The act of scrolling this particular thing into view is what made the clock show up. And so there is JavaScript that updates the clock. And the framework does the updating. Now we talked about tree shaking, let me go back actually. If I go to the counter and if I look at the serialized state, here's the JSON, you will see that there's 0 here, represents the 0 over here, right?

The state of the system is serialized in here. The subscriptions over here talk about the reactivity graph, right? So it understands the clicking this button needs to update this particular thing over here. So that's straightforward. Now what I find interesting is that, if I go to the Hacker News, the system looked at it and said, actually, I don't need to serialize anything, right?

Because, yeah, the data came from some REST API and I had to do data binding to kinda make it show up, etc. But if you think about it, there's nothing that I can do on a client that would cause the data to change, so then why am I sending the data to you, right?

So this is an example of tree shaking of the data itself. Now if I go to the comments section, notice that the JSON now contains a lot more stuff. This is basically whether or not a particular comment is open or closed. So this is information about the state of the components, whether they're open or closed.

In this particular case, they're all open. And this looks like a very, very long thread with many, 80 comments, so it's pretty big. But what you don't see anywhere in here is, you don't see the actual text serialize anywhere in here, is just serializing whether or not a particular component is open, right, so I can close this.

I can click on, I can open it and close it, right? So it behaves the way you would expect. But the data from the server is not in here, it's not included, right?
>> And to clarify the reason why that's the only thing that shows up in the data is because that's the only part that's interactable?

>> That's right, that's right.
>> Got you.
>> Yes, Mark?
>> It's a question around offline, and if you become offline, will you download, or how does that work?
>> Yeah, so that's a super comical question. What happens on a slow network, on a spotty network, if you get through a tunnel, etc.

So, first of all, this is a dev mode. This is not actually how it works in production, okay? There's lots of other things we do in production. But in production, what you have is, you have a service worker, or let me back up a second. The way to think about is, when you run the application, we break up the application into as many pieces as possible.

And then as the application is running, we collect information about what bits are actually needed and what actually are not needed. Based on that information, we can create ideal bundles that have just the bits that is required and the bits that are not downloaded, those are not required.

And that information actually gets produced as part of the build step and is fed to the service worker. And so the service worker starts prefetching all of the code ahead of time so that by the time you enter the tunnel or whatever, you'll have everything available for yourself, right?

And so once the service worker is done with prefetching all the code, it's no different than any other application, right? The key thing to understand is, or the first order of approximation we should think about is, is not that we are lazy loading everything, is that we are lazy executing everything, right?

Think about the fact like, let me just download all of JavaScript as an existing system, right? I don't have to execute it eagerly, that alone is a huge win. The fact that we can further subdivide your chunks and lazy load those, that's just icing on a cake. The big win is the fact that we didn't eagerly have to execute everything, right?

So, it's more about lazy execution, rather than about lazy downloading of code. Lazy downloading of code is just icing on a cake. But there's a service worker that makes sure that you will never get in a situation where you clicking on something means that the code isn't downloaded.

The service worker will prefetch all of these things and make them available to you. And because the amount of code is less than what would be a normal application, the service worker will always finish its job way before the existing system would even download the JavaScript. Just wanna point out that a lot of times people get caught up by this idea that, I'm gonna click and I'll have to download the code and it's gonna be slow, right?

And I just wanna dispel that it's not how it actually works in production, right? In production, the code is downloaded eagerly. The when is the lazy parsing and execution of that code, right? Yes?
>> So, I mean, if I see the angler where we do the lazy loading end or we just, I mean, create the lazy loading pattern where the bundler will divide the modules.

So in Qwik, we have to follow any kind of pattern or bundler will do the job automatically dividing the whole application?
>> Yes, so let's see where am I here? The conference app, so, oops. Let's go to the clip, so this is the clock. Is this the clock?

Yeah, this is the clock demo here. So let's go back to the clock demo. Every time you see a dollar sign in Qwik, this basically tells the system that, I would like you to insert lazy loaded boundary over here. I'm not saying that you should lazy load here, I'm saying that it could be, right?

Because whether or not the lazy loading boundary is actually ended up with is a thing that happens based on how the users actually use your application. So as they use the application, you collect information about, what actually is needed, what isn't. And based on that, you create ideal bundle sizes and ideal bundle distributions, right?

But it requires you to be able to do that. And this being able to is done through this dollar sign. So every time you see a dollar sign, think, this could be lazy loaded, right? And so if you go down, you'll see, this could be lazy loaded. The styles could be lazy loaded.

The client effect can be lazy loaded. The whole component can be lazy loaded, right? And so by including these dollar signs, you're placing lots and lots of places where lazy loading could happen. And the biggest problem with the existing frameworks today is that lazy loading is not something that is easy to do, right?

It's quite a lot of ceremony to do lazy loading. And again, we're gonna dive into this more tomorrow, right? So by making lazy loading so cheap and so low cost as single character, by the way, it's not like I can forget to type this character here. Because if I do, TypeScripts gonna scream at me and be like, there's no such thing as a component, there is component dollar sign, right?

And so the TypeScript just kinda forces you down this particular path. So, for example, this click button that says, print a console test, right? This, p here is, clicking here, I'm sorry that's a conference. Sorry, where is that p, yes, it's a console. Here we go, let's do it, refresh again.

If I click, it prints test, right? That, if you look at the Network tab, literally only downloaded the console.log test. Because, well, it's behind the dollar sign and the framework automatically pulls it out, right? Think about it an existing existing framework, existing framework would be like, well, I have to hydrate the component in order to figure out if there is a click listener.

Which means I have to download the whole component, I have to execute the whole component. And then I have to find where the listener is, right? And I will create a closure for that listener. And then closure gets attached to the DOM, and then I'm ready to do your stuff, right?

Whereas here, none of that stuff happened, all that stuff got skipped.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now