DejaVue

Vue is fast (actually the fastest SSR framework)! But sometimes apps might a bit more fine-tuning. And by sometimes, we mean rarely.

Still, it can happen - so join Alex and Michael in this DejaVue episode to dive into what tools Vue gives us to improve the frameworks' performance. 

Further, they dive into the recent SSR benchmark and what it means for you as a developer, as well as striving topics like perceived performance. 

Enjoy the episode! 

Chapters

  • (00:00) - Intro
  • (01:14) - The topic of this episode - Performance
  • (02:05) - Optimizing for performance from the beginning?
  • (04:03) - Prop stability
  • (08:18) - v-once
  • (10:45) - v-memo
  • (12:57) - Does v-pre fit into the mix?
  • (14:28) - Recalculation of computed's
  • (20:47) - Virtualization
  • (24:05) - shallowRef
  • (27:25) - Vapor Mode in the future
  • (28:44) - Server Side Rendering
  • (29:14) - The recent SSR benchmark
  • (31:35) - Results of the benchmark
  • (32:00) - What does this mean for you?
  • (35:19) - Perceived performance
  • (37:33) - Improving SSR performance
  • (39:12) - VueConf Toronto
  • (40:20) - Wrapping up

Links and Resources



Links marked with * are affiliate links. We get a small commission when you register for the service through our link. This helps us to keep the podcast running. We only include affiliate links for services mentioned in the episode or that we use ourselves.

Creators & Guests

Host
Alexander Lichter
Web Engineering Consultant • Founder • Nuxt team • Speaker
Host
Michael Thiessen
Full-time Vue educator
Editor
Niki Brandner
Sound Engineer

What is DejaVue?

Welcome to DejaVue, the Vue podcast you didn't know you needed until now! Join Michael Thiessen and Alexander Lichter on a thrilling journey through the world of Vue and Nuxt.

Get ready for weekly episodes packed with insights, updates, and deep dives into everything Vue-related. From component libraries to best practices, and beyond, they've got you covered.

Alexander Lichter:

Hey, everybody. Welcome back to a new episode of DejaVue.

Michael Thiessen:

It's your favorite Vue podcast. You just don't know it quite yet. I am here with Alex, my co host, who is wonderful, creating content on Vue and Nuxt, on the core team of Nuxt, going to conferences, doing all sorts of amazing things in the community. Glad to have you back.

Alexander Lichter:

Thank you. Yeah. I couldn't join last episode, unfortunately. I've been around the conference in Prague, which was pretty fun, amazing. Slides are also online that.

Alexander Lichter:

And, yeah, happy to be back. And, of course, I am here with my wonderful cohost, Michael Thiesen. He's a YouTube, also streaming, but mainly focusing on, blog, posts of courses or lots of material around the Vue ecosystem, the Nuxt ecosystem. You've seen them maybe also in the Mastering Nuxt course and so and so an amazing content creator as well. I'm happy to talk to you again once again.

Alexander Lichter:

How are things?

Michael Thiessen:

Yeah, things are pretty good. I'm excited for this episode.

Michael Thiessen:

We're going to talk a lot about performance and Vue and talking about this latest benchmark that came out and what it means and, you know, all sorts of stuff like that. So I think there's a bunch of interesting, actionable things in this one.

Alexander Lichter:

100%. I mean, performance is always like a big topic. I feel like, as you mentioned, that benchmark saying, oh, which framework is the fastest? And of course, if if we just dump it even down further, it's like, hey, we build applications. We want them to be snappy.

Alexander Lichter:

We don't want the users to wait necessarily. And, yeah, performance is such a big topic. Like, we could probably do 5 podcast episodes about it. And if you are there wanted, let us please let us know. But today, we wanna focus on more of the Vue specific things.

Alexander Lichter:

So we don't wanna turn the whole wheel of performance of, like, okay, how to test your application, what are some metrics, and and so on and so on. But we wanna more focus on what can Vue do for performance and, of course, what it does already. We talked about, in the Vue 3.5 episode about performance improvements where you don't have to do anything. And now it's more about, like, what you can do to make sure your application is still performance.

Michael Thiessen:

And the great thing about Vue and like maybe most of my development experiences that I don't really think about performance a lot of the time. But then there are cases where, you know, as your app gets bigger or all of a sudden you are switching to lots of data and then you do realize, oh, this part is maybe not as snappy as it could be, or you get like this huge, nasty performance thing. In the last episode with Erik, he we talked about how they they at AWS Amplify had this, like, weird rerendering thing that they had to deal with. And so then it's like, you know, when it's an issue, it's a big issue because no one wants to wait 3 seconds for something to happen after you click a button, you know?

Alexander Lichter:

