A deep dive into Qwik, how it makes your apps fast by default, and the carefully calibrated amount of “magic” that makes it uniquely powerful.
Miško Hevery: Yeah, so people very much think in kind of classical ways. A typical example is suppose I want to have a mouse move, I want to track the position of the mouse. The way you would do it in a classical framework, you’d say, “Oh, okay, so I’m going to create a use effect, and inside of use effect, I’m going to say document.addEventListener mouse move.” And you can do that in Qwik; that totally works. But if you think about it, that’s not what you want, because now you’re like eagerly executing code on application startup. Instead, what you want to do in Qwik is you want to say – you want to run the registration of event listener on the server. And to most people, that’s like “What are you talking about? You can’t do that. That’s in the server. There is no DOM. We’re doing SSR, that can’t possibly be done.” But the framework knows how to serialize these things, and actually, it can be done on the server.
And so people end up writing code that is idiomatic for other frameworks, and it just happens to work inside of Qwik, but it’s not performant. Because they’ll end up eagerly registering all these listeners, and pulling all the code that’s unnecessary. And so a lot of issues is like, well, you’ve got to think like Qwik, which means “Can we offload many of these things to the server side?”
The other thing that people are kind of surprised with is that all the other frameworks have these expectations, that “This is the server code, and this is the client code, and the two should never meet.” So you have to separate it in separate files etc. And so because people are already pre-trained with this mental model, when it comes to Qwik, they’re kind of confused… Like, “Wait, where do I put the server code? Where do I put the client?” Well, just put it in the same place, and the right thing will happen. And then they’re like “Really? That seems strange. I don’t expect that.”
So some of this is just behavior that they’re just preconditioned with from other technologies, that they have to kind of unlearn, so to speak, to kind of understand “Oh, the mental model is different. It is not my application running on a server, and then a separate thing running on the client. It’s the application starts on the server and then it gets moved over.” And so a lot of times people will try to do things like, say, you run this code on the init phase of the component, and they’re surprised why it’s not running inside of the client. Because, well, the component [unintelligible 00:45:09.24] on a server, not in the client, so the constructor no longer runs on the client. And because they’re used to the hydration world, where all of the components reconstruct themselves on the client, they’re kind of like “Well, why isn’t this working?” It’s like, “Well, because resumability.” We are instantiated on the server, and we continue running on the client, without reinstantiating everything on the client again.
And so there is a little bit of learning that has to happen… But once you kind of get that mental model, it kind of totally makes sense. Like, “Yeah, of course. We started on the server, then we moved to the client, but the server one was the one that instantiated the component. The server one is the one that registered the listener for the mouse move, and so the client only downloads the mouse move code if you actually move the mouse. If you don’t move the mouse, then no code gets downloaded.”