For sure. But that's, I think that's also a really good part to start with maybe like, as you said, performance or, like, optimizing, let's say, quote unquote, is not something you should necessarily start with. Right? Like, it's more, okay, you notice there are some things that are slow and then, yeah, you should benchmark it. You should track it.

Alexander Lichter:

You see, like, okay, what is exactly so what's the slow part here and and optimize that code? Because by default, I think, like, you can also write everything super fast and could be, like, 10 milliseconds faster if you write a a for loop, like, like a for let I equals 0 and so, like, not a for off and so on and so on. You can do that, but then, well, it will hurt the code readability and the maintainability. So instead of saying, like, okay, we write all code, the most, like, less abstract way and the most performant way, no. Why not just writing the code the way it's the easiest, like, readable, understandable, descriptive?

Alexander Lichter:

And if there are hot parts that that are important for performance, if you're not like, okay. I have to show 10,000 records here. Well, then, of course, this should be optimized. But not prematurely, but with as I said before, we're benchmarking, we're actually showing what makes the code slow to fix that.

Michael Thiessen:

Yeah. So why don't we jump into some of the ways we can actually, you know, address these performance things with with our apps. And one of the first things is to do with props. So in Vue as in most frameworks, when the data changes, the DOM changes and we trigger that re render. So the most important and fundamental thing we can do for performance is just preventing our props and our data from changing unnecessarily.

Michael Thiessen:

And that may sound like super humphous, but there are cases where the way that you calculate a prop or dynamically doing different things on those props, you're changing it multiple times when it doesn't actually affect the functionality. Maybe that's a little confusing. Maybe maybe you wanna take it from there.

Alexander Lichter:

Yeah. No. I I think I think it makes kind of sense. Let's let's maybe have a more illustrative example. Let's say you have a list of items, and you say the first and the last one, they should be colored red for some reason because that's the requirement.

Alexander Lichter:

Or, like, they should be in a fancy way of showing, like, hey. It's the first item. Definitely buy that whatsoever. So if you have your component with, let's say, your your item in there in the list, then you have lots of options. Right?

Alexander Lichter:

You can say, you you pass in, the index of its allocation, the position, like the first position, the second, and so on and so on. Or you could say, I pass in whether that should be highlighted or not, like, just with a Boolean. Right? So the thing is if you pass in a Boolean, then it only changes when it's actually needed to highlight. Right?

Alexander Lichter:

So if, let's say, you resort the list or you remove something or you add something to the list, then it will be on the first spot. Okay. Highlighted the second, not anymore. 3rd, 5th, 6th, it's fine. It's always false to be not to highlight it or not highlight it.

Alexander Lichter:

But if you pass in the position, then well, if you don't need it for anything else, but just for exactly the functionality, there will be an unnecessary rerun, recomputing because, okay, you pass on different prop, things run again because a prop changes, and then it's simply more effort. So this whole concept of prop stability is is super important to think about what kind of information do I wanna pass in there. Is it really the position needed because you maybe wanna show it? That's fine. Or is it more about a Boolean and then compute that beforehand and give a Boolean expression in to make sure, okay, all the props are the same.

Alexander Lichter:

Even if I move it around

Michael Thiessen:

Mhmm.

Alexander Lichter:

I don't have to touch it. It's faster.

Michael Thiessen:

It's interesting too because I think this touches on, like encapsulation and like what should each component do? Because if you pass in, for example, the position of each item, as well as the length of the whole list, so then the child component is responsible for calculating. Okay. Am I in the 1st position or the last position? What should I do?

Michael Thiessen:

Then, yeah, you end up with this, like every single time the list changes every single item, every single sub component there is going to need to do a rerender. But also if you look at it from a, you know, best practices just from the code side of things, you'd say, well, why does that child component need to know all that kind of stuff?

Alexander Lichter:

Exactly. Yeah.

Michael Thiessen:

And so this one is almost like if you're writing code in a thoughtful way and refactoring and cleaning things up as as you need to, then there's a good chance you'll sidestep a lot of these problems. But it is still good to think about and to know that this is a trap that that you can end up getting caught in.

Alexander Lichter:

Yeah. Like, as you said, if you always think about, okay, what does that component actually need to know and also not be lazy about and say, like, okay. You know, I just pass in everything and they they will pick whatever they need, Then, yeah, you can avoid it. But I think on the other hand, it can be really tricky if you have lots of properties, if it's like a big component. Of course, as you said, refactoring architectural decisions.

Alexander Lichter:

But as we all know it, okay, features have to be shipped here and there. Sometimes, like, okay, let's go. And and then wondering, like, oh, if I resort the list, then maybe, it it will take ages to compute or whatsoever, then then that might be a good chance. And also, I mean, there is in the Vue dev tools, for example, performance tab. So that's also worth checking out and to see how long components take for rendering, for changing.

Alexander Lichter:

So that's also one good way to check out what could be the culprit there.

Michael Thiessen:

Yeah. And beyond just making sure that our props are stable in this way, we've got a bunch of directives that we can use to help us with these performance things. So the first one is the v-once directive. And that one is pretty straightforward. So what it's doing is basically we're going to make it sort of like a read only kind of thing.

Michael Thiessen:

We're going to render that out, but only once. And after we've rendered that that HTML to the to the DOM, we're not going to worry about any future updates. If the data in there changes, the HTML will not change. So it's sort of like we're not rendering static HTML and we're not fully dynamic. On the first load, we're going to interpolate all those variables, get them in there.

Michael Thiessen:

But then once that's done, we won't touch that anymore. For certain situations, that's useful, and we can, you know, improve the performance there.

Alexander Lichter:

Yeah. Absolutely correct. Like, it will be just treated as static content, so to say. And in a way, like, it this has been around for a while. And I feel like there at least to me, I didn't come across that many use cases where it's like, okay.

Alexander Lichter:

I have to use that v-once directive ever. Of course, if you render, like, thousands of components and it's like, okay. It's enough to render it once and we're fine. And then if the component is unmounted or destroyed and will be spun up again, then I can rerender. That's that's totally, totally valid use case.

Alexander Lichter:

And yeah. Have you have you come across any v-once usage so far in your applications?

Michael Thiessen:

I haven't really. There aren't a lot of situations where I found that I would need this for. And I like, I struggle to even come up with, like, a particular use case just like off the top of my head right now, but I'm sure that there are definitely use cases for this.

Alexander Lichter:

Yeah. I think, like, really of, like, otherwise, that would be checked and rerendered with, like, a lot of components inside even though, you know, okay, you just wanna render them once, and then they they do their thing, and it's fine. But I think that also underlines once again that, like, in general performance, in terms of Vue.js itself and, like, make that more performant is rarely a case to, let's say, bother with. Maybe the whole topic of data visualization, so, like, lots of different nodes at once is also something that comes up there where it's, I think, more important than, like, in a typical CRUD application or, like, typical software as a service thing.

Alexander Lichter:

So, like, probably also, like, charts and all that.

Alexander Lichter:

But maybe that also fits in very well with the next directive, which more or less is v ones but with conditions, and it's called v-memo for memoization. So the idea is that, okay, we have memorization also in normal programming. Like, you can write a function that will render a result for the first time and then memoize it. So it just, like, saves it.

Alexander Lichter:

And the next time the function will call the same parameters, it will just give the same result without the calculations. And that's also about the v-memo directive, but it applies to a certain part of the of the rendering. So you can just smash v dash memo on something, and then you can define conditions as in just an expression. Can be an array of things, can be a certain variable. Let's say as long as they stay the same, please render exactly as it is.

Alexander Lichter:

And if it changes, then rerender. So like v-once with conditions.

Michael Thiessen:

Yeah. And I like to think of this one as like a computed ref, but for your template. So it does like the same kind of thing of memoization and you can specify what those dependencies are explicitly. And like one key thing with this one goes back to the prop stability thing where we want to make sure that what we put into that dependencies aren't going to change unnecessarily because if the dependencies change, it will rerender it. And so the same thing with those props, we want to make sure that we're only changing it when it's actually necessary to change it.

Alexander Lichter:

Exactly. And one typical use case with v-memo is like a v-for directive. You can use it on the same element and say like, hey, this is the list. Don't rerender it as long as, let's say, the selected element is the same. If that changes, please rerender the list so we don't have any unnecessary rerenders.

Michael Thiessen:

Mhmm.

Alexander Lichter:

So also there, it was introduced in 3.2. It was not part of original 3.0 release mainly because there was no, like, super huge need for it. And there were, of course, other topics to consider first, like, flashing out a Composition API script setup and so on and so on. But it's nice that it's there and that you also have a choice between saying, okay, I rendered once and that's it, or like, rendered every time, just having little fine grain control. And there v-memo is extremely useful.

Michael Thiessen:

Yeah. I also want to mention that there's this other directive, vpre, which is basically telling the compiler to just like ignore everything. And I don't know if I've ever found a good use case for this. I'm not sure what the intended use case is, but it's basically like it won't interpolate it. It won't compile it.

Michael Thiessen:

It'll just it kind of acts like a pre tag where it just preserves all of the formatting and everything in there.

Alexander Lichter:

Yeah. It's like v preserve, I suppose. So that's that makes sense. I think like main use cases is if you don't use Vue standalone, but have something like a rendering engine that renders other content inside there, uses also like the mustache syntax, or maybe also with web components that you wanna render, like, any kind of other components in there that should be like, okay, this should not be interpreted as a Vue component. Everything that goes in there should be like a a different, different kind of component.

Alexander Lichter:

But that's mainly for interoperability, I would say.

Michael Thiessen:

Yeah. Now that I now I say it out loud, I think it's not as much about performance. But for some reason, I always had it in my head that it that it was like a performance thing. So

Alexander Lichter:

I mean, I probably won't do a big thing in there. But if you use it with if you use Vue with other systems, then, of course, the v-pre tag is is super necessary. So that's that's never a bad idea to mention. And, yeah, I mean, from from there, we've talked a lot about profitability, about memoization, and rendering things once or based on conditions. You also mentioned that v memo is a bit like a computer, but for for the template, let's say.

Alexander Lichter:

But let let's talk about computers themselves because in general reactivity, we talked about it in an episode before. It's super useful. It's baked in. We don't have to think about it much after understanding the concepts. But in terms of performance, there can be quite a few things done there.

Alexander Lichter:

Because especially if you have a computer and it returns an object, then you might run into issues because let's say your computer returns a string or a Boolean, and it's all fine because obviously, you can just compare them with a triple equals and say, okay. The strings are the same or not. With objects and arrays as everyone in here knows, like, we can't compare them with triple equals because even if you have the same content, well, then there's still a new reference. So they're technically same content, but different objects, not this they don't point to the same position in memory, so to say. So that means you might accidentally trigger some rerenderings by just returning a new object in the computer every time and then using the results of that object.

Alexander Lichter:

So, if you say, like, I don't know, you have an object and return a couple options there because you want to pass them in a component or a couple of classes, that can be really useful. But the problem is there then that's, if you pass the computed as is, well, then, you might trigger rerenders in your components or, like, your logs, watchers, whatsoever, just because it is always a new instance.

Michael Thiessen:

With this, I'm wondering like if you took that computer that calculates this new object, if you split it into a bunch of computed refs that each calculate individual values, like your primitive values, like string number, whatever. And then you had a final computed that combines it all at the end. If that would be a way to sort of prevent that. So, like, if any of the underlying values changes, the decomposed computed refs are being memoized properly and you're sort of splitting that out.

Alexander Lichter:

But as long as there is a new object created in the end, then you you always have the same problem. Right? Like, let's say, you only need one information in there, and the object will be always recreated so it will always be checked. So either just take the 3 computed separately or if the performance is not important there, then it's fine. Like, once again, it's not an anti pattern.

Alexander Lichter:

It's not like people say, oh, let's never do that. It's more let's say you you watch that computed and do a very costly operation on that or, like, you rerender a very big component, then it might be better to split it into 3 parts, instead of having 1 computer with an object to return just so it's easier to detect, hey. Can we reuse the component? Do we have to rerender that? What do we have to update in terms of props?

Alexander Lichter:

So I I think also there, then it's easier to, like, just fully split it up or say, that you have some kind of Boolean logic you wanna do in the computer right away, and then we just return true or false, and have computed for properties separately. But nevertheless, this is like really more of an edge case as a lot of things with Yeah. With performance in here.

Michael Thiessen:

Over time, the computer has gotten a lot better in like how it calculates things. I remember a few years ago there were some edge cases that that were being talked about where in certain cases it wouldn't actually be cached properly and would trigger extra. And like in recent update, we had like even more fixes to memoize things better and all of that. And so the framework itself is improving for us. And so I think that's that's always really nice.

Alexander Lichter:

Yeah. Also, as we mentioned in the 3.5 episode, like, there are performance improvements just coming to us, be it, like, less memory consumption as I said, like, avoiding recom like, recomputing and and all the contributions that are super valuable because they're basically like, there's zero cost for us. As long as everything works and thanks to the test suite, that's the case, then, yeah, we're we're gladful for taking them. And all the people that really dig into that because it's it's so different writing an application with a framework like Vue or Nuxt than actually working on the thing, like, also on, let's say, a compiler level or in a type level or just in the implementation. So once again, like, kudos to people that really dig into that.

Alexander Lichter:

And, like, you learn so much by by going through that, like you do, for example, with, your newest, upcoming project.

Michael Thiessen:

Yeah. So recently I launched a free email course called reactivity from scratch, where we go through day by day for a week And we build a Vue 3 inspired composition API, like reactivity system. And so we ended up building actually quite a number of things. We build ref and reactive and watch and compute it. And then we ended up building our own sort of like a penia data store thing at the very end.

Michael Thiessen:

We have all these things in there read only that kind of stuff. And it's, it's pretty great. We've had a bunch of people sign up for it and go through it and I've been getting some pretty good feedback from that.

Alexander Lichter:

So that's it. If you wanna link, to the landing page, go for it. Because it's it's so nice to, yeah, get them through the internals even beyond what we discussed in the podcast because, of course, if you, like, do it yourself, like, okay. That's how like the basics work. Even if, of course the code is not 1 by 1 what's in Vue.js, but the idea, the concept that's, that's what you're interested in.

Michael Thiessen:

Yeah. There are so many edge cases and performance optimizations that are not covered in there because then I would just be banking my own framework at that point. So

Alexander Lichter:

Yeah. Mue. Michael's Vue.

Michael Thiessen:

Yeah. Maybe I should do that.

Alexander Lichter:

I mean, would be fun, though, like, all in all, it's I think also that the big power of of open source of, like, all these people watching us, like, hey. We can do better. And even the benchmarks, which we also discuss on later, about performance, like, every time there's a new benchmark coming up, it's always like, yeah. Is it, like, is it really meaningful? We'll also see, but it will definitely point, like, to the authors of the framework.

Alexander Lichter:

Like, hey. Okay. You can do better. Like, hey. Someone oh, we want to be number 1.

Alexander Lichter:

Oh, we want to be the fastest framework. And, I mean, there's this there's this super big collection, the JavaScript benchmark JavaScript framework benchmark out there by by Stefan Krause who's comparing, like, all the frameworks out there with, like, the same test in terms of rendering. And that's also worth checking, of course, because, yeah, performance of frameworks just in the baseline is is important. Doesn't matter if it's like a millisecond more or less, most likely not for your application, but it's good that you know how to fine tune it if you need that, for example, database and other things.

Michael Thiessen:

Our next topic is on virtualization, which is basically we're, we're reusing components over and over again. So imagine if you're building like a spreadsheet app with Vue and you've got a component for every single cell. You know, if you have a 1000 by 1000 spreadsheet, that's a 1,000,000 components that you're working with and that's a lot. And you're not going to render all of that all at once. And most of the time those cells are not even on the screen.

Michael Thiessen:

And so the idea is that you basically render what's on the screen. And then as you scroll around in the app, you deactivate the existing, like the ones that go off the screen and reuse those. So you're not constantly creating and destroying components. You're just like reusing the existing components and you save a lot on performance and memory as well. And it's a whole thing.

Michael Thiessen:

And there are libraries out there. I haven't actually looked at this in a while, but years ago, at least there were some good libraries on doing this. I'm sure there are some good ones out there still today.

Alexander Lichter:

Yeah. Vue virtual scroller from, Guillaume Chao, AKA akryum, is still, I think, the most popular one for, like, virtual lists and things. Yeah.

Michael Thiessen:

That's the one I was thinking of.

Alexander Lichter:

That's that's still a good choice. With virtualization, the other part, as you mentioned, like components, that's a very good point. But also if you go a lower level, like, DOM nodes just in the browser Right. So you don't render not only these, like, 1,000 by 1,000 components, but each of the cell would be also a dumb node, probably also some contents on. So, yeah, you especially working with, like, large data tables and, like, as we said before, typically, like, CRUD application, you don't really want to render all of them at once because especially on the, let's say, not, higher end MacBook Pro and whatsoever laptops, that should still be usable.

Alexander Lichter:

So it's good to have the data there. Of course, course, you have also pagination stuff, but some is like, okay I wanna see the last 10,000 entries.

Alexander Lichter:

You still don't have to render them. You can search for them if you only have the data and don't need to render the the DOM nodes. And, yeah, as you said with, like, some list virtualization, that's that's a good way to go. Of course, there are also some caveats there with, like, okay.

Alexander Lichter:

Yeah. You want to reuse them. You have to show the scroll bar to right height, for example. There there are a few things that the libraries will really

Michael Thiessen:

Yeah.

Alexander Lichter:

Do do the heavy lifting for us. But, yeah, luckily luckily they're there.

Michael Thiessen:

It's, like a tricky implementation because you're like, like if you're scrolling, you can't just render something as soon as it becomes visible. Because if you do that, then the lag will mean that, you know, if you're scrolling really fast through this list, the thing will only be rendered, you know, by the time it's, like, already halfway up the screen. And so you have to, like, figure out at what point, like, is it as it's about to come into view, you need to start rendering it and all these, like, things and calculating window heights and and all that kind of stuff, which is always a fun a fun thing to get into.

Alexander Lichter:

Exactly. And of course, we didn't even talk about server side rendering to make sure all the content is there for SEO because that's usually not a topic, but yeah, that's also something to consider where to use the virtualization and if that fits for your use case or not.

Michael Thiessen:

The next API we have is back to the Vue core, which is the shallow ref composable. Basically, what this one does is normally our reactive data is reactive and like nested properties, if you change them will cause updates in your application. But if you have this massive object that you've got and, You know, you're changing lots of things on it. And these re renders are expensive and slow. You can actually put it through the chalo ref and it will only update and trigger that that re render when the entire object is replaced.

Michael Thiessen:

But you also get a little bit of control here. There's some methods to trigger the these updates manually. So if you update this object, you do something with it and you know that you want to rerender because of that, then you can manually trigger that update. And so you have a little bit more fine grain control over when your app is getting rerendered instead of just every single time, you know, one of these, like, properties is is updated, which could be a lot depending on how your app is working. And so you can yeah.

Michael Thiessen:

You can control it and update only when you need it.

Alexander Lichter:

Exactly. And typically use cases, we also mentioned it before in quite some episodes, is like data fetching. Because if you fetch data, okay, then you replace the results from before. Or maybe there is no results. We could take it in.

Alexander Lichter:

That's that. And then you can, from there, reuse it, but you rarely manipulate the original ones. Maybe you have computer property based on the data and so on and so on. And the other thing is integrating some kind of third party state management, like Immerge as something with immutability, because there you also okay. You get a new state.

Alexander Lichter:

You wanna set that. You get a new state. You wanna set that. You never, like, modify things directly. But, yeah, I think these are the 2 most common cases in your application.

Alexander Lichter:

Of course, if you have a scenario that, like, fits into one of these twos and it's not covered by 3rd party composables or APIs, like, you would say some data use patch, they they already can use ShadowRF under the hood with a flag or index 4. And, of course, VueUse is also doing that. If you query based on 10 stack queries, also doing that now with a flag, I think, by latest PR. I once sent one to change it for for one of the methods, but now it's, available everywhere with with a flag, if I remember correctly. Also will link all that in description slash show notes.

Alexander Lichter:

So, yeah, luckily, most libraries got you covered. But if you have a case on your own, definitely, if you say, okay. I have a ref and I only replace the value and never change it directly, might be worth moving it to your shallow ref and see if it changed something or not. Yeah. And then I think, like, Vue specific, cases, these are these are a good good number of them.

Alexander Lichter:

I think one more to add is maybe the classic. If you have a list of things, like rendering with v 4, you can memoize it as we mentioned before, but also you should set a key. Right? So make sure for all these elements that, writes great. They can be easily sorted, moved around by identifying key, and the key should not be the array index.

Alexander Lichter:

The key should be part of the thing you render. Let's say you have an ID from your database or a unique combination of values whatsoever. But yeah, please don't set it to random value. Please don't set it to the area index because then if you start like resorting shuffling things, stuff will break. We promise.

Michael Thiessen:

Yeah. I can't move on without mentioning the, vapor mode, which will be coming in the future. It's being actively worked on. And this one is opt in per component. And I believe that there aren't any like syntax changes.

Michael Thiessen:

It's just like a switch that you can flip. And instead of using the virtual dom, it will like directly render and, and it's got some performance optimizations there. So it's like more bare metal rendering. And so, that's something to look forward to in the future.

Alexander Lichter:

100%. And on that note, we also picked it up here and there already. There is from, Vue community member, ubugeeei. I hope I pronounced the name the right way. He wrote a little documentation about reading Vue.js core vapor, and he dives into the code.

Alexander Lichter:

So not only what vapor does, but actually the the code, how things are written. So maybe if you want some understanding what's going on under the hood, how is paper mode differently, then, yeah, definitely check that out. Also, the link down there, really worth reading. It's still work in progress here and there, but it's, it's amazing.

Alexander Lichter:

I got into it and it helps a lot to understand the code and what's written there. Because as mentioned before, we're almost working on rendering engines every day.

Michael Thiessen:

We can't talk about Vue and performance without talking about SSR. Because that is one of the benefits of SSR is we can get some extra boosts there. So there was this benchmark that came out recently and I didn't really pay attention much to this, but, but you've been tracking with it a bit. So maybe you can explain a bit what, what happened there. And, there's a little bit of drama around that. Not a bit.

Michael Thiessen:

I mean, as with with any benchmarks, there's always gonna be drama. So

Alexander Lichter:

That's that's true. Yeah. So actually, there was a as you said, Michael, there was a benchmark around service head rendering. If you don't know what service head rendering is on that point, by the way, if you never heard of the term, our very first episode after the trailer, we talked about what SSR is, the need for it, and so on and so on. So there was a benchmark of all the major frameworks like React, Solid, Swell, Vue.

Alexander Lichter:

Angular was even, PR, but didn't make it eventually, Preact, and so on, based on Fastify, which is like an let's say, an express like JavaScript framework for just, like, running your Node. Js, things. So Fastify was used as the base, and then there was Fastify HTML just like as a baseline. So, like, okay, I output something. And then the different frameworks like Vue, React, and so on and so on, they were used, there.

Alexander Lichter:

And the goal was, okay. We want to find out the performance of service at rendering. So who's which framework can render on the server the fastest by, let's say, a constant amount of users and requests and see, like, okay. What's the best throughput? Or the other way around, I wanna have x concurrent users, how many requests per second, can I do, how much data is is transmitted, and so on and so on?

Alexander Lichter:

There were 2 iterations on the benchmark, actually. The first one was taken offline real quickly mainly because there were some, well, problems with most of the implementation. So Rich Harris from Swells pointed out that there were some, issues. For example, he also contributed the Swell 5 version just to, like, hey. Okay.

Alexander Lichter:

Things would be way better than with the current one, and there were some unnecessary style bindings. Ryan Carniato from Solid also pointed things out. Someone from the Vue community as well, SliBee, it was the name, I think, also sent a PR to, make it more fair to use the same way of styling than as in other frameworks. And so there were quite a few things, and I think the biggest one, then Abermoth sent a PR to ensure React is also running in production and not in dev mode. So, of course, this, this changes the perspective.

Alexander Lichter:

Yes. Exactly. Yeah. That these numbers were, like, fixed, after a week, and also to everyone making a benchmark, very important. And I also mentioned that in the video that I made about exactly the topic.

Alexander Lichter:

Always check-in with the authors. Give give them some time to take a look. It's like, hey. I wanna publish this in a week. Take a look.

Alexander Lichter:

Here's the code. Run it yourself. These are our results. Does that make sense? Is that the way you would write code in your framework?

Alexander Lichter:

Also very important. It shouldn't be optimized for the benchmark. It should be as people write code.

Michael Thiessen:

Mhmm. Yeah. The results were basically to summarize. So Vue was the fastest for SSR, followed closely by Svelte and then Solid and React was about twice as slow as as Vue. And it came in at the very end there.

Michael Thiessen:

So that's a win for Vue if you want to frame it in that way.

Michael Thiessen:

And, you know, the question then is what does this benchmark actually test? And does this mean anything for us developing apps, not developing benchmarks? We don't get paid to make benchmarks that are faster than other benchmarks. We get paid to build features and apps that that real people are using in real ways.

Alexander Lichter:

Yeah. I I think that's a very fair question because first, every benchmark is always flawed. In this case, the idea was to render a little spiral out of diffs. So there was an algorithm trying to a little, let's say, galaxy like spiral, with lots of elements, and that makes sense because it's very common. Okay.

Alexander Lichter:

You have lots of DOM nodes and typical pages, but it's still not a, like, real life case. It's not an ecommerce page. It's not a a blog or something like that. In in my thesis that I still didn't publish yet, but I I will at some point. I promise.

Alexander Lichter:

I I did actually investigate meta frameworks. So mainly, Next and Nuxt, and also added Angular because there was no, like, 1.0 of analog back then and compared these frameworks like how they do in terms of server side rendering. So I have a little bit of expertise in that, in that area. And it's very interesting because in the in the platformmatic, SSR showdown, benchmark, Well, first, the the underlying frameworks were compared, and it's a bit easier for sure. It's not a real life scenario and especially, it's good that it focuses on the framework itself.

Alexander Lichter:

But in an actual application, okay, you, like, Vue without any, anything, just rendering the the DOM nodes, gets, like, 1,000, I don't know, something requests per second, which is pretty decent. But as soon as you add one API call to it, that will slow down dramatically mainly because the API call is not a bottleneck. And that's very commonly the case. Yeah. Also for non SSR.

Alexander Lichter:

So as soon as you have an API involved, that's usually what slows your application down and not how fast it renders except for data visualization. That's always a bit of an outlier.

Michael Thiessen:

Yeah. That that's a really important point in that the things we've been talking about today have mostly been about rendering. And once you've got all the data and you are now ready to render it out to the page, how can you make that faster? But in many cases, the actual bottleneck is, oh, you fetch twice when you only needed to fetch once or you fetched more data than you actually needed to, or you should have cached that fetch. And there's all these other things that are like, you know, if you look at your performance and you do like an actual, like, in-depth audit and stuff, you'll you'll find that like the actual render and the especially on, like, initial page loads is is mostly about, like, fetching that data or and even, like, when you click a button, usually when you click a button, it causes some sort of API call to happen.

Michael Thiessen:

Not all the time, but, you know, the speed at which that happens and then you can update the the UI is bottlenecked by that. And you can do, you know, optimistic UI updates where you

Alexander Lichter:

Exactly. And I mean, you touched already an important topic as well, the whole, like, big category of perceived performance because, depending like, let's say, okay, you have a loading state while that API request just super slow flies in. Well, first, easier would be like, okay. Let's talk to the the back end people or, like, if it's your API, then make it faster. As I mentioned you mentioned caching.

Alexander Lichter:

There there are lots of ways depending on the data that you get. But if you can't for whatever reason, and it's not cacheable because it needs real time, then, yeah, make sure that that the loading state is there and that it's also fitting with the average expected loading time. For example, skeleton loader is super common. It's like, okay. The page, it's it's moving.

Alexander Lichter:

Something is happening. That's great. But for example, there if if the loading time is rather slow, then a skeleton loader can actually feel slower than the loading process is. So also they are looking into perceived performance topic is super important. Not necessarily for SSR, but, like, in general for, like, transitions and states.

Michael Thiessen:

One interesting thing about the perceived performance that I learned a long time ago, which is has always fascinated me is that I think it's like under 200 or 300 milliseconds. You actually don't wanna display any loading thing because if it loads within 200 milliseconds, then it still feels fast. But if you flash a loading spinner in those 200 milliseconds, then it sort of feels more more janky and and like things are taking longer. So it's like this it can be fairly complex of like, okay, if it's taking longer than 200 milliseconds, now we show the spinner, but don't show the the loading skeletons if it's gonna be too long and, you know, all these little tricks that you can do to make it feel like it's loading faster.

Alexander Lichter:

Yeah. But also there, like, I think there are lots of optimizations that are always possible. I think at some time, you should also, like, stop on us. This is like, hey. I need to bring up conversions.

Alexander Lichter:

We have to take a look at all that, which is is totally fine. But, like, having a loading state, unless it's super fast, right, which most of the APIs aren't, is is already a good thing. And then as you said, like, going for, okay, maybe add a promise race, and say, okay, if the promise is there already, then don't show the loading state. Otherwise, alright, fine. Let's, let's go for that.

Alexander Lichter:

So there are lots of lots of ways to improve.

Alexander Lichter:

Cycling back on the SSR topic, though, also there, as as you mentioned, like, the the back end, the API, is is the way to go to improve. Also for SSR, for time to first bite, it's, like, more of the the general parts. We might go in another episode if you all are interested in a general performance episode. So it's it's really mostly about the network and and then applying all techniques as we mentioned because the rendering, sure, if you have, like, 10,000 DOM nodes, you might also think about, do I really need all of this on the server?

Alexander Lichter:

Is there something that I can render on the client? Probably there is. You might not need a a model rendered on the server, especially if it's hidden anyway, and all that. But, yeah, that's also from from my experience commonly tackling the API parts first and and then also seeing what's, can be improved. Or as we mentioned before, like components, abstractions around that, improving the scenarios there.

Alexander Lichter:

If you don't render DOM node because you might not need it, that's also if you use the component 100 times, for example, once per item, it's 100 elements less, and that's already a big change. So also make sure that you have a good way of abstractions, but not too many or, like, too many DOM nodes for something that you could also do with, I don't know, different ways, a bit of CSS and so on.

Michael Thiessen:

Yeah. I think, doing a whole episode on data fetching and caching and, you know, lazy loading components and all that kind of stuff. I think that could be a good episode because there's a lot there still. And so, yeah, if that's interesting to you, let us know on Twitter or X, whatever you like to call it in the comments. Email us, send us a letter in the mail.

Michael Thiessen:

Exactly. Have any addresses publicly, but

Alexander Lichter:

If you meet us at a conference, talk to us. Yeah. And of course, before we before we fully say goodbye, we have a little discount code for the coming VueConf in Toronto for you. That's correct. We hopefully will be there.

Alexander Lichter:

We don't know yet because we both applied. I think one of us might be maybe the 2 of us. I will definitely let you know when when the info is out. But with the code DEJAVUE, you save 15%

Michael Thiessen:

Mhmm.

Alexander Lichter:

On the whole thing. So grab the tickets now. Also, workshops there, for example, from the wonderful Daniel Roe who also joined us here. Vue, will be covered through 2 days, and Evan will also be there. So definitely, give that a go.

Alexander Lichter:

Link with the coupon code down there.

Michael Thiessen:

Yeah. And I'll be there regardless because it's in my backyard, basically.

Alexander Lichter:

It's around the corner.

Michael Thiessen:

Right right here. So I'm there every year, and I'll be there this year as well. So I you know, if you're in the area or even if you're not, I'd love to see you there.

Alexander Lichter:

Yeah. Likewise. Even, I might be there, might not, but definitely catch Michael. Maybe the 2 of us. Maybe we'll have a little DejaVue episode there.

Alexander Lichter:

Who knows? Who knows? We will see. But where you can catch us on other DejaVue episodes, of course, the older ones, the older episodes, definitely check them out. A few we mentioned are linked down there.

Alexander Lichter:

And if you don't watch that straight away and the first week comes out, also the newer episodes. So have a look at all of them and let us know what you think. Until then, stay tuned and, hopefully, see you soon all.