DejaVue

Vue 3.5 came out recently, so why not using the opportunity to dive into the features of the new minor version? Michael and Alex will do so and discuss performance improvements, SSR features and new composables in detail.

If you wondered what the difference of the future Lazy Hydration and existing async components or what other features are part of the new minor, it is time to tune in ✨

Enjoy the episode! 

Chapters

  • (00:00) - Welcome to DejaVue
  • (01:26) - Performance improvements in 3.5
  • (04:59) - Props Destructuring out of experimental
  • (12:23) - SSR Improvements
  • (12:52) - Lazy Hydration
  • (17:10) - How is Lazy Hydration different to existing async components?
  • (21:42) - useId
  • (25:25) - data-allow-mismatch
  • (29:02) - Web Component improvements
  • (31:42) - useTemplateRef
  • (34:34) - Deferred Teleports
  • (38:45) - onWatcherCleanup
  • (42:37) - 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.

Michael Thiessen:

Welcome to DejaVue.

Alexander Lichter:

It's your favorite Vue podcast. You just don't know it yet. Or maybe you do. Welcome, to another episode. And today, we discuss Vue 3.5, the big changes.

Alexander Lichter:

But before we get into it, who are we? Well, I'm here with Michael Thiessen, an amazing content creator in the Vue ecosystem. He's doing courses and newsletter, blog posts, articles, some video content live streaming, and I'm so happy to be here. How are you doing, Michael?

Michael Thiessen:

I'm doing great. And I'm here with Alex, who is part of the Nuxt core team. He's also a great content creator with his YouTube channel on Nuxt things and giving talks and all of that great stuff and doing consulting. And, you know, the list goes on and on and on and on and on. Today, we are indeed talking about Vue 3.5.

Michael Thiessen:

There's some pretty awesome changes in here. So before we get into that, though, we did have an episode with Evan You on some of the things coming in Vue, which we are now seeing with Vue 3.5. So if you wanna go check out that episode, might give you a little bit more context into this and, you know, upcoming changes that we haven't quite seen yet. But, yeah. Let's let's get into 3.5.

Alexander Lichter:

Absolutely. And also to note, of course, Evan talked about Vue 4 as well and lots of other things. So if you haven't listened to the episode yet, maybe you didn't discover the podcast before. Colleagues sent you a link to this episode. Well, then time to listen to all the other amazing episodes beforehand.

Alexander Lichter:

But, yeah, as you said, Vue's 3.5. Another minor version. Right? No breaking changes, of course, and a lot of improvements. And I think the best thing to start with that applies to everyone out there no matter if you use service at rendering or not, if you use a meta framework.

Alexander Lichter:

First of all, better reactivity system in terms of memory. Less memory being used now, thanks to internal improvements. Nothing changes. Nothing breaks because of that. So it's always great to see, well, low effort changes for for the users that bring better performance out there.

Michael Thiessen:

Yeah. And the blog post here says about 56% improvement on average, which is pretty significant. It's not just like a little a little bump here and there. That's a big deal.

Alexander Lichter:

Yeah. And, I mean, just think about, like, how mature Vue became over the years. And even then, there's still space for improvement. I remember with Vue 3.4, we already had some improvements here and there when it comes to certain scenarios in reactivity system. And now we even go further with that.

Alexander Lichter:

So it's it's really amazing to see that you can push even a little bit harder and harder.

Michael Thiessen:

Yeah. And faster arrays if you had deeply nested things. I'm not sure exactly what scenarios that might apply to, but, 10 times faster in some cases, which is, you know, if you have a case where that could benefit from that, that's probably yeah. That's a that's a big speed up.

Alexander Lichter:

Yeah. PMPM update right away. You know you know what to do if you haven't done it already, of course. And yeah. I think, especially as as you said, like, deeply nested arrays, big data structures.

Alexander Lichter:

So, you probably wanna use a shallowRef there anyway, but still, if you need a deeply necessary activity Mhmm. Then, that's that's your way to go. And especially if you have, like, big data tables with, like, not only 100 of thousands of entries, then maybe that's a really good scenario where things would just be faster from now on.

Michael Thiessen:

Yeah. You can't always use shallowRef. You sometimes do need that deep reactivity or and you can't get around with the, you know, manual triggering and and all of that. So, you know, another great, performance bump. It's interesting that we've seen in the last few minor releases that there continue to be performance improvements, like, across a lot of different areas here.

Michael Thiessen:

And then, you know, Evan's also been working on Rolldown. Almost said Rollup, but, yeah.

Alexander Lichter:

Yeah. That's that's always a tricky one. Yep.

Michael Thiessen:

And and it's just like, okay. We're, you know, performance performance and and speed. I'm here for it, you know.

Alexander Lichter:

And also Vite. Right? Like, it's it's the whole tool chain. If you like the framework itself on the like, in the browser running, the build steps in between and also, like, framework agnostic and and with roll down, bringing it all even further to the bundle level. Yeah.

Alexander Lichter:

There there's amazing things to see. And I remember the the tweet also linked in the show notes or description, of course, where I said, like, oh, yeah. I I set the Vue's build system all up with Rolldown now. It works like 40 x speed improvement just to build things. And Yeah.

Alexander Lichter:

Yeah. That's that's crazy.

Michael Thiessen:

Yeah. Evan doesn't seem to tweet a lot, but when he does, it's always like something like that where you're like, oh,

Alexander Lichter:

I guess that's what you've been up to. Yeah. Exactly. So kudos also to all the contributors. Right?

Alexander Lichter:

Bpsi is Evan as well. Like, these these minor versions, also patch versions, they come together because of all the amazing people in the core team, but also contributors outside of the core team. So thanks to everyone, contributing because that's, well, it Vue wouldn't be as amazing as it is with without y'all there.

Michael Thiessen:

Yeah. It's a team effort.

Michael Thiessen:

The next feature that that we wanna talk about is the reactive props destructure. So not a performance improvement, but certainly a developer experience improvement. So this is a common thing that people often run into where they do your defined props or how are you defining your props?

Michael Thiessen:

And then trying to de structure that. And then all of a sudden things aren't working the way that you expected. And it's like this subtle little thing where props aren't reactive objects like made with reactive and they're not refs. And so it's like, how does the reactivity work? It's a kind of more subtle thing, but then the restructuring it so far has broken that reactivity.

Michael Thiessen:

And so now you can actually destructure and with some compiler help, it will maintain that reactivity. So you don't have to worry about that and you can destructure all day long.

Alexander Lichter:

Exactly. And I mean, it's it works pretty similar to reactive when you also destructure reactive. Mhmm. Like, object defined with reactive. Their activity is gone.

Alexander Lichter:

Like, think about I don't know. They they use routes, composable from from your router. If you're also like, okay. I'll just structure things out of that. Too bad.

Alexander Lichter:

Reactivity is gone. But yeah, as I said, the biggest foot gone is with props because people might not be aware of that might not have read the docs or maybe there didn't enable the ESLint rule, but yeah. Vue is a compiler based framework and that will help a lot here. So now that whole thing is basically replaced saying, okay, instead of count somewhere, do props that count. It still comes with some limitations.

Alexander Lichter:

So if you now want to watch a prop, you can't just watch, let's say you have a prop called name, then you can't just say watch, and then name. You have to use a getter. So watch and then like an arrow function that just returns name, a bit like you did before with props dot name in there. So there are a few things we have to be a bit careful about, but luckily that change first has been around as an RFC for a while.

Alexander Lichter:

So it was tested, feedback was there. Some people had said, like, okay, it might be a bit too magical, but the good part is it doesn't break anything because if people assume that worked before, like, okay, reactivity is still there, then the code will magically work now. And if they knew before, okay, reactivity is not there, then, well, it's fine. They didn't rely on reactivity anyway. So a good change that only has positive impact because it might fix some parts that people thought it would work that were broken before even though behaving correctly and now they actually work.

Michael Thiessen:

I think my my favorite part about this is the ability to set defaults more easily now because without this and before the whole dance with the with default and then, you know, you put in your types in the defined props and it's just kind of like, it feels like a big mess. And I always messed up how to actually write the with default and like the it's kinda like this weird gnarled syntax that's going on there.

Michael Thiessen:

And I never really liked it. But now we can do with the destructuring. You can do, you know, inside that destructuring, you do the variable name equals your value. And then, you know, that sets the the default value if that prop hasn't been set.

Michael Thiessen:

And so that's a really nice improvement there.

Alexander Lichter:

Yeah. I also think, as you said, like, it feels a bit more natural now you would as you do it in plain JavaScript, let's say, to be like, okay, My const then is structured name equals Michael, for example, as a test if there is no name set. I don't have to handle with the whole width defaults. I the only thing I wonder about is how this will work out when there are more complex, like not primitive data types, but let's say you have an area as a default or an object. If you then still have to use with defaults and then like a a function to set it or if the compiler is is clever enough to actually, infer it.

Alexander Lichter:

I I probably think the first one, but

Michael Thiessen:

Something to test out for sure.

Alexander Lichter:

Okay. Alex and Michael from the future here right back at you. Of course, we're taking a look and, Evan as myself said that it's not necessary anymore to use a factory function for non primitive objects. So you're good to go without one. And now let's continue where we've been before.

Alexander Lichter:

But all in all, reactive property structure has been, as we said, has been in our sea for a while And people got a lot of feedback of like, okay, is it is it maybe too much magic because people might not expect it or is it a good level? And, well, eventually everybody trying it out on most of the people's head of down roof. That's that's a good thing to add.

Michael Thiessen:

I'd like to get your opinion on the, the best practice around props and destructuring. So I know that in the past I've, I've seen some discussion around this and some people prefer to keep everything on the props object so that when you access it, you're always accessing props dot whatever the prop name is. So then, you know, this came from a prop. It's a prop. Versus now, if you destructure, you just have these values floating around in your component and you lose that context of if it's a prop or if it's just local to the component or like where this value came from.

Michael Thiessen:

So I'd be curious to know what your thoughts are on that.

Alexander Lichter:

Yeah. I see a big benefit in using props or whatever at least in the script setup part. In template part, I'm not big fan of, like, the dollar props prefix or the just, like, props dot, because they are frankly, doesn't matter. But I see merit in that. What I commonly also tend to do if I need to do a lot of reactivity is just using 2 ref or 2 refs depending if I have multiple props, and also like they they should be existing then, or 2 ref if I also have an optional prop that I want to convert as a RAF and then then deal with that or just create a computer property out of that.

Alexander Lichter:

So I see that it could be a bit confusing, which is a bit of the general downside also of using reactive. It's like, okay, you don't have a type indicating, hey, this is reactive. You know, it's more like, okay, it's the same as before. You you don't know necessarily difference. So I think using it sparingly and where it makes sense, especially for defaults, I think that's pretty good.

Alexander Lichter:

But, yeah, like I I still see Meriden having an actual props, object and and using that around.

Michael Thiessen:

Yeah. I'm not sure I have a, like, a hard and fast opinion on this one yet. I do I think the defaults makes it a lot easier for me to suggest, like, using the the restructuring. But yeah. Certainly for like small components, the restructuring is fine because you probably only have props and not a lot else, but yeah.

Alexander Lichter:

That's fair. I also think it it comes down a lot of matter of preference and

Michael Thiessen:

Mhmm.

Alexander Lichter:

Also the complexity, as you said. Like, if it's a very simple component, then sure, I define my props. I set some defaults and and I'm good. But the more I do with it, the more I want to, like, make it clear in a code that they are actually reactive and also read only. That's another important thing.

Alexander Lichter:

While, for example, computed or like a read only ref, might might be a really good case. And coming from the reactive props destructure, which also a lot of you maybe have used already because as we mentioned, it's it wasn't our seed. It was behind experimental flags. So maybe some of you have it already in there, can just remove that trigger because, well, the the blue flags are needed in more than 3.5. We come to something that's maybe not all of you need.

Alexander Lichter:

And this is a bigger category of SSR improvements. Right? Server side rendering, some of you use it. If you don't know what it is or why you need it, this is our very first episode where we talked about. So also linked to that in the show notes description.

Alexander Lichter:

Let's just say if you use Nuxt.js, there is a fair chance you use server side rendering unless you disabled it. And have been quite a few things in 3.5 that, well, influence SSR at least. Michael, what's what's the big thing in there?

Michael Thiessen:

So the first thing is lazy hydration. So now we can have with our async components, we can control when they get hydrated in their life cycle. So, yeah, maybe you can speak a bit more about how that works and how perhaps maybe a certain meta framework will be using it.

Alexander Lichter:

Yes. Of course. Let's let's start with how it works. So the idea is hydration is quite complicated. I try to write a blog post about how to fix hydration errors and it's talk, and it's still a bit frustrating.

Alexander Lichter:

What it means is that if you have content rendered on the server side through, for example, view SSR, Nuxt, whatever use. And then Vue is initialized on the client side and it's basically taking whatever came from the server side, like the HTML there and tries to make it reactive again, apply listeners and make sure the thing that Vue expects is what has been rendered there. And if there's a mismatch like, oh, there's an element that shouldn't be there, then there's hydration error because Vue is expecting something different in the client that was rendered on the server. So easy examples are invalid HTML. If, yeah, by accident you render, I don't know, an a tag and a tag, which you obviously shouldn't do, that that just doesn't work out in HTML.

Alexander Lichter:

It's invalid. Then the browser will say, oh, it's fine. I'll fix it for you. But Vue is not that easy on you because Vue takes it as expected. So there will be a mismatch there.

Alexander Lichter:

Another thing is, of course, let's say you have authentication state and on the server, well, it's maybe always unauthenticated because you're only checking the local storage then well, on the server, you have always the, hey. I'm not, authenticated, maybe a login button content. On the client side, well, if you are authenticated, then the login button won't be rendered. And once again, there are some issues. Luckily, there are things how to like resolve these hydration errors, but that's the gist idea of hydration.

Alexander Lichter:

So and we also come to these errors and future improvements as well. 3.4 already brought really good error messages. We also talked about that, beforehand, like, really, really good things. But with lazy hydration, well, we want to avoid this, oh, Vue takes, a part of a component that makes reactive, let's say. We want to defer that.

Alexander Lichter:

We want to make it lazy. And you might wonder, okay, but why we need you to have that component up ready? The question is when. Right? Like, when do we need it?

Alexander Lichter:

If you have something below the fold, let's say you have a big list, of, let's say, products. Right? Ecommerce. And you wanna render, I don't know, 30 of these and the first ten are in your viewport, then maybe you want to make them reactive again, like trigger the hydration when you hover on them or when the browser is idle and loaded the rest and so on so on. And maybe the other one just on scroll.

Alexander Lichter:

So there are really good cases because this hydration process is very CPU intensive and that means well, if you can delay it, defer it, make it lazy in some kind and control it yourself, then your performance will be better. Your LCP values will be better. It's your total block in time will be usually better depending on how you set it up. And, yeah, you can you can do lots of things around it. So the idea is that you have different triggers as you can, for example, as mentioned, say on hover, on scroll, on idle to then say, okay, let's make that component reactive again.

Alexander Lichter:

Let's make it work. Because before, if you click on a button, have a, I don't know, console log, nothing will happen because, the JavaScript code is just it's not there. It's just fully static, just the HTML. So that's where lazy iteration is going. How Nuxt is implementing that?

Alexander Lichter:

Well, yeah, we internally thought about a a few versions there. There's also an open discussion about that even before Vue implemented that, but it's always something that was rather be good to see in Vue itself because it makes it way easier for us to build something nice on top of it. So one idea is to have some kind of directive to say, like, okay, we have something like on like hydrate-on-scroll, for example, hydrate on on mount, hydrate on idle, whatsoever. But there are there are still a few things to discuss there. And if you have any opinion on that out there, it's like, yeah, amazing.

Alexander Lichter:

I waited for so long, then feel free to discuss this with us. Also, link to that discussion is in the short description, so definitely check it out.

Michael Thiessen:

So how does this differ from how the, like, lazy components, async components worked before this change. So before with, with async components, they're in a separate chunk and we can like have them load once the page is ready and like everything else is loaded or we can choose to load them. Well, you know, if you put them on a VF, then they only get loaded when that component needs to be rendered and then it'll be loaded. How does the hydration fit in to that? Because my understanding, which could be a flawed understanding for sure, but my understanding was that there was no hydration on the server side for that that component that's loaded lazily and it's just loaded into a client directly.

Alexander Lichter:

So, I mean, we have 2 cases that we definitely can discuss. They're very good. Let's start maybe with the v f case. So if you have, let's say, a model and you have a v f on that and it's not triggered by default and it's a lazy component, I don't define through define ason component or just with the lazy prefix in Nuxt, then this component, as you said, it gets its own chunk, absolutely correct, and will only be loaded when that v f and a condition is triggered or when you then prefetch it. You can also do that in theory.

Alexander Lichter:

And then what will happen? Well, on the server side, it's it's not there. Right? The the VFS falls, so there is nothing to render. And when you render it on client side, then the whole chunk will be loaded.

Alexander Lichter:

So that's correct. If you use, for example, let's say you have a footer on your application and you put lazy in front of it, but you don't have any condition at the moment, nothing will happen. It will just behave like a normal component. Because even though you say, okay, make it async, you need it straight away and it will not have any big benefits for you. So right now the async components are really good if you actually load them after loading something else on demand.

Alexander Lichter:

But if you need them straight away for the initial render, there is no benefit in using that lazy prefix or an async component. And, with the lazy hydration and these, hydrate options and triggers, that will change a bit because then you can say, okay, on the server side, we still render it. We have the content on the client side. Okay. When a specific trigger is met, as we said, on, like, on browser idle, on scroll, whatsoever, on hover, for example, as well, then please load it and execute the hydration.

Alexander Lichter:

So now we have what you imagine for the scenario with the footer, let's say, when you don't have, like, any v f condition, that's exactly where this improvement goes for.

Michael Thiessen:

Okay. So before it was, we had like 2 options, either for most components, you just render it on the server and it's like, it's loaded. And then async components are only loaded when you want them to be loaded. And this one with dehydration, we get like sort of a middle ground where we can have the server rendered part. Like, we can control when that gets rendered on the client, like a bit more granularity.

Alexander Lichter:

Yeah. When the whole, like, let's say, view on the client side kicks in because you see the content still that came from the server. Exactly. But when the client's had JavaScript is loaded and actually hydration process is like, okay, I take the state from the server and put it in components, see what will happen. That all that's also the more CPU intensive part as mentioned before.

Alexander Lichter:

That's, possible to, like, fine granularly, choose now.

Michael Thiessen:

Okay. Yeah. So now we can do async components, but they have been server rendered as opposed to just, like, 100% client render. Okay.

Alexander Lichter:

Correct. The best part, you can even say there is a component. And, like, I I haven't played around with this too much so far, but, also Evan said in the episode recorded with him. So just to reiterate that to say like, okay, let's have a custom, hydrate function, probably promise or similar. And you say like, let's never hydrate that because this will always be a static component.

Alexander Lichter:

So why would you hydrate that at all if you know it's always static? You don't need anything in there. So I I think there there are a lot of good things coming in there. Also, for example, very interesting for Nuxt server components.

Michael Thiessen:

Mhmm.

Alexander Lichter:

So, we're very curious what, improvements in there in Nuxt bring to make the API a bit more accessible because it's also mentioned it's a bit low level, but it's intentional. So, yeah, we and as the Nuxt team can build a nice syntactic sugar around that, and then probably also make it available something like an unplugin if you want to. So you can use it in your non Nuxt application as well. Like, all the other things like, well, auto imports, and, file system based routing is also possible now. So yeah.

Michael Thiessen:

Yeah. I like this back and forth between Nuxt and Vue where what Nuxt is doing is influencing a little bit of what he was doing. And I mean, you obviously don't wanna, like, have Nuxt completely control the direction of Vue because a lot more people use Vue than just Nuxt.

Alexander Lichter:

Especially. Yeah. That's true.

Michael Thiessen:

But yeah. Like, I mean, you can put in useful features like these fine grained hydration and async components and and stuff and, you know, things that are valuable for everyone, which also includes this new composable called use ID, which we've seen already in Nuxt, but now we're getting it in Vue itself.

Alexander Lichter:

Exactly. And the whole idea was also, okay, Nuxt needed it because here we come back to hydration errors. If you set, let's say, random value on the server and well, you want it to be stable, so you want to transfer to a client, that's a little bit of a pain. So the idea was, okay, we need this, for example, libraries like Catalyst UI, other, UI component libraries, they needed to say, okay, if I generate some labels for certain inputs while the ID should match and should be randomly generated so it doesn't clash and you don't have to do that. And the problem is that this worked very well, but it wasn't the same with the service and the clients.

Alexander Lichter:

So there were sometimes, especially with your 3.4 hydration warnings because we we've been for improved the error messages and also compared attributes. So it were better messages. But then everybody's like, oh my god, things are broken while this has always been like that. It was just warned about. Is that good?

Alexander Lichter:

No, of course not. And that's why this user decomposable is there to have like these unique but also stable IDs that are stable. The client on the server side, We patched it Nuxt to make sure, okay, people using SSR very likely they use a meta framework and very likely use Nuxt. So let's provide that to them. There's an easy way to say, okay, for the component library authors, for example, headless UI implemented it very nicely to say, okay, Just have a provide option for the user decomposable.

Alexander Lichter:

Then you can just choose either your own one if you want to write your own or just take the one from Nuxt or at some point just the one from you like now. It's it's really good to see that in 3.5, that it happened because it's also something that's really good in the core because now nobody has to rely on on Nuxt itself to to do that. If you have your own, view SSR set up because of your you have few reasons, I guess, then now you can also use that and are not relying on either writing your own or copy paste

Michael Thiessen:

pasting code, but just it just works. Yeah. It's a a thing that basically everyone who's doing SSR will need. And you can write it yourself, but it's, not the nicest thing to, have to do, especially if if so many people need it. It, you know, should be in the in the framework itself.

Alexander Lichter:

Exactly. And also, of course, it's easier for, like, in the view core to access all the information needed to actually make it happen that these IDs are stable than saying, okay, I write myself and have a, little, say, quote unquote hacky way around it. But, yeah, it's it's there. I also think it was a really good idea to, let's say, polyfill, quote-in-quote it beforehand in the Nuxt just because there was a demand. It was possible for us.

Alexander Lichter:

And it's the ID generation also doesn't matter too much. Like, it doesn't matter what the outcome of it doesn't matter. So, it just matters that it's unique and stable and a valid ID for, like, CSS selection and stuff. So, luckily, there was also no worry about, oh, do we break compatibility with that? No.

Alexander Lichter:

It's all good. It doesn't matter if they change now. It only matters that, yeah, it's in the core now. One last thing that we need to do, we can remove that or, like, not, expose it anymore. And, we're good.

Michael Thiessen:

Yeah. Another thing that I'm excited for related to SSR and hydration is the new data allow mismatch attribute. I think that'll come in handy for, you know, getting rid of all those warnings that don't really need to be there.

Alexander Lichter:

That's also something you have to use very carefully. And also something that Evan teased before this, like, okay. Let's say you render the current date on a server and a client. Then obviously, if you want right now and that moment today, it will never be the same because the milliseconds, the seconds will be different on the server and the client, maybe even the minutes if you have a bad timing or the years if someone pushes the button right at the end.

Michael Thiessen:

Or time zones.

Alexander Lichter:

Time zones also a good part though at least that you yeah. You you can cover with bit of effort, but it's true. That's also a good one. Nevertheless, sometimes, and once again, treat it with caution. Sometimes these hydration mismatches, they are acceptable.

Alexander Lichter:

And, of course, then you don't want to have console warnings saying everywhere, oh, no. It's so bad. No. Of course. Then you want to have a way to say, okay.

Alexander Lichter:

We accept it in certain cases. It's more as an of an escape patch. And it's really nice to say, okay, then just accept the value, that's then on on the clients because it's different on the server, but we want to work with the client when you're good, and you still need the server value, for example, for SEO. So, yeah, for example, for for dates, as we mentioned before, times as well, it's a it's a really good case. But don't think, oh, yeah, cool.

Alexander Lichter:

Now hydration errors, I just make them gone by using that directive quote unquote. It's just a data a lot of mismatch, attributes. So it's not even a directive. Just don't use it everywhere. Treat it with caution.

Michael Thiessen:

Put it on every single element, and you will no longer have any warnings.

Alexander Lichter:

Let's just write a rollup plugin, that does it automatically for all of us. That that reminds me of this this a little sidetrack, but the the Volkswagen, package that just turns your your CI always green no matter if it tests fail or not. This was, it's so hilarious that you like, when I saw that as as a German, it triggers twice.

Michael Thiessen:

Yeah. I imagine.

Alexander Lichter:

So, yeah, that was that was a lot of fun.

Michael Thiessen:

One of the nice things too about this this attribute is that we can limit what it's actually going to allow. So the different values here are text, text content. So children, class, style, and attribute. So if you know the classes might change or the style itself might change, you can limit it to just that. So you're not going too broad.

Michael Thiessen:

You can be a little bit more specific.

Alexander Lichter:

Exactly. Also there, the more strict you can be, the better because you want to get rid of the warnings that you accept on purpose. Right? It's a bit like with ESLint, you can say turn ESLint off for the whole project. That's usually not what you want.

Alexander Lichter:

You want it for a certain line, for a certain rule, and then you're good. Sweet.

Alexander Lichter:

And then we come to something that I was a bit surprised to see about, and it's related to improvements all around custom elements. So we navigate a little bit in the web component space, and web components. I feel like so all the conferences have been this year that were like more JavaScript purpose.

Alexander Lichter:

Everybody's like, yeah, this is the year of web components. Web components will rise. Didn't feel that much about it so far. But I mean, it's it's good that there is a standard out there, and it's good that Vue itself improves the way to say, okay, you can render Vue components as web components. This was possible before, but the with 3.5, a few improvements to the define custom element API com.

Alexander Lichter:

So it's way easier to actually do that and maybe provide a framework agnostic or even just like, yeah, standardized way for your components. That's not even related to Vue that you can use any Svelte, React, Angular, vanilla, jQuery project, and and you're good to go.

Michael Thiessen:

Yeah. I mean, I haven't really spent a lot of time with custom elements or, yeah, using this API at all. I did one time spend like an afternoon with it. And then I found that I kept adding some helper functions and a little bit of abstraction here. And then all of a sudden I realized, wait a second, I'm building another framework.

Michael Thiessen:

And so.

Alexander Lichter:

Yep. That's how it's going sometimes.

Michael Thiessen:

It was fun, but, you know, I just use you. So there you go.

Alexander Lichter:

Yeah. I mean, same here. I played around with web components, especially I also gave a workshop about web components in terms of, like, taking a look at what JavaScript offers in in terms of framework like components. I think that's the the best way to to name it in that context. Mainly because sometimes the requirements are we want to adhere to the standard, we want to avoid build steps, we want this and that.

Alexander Lichter:

So just saying, hey, there is something you can use and that will probably not break in 10 years, very unlikely, then I still think something like LIT, which is a very thin layer on top of app components and solves issues like state management and templating, is a little bit more convenient than just the standard. But I think it's still good that you can use Vue to write Vue components that then move to web components just or like custom elements in that case Mhmm. Just to make it possible for interoperability and not say like, oh, what if, this other team needs that component and they use a different framework, especially think of like big organizations. And it's like, okay, sure. Shoot it out as web components are good.

Alexander Lichter:

So, this is definitely a good thing. And also there there is a reason why, for example, Vue has a 100% compatibility in terms of custom element specs, not like other frameworks like React. There's like 66 or something. There's a website. Also, of course, link as usual, you know, where to find it, where to check.

Alexander Lichter:

Most of other frameworks also have 100%, and some are actually based on custom elements like Angular, for example. So that's also important to mention. But, yeah, it's great. It's great to see. I'm really happy about it, even though I also rarely have used it.

Alexander Lichter:

But the people that are using it, they will be even more happy about this.

Michael Thiessen:

And if you're using custom elements with Vue, drop a comment. Let us know what you're doing with it. I'd be interested to know.

Alexander Lichter:

100%. Could be even a whole episode about it one day if someone's like, Hey, man, we have this amazing thing. Bring it on. Bring it on.

Michael Thiessen:

There are a few other features we should include as well, not related to SSR or custom elements. And the first one is useTemplateRef. So basically, before we were able to do template refs, but they were defined as just a regular ref. And we had to match the name that we used in our template with the name of the ref itself. And now we have a more structured way of defining these with the use template ref, pass in a string, and that uses that as its ID and will match it up.

Michael Thiessen:

And the main benefit of this is that instead of needing to have everything be static and all the names be set at compile time, we can do dynamic template reps.

Alexander Lichter:

Yeah. I think that's also something that that Evan teased a little bit back a couple months ago. And I'm particularly excited about it also because the the type improvements. So, like, if you have, let's say, a template graph and then you just say, okay, it's ref of type and you insert your HTML element or, null. Okay.

Alexander Lichter:

Fine. But then if you change it, you have, like, no information if that's still the correct type. If you don't say, oh, I don't want to have an I don't know, a diff but in span or whatsoever. So that's a tiny bit annoying. Now with useTemplateRef, you don't have these issues because you don't define the type yourself.

Alexander Lichter:

You just say, okay, that's the template graph. You put in the name and the type will be fine. Plus you can share it around, like, properly, in composables. You don't have to define a top level, which is also great. So we can define it in a composable, then expose it to the outside, and you're good because right now you always have to have a top level on script setup, which is also not ideal.

Alexander Lichter:

So it also allows to structure your code even better.

Michael Thiessen:

Yeah. I'm sure there's going to be a lot of improvements with how headless UI components use this, where you don't have to define the rest all upfront and then, you know, pass it in and do all of that. But they can sort of handle more of that internally. And then, yeah, hooking things up might be a little bit more straightforward.

Alexander Lichter:

Absolutely. And also on that point, a big shout out, of course, to Vue Language Tools and Volar and Johnson and team, because that's also a collaboration that, for example, in VS Code and WebStorm, you see these types correctly, that everything is inferred nicely. And also to mention we discussed the reactive props, destructures and text word earlier. Right? Also, there you have nice little inlay hints so that your IDE actually helps developing things better and makes things more clear that, you know, like, okay.

Alexander Lichter:

What's wrong there? Why it doesn't and then you have indication like, okay. This is this is a property. So also there, the ecosystem, the tooling is so important, sometimes even more important than new features because with the right tooling, they're even more appealing. But in this case, yeah, great collaboration and so happy to see that.

Alexander Lichter:

And coming to the next feature, it's something well, something that, one of our guests who was on here before, Julian Huang, also worked a lot in Nuxt Server components, was extremely happy for when you saw it in the patch notes, deferred teleports. So if you have a teleport in Vue before 3.5, so so, like, say, 3.4, 3. Whatsoever, then you say, okay, you want to teleport to a certain target. The problem is that target has to be there already. So you can't say view or, like, your application is adding maybe a diff later on, And there is where you want to teleport to.

Alexander Lichter:

That wasn't possible until now. Now this is absolutely fine. You have little defer attribute on your teleport, set the target, and then things work.

Michael Thiessen:

Yeah. There's this interesting use case that Matt Marabojcic posted on Twitter. He's our guest on the podcast previously, linked to that episode before. That's

Alexander Lichter:

for you guys' episode. Yeah.

Michael Thiessen:

And if I pronounce your last name wrong, then I apologize. However, this is an interesting use case where basically what he does is he has the teleport with defer. And then later on in the component has the target element, but you can conditionally enable or disable that teleport so you can switch where the content inside that teleport shows up. Does it show up earlier on or does it teleport to the end of the component? And so he was using it as a way of, you know, if you have a have content that on desktop, you want to appear in one spot, but on mobile, you want it to appear in a different spot.

Michael Thiessen:

This could enable a use case like that in a bit more of an elegant way as opposed to just, like, defining all of these components and duplicating your code again.

Alexander Lichter:

Yeah. I think it gives a lot of option for layouting as mentioned. That's probably more of the exotic case, but I see some merit in there for sure. The other thing that that was quite interesting came to my mind is, like, let's say, nested teleports. Like, I don't know.

Alexander Lichter:

You have a model. You wanna have a model in the model. You excel, but, sometimes it's necessary. I like dialogues and dialogues, for example. And even then, I can imagine that's pretty good because then you want the element to teleport into in the first model that might not be there when you have to define it.

Alexander Lichter:

So, instead of going to catch 22, you you can just, yeah, defer it and and you're good. And, yeah, also as mentioned for Nuxt server components will be also nice. But, Julian, as soon as as there there are some, things in PRS, we'll also let you know and probably Julian will also tell us for you to bit about it.

Michael Thiessen:

Yeah. The, being able to dynamically add targets for your teleports, I think that'll yeah. It'll be interesting to see what people end up doing with that. Yeah. The nested models is always a a previous job of having to deal with that.

Michael Thiessen:

And there was always a lot of discussion from the technical side of how do we even implement this. And then also the UX designers were like, why are we trying to implement this?

Alexander Lichter:

Yes. Yes. That's the one guys who, like, oh, you guys know. And Yeah. I remember we we also talked about it in our teleports episode, how painful is this to build sometimes.

Alexander Lichter:

And with the new dialogue component, it's also less painful because it's not really possible to have like a dialogue in dialogue. So it's good. Maybe we'll get rid of that. But I understand that sometimes you want to have some content in the modal. It doesn't necessarily have to be a stacked modal dialogue, but, there there's definitely merit in that in certain cases.

Michael Thiessen:

Yeah. I actually got an email the other day from someone about asking about good patterns on on how to do this. So maybe that's an episode for another day.

Alexander Lichter:

Yeah. For sure. And probably the the first one is don't. I try to avoid it. But there there are good reasons as I mentioned.

Alexander Lichter:

Just Mhmm. If if that's the first idea, maybe there's a second and third that might be better. Maybe it's not. It's, yeah. It depends as the senior developer or consultant would say.

Alexander Lichter:

Yep. Nevertheless, we come to, another feature that is, quite interesting. It is, a function called on watcher cleanup. And interestingly, you might think, okay, wait. What watching.

Alexander Lichter:

Good. We have, like, watch effect. We have watch, and we can stop watcher and, like, we have this whole, like, scope disposal already in there. So if you define me in there, it's like it will be removed in terms of reactivity. So you might wonder, okay, why do we need another cleanup?

Alexander Lichter:

And the good part is here that it's not about saying, okay, the watcher stop. We we stopped that. No. Maybe there is an async operation because, well, these are watchers are great for side effects, of course, not like computer properties where you shouldn't. And let's say you fetch something in a watcher.

Alexander Lichter:

And if you want to re execute a watcher, maybe there's a dangling request that you want to abort. So then you have this on watcher cleanup and say, okay, beforehand you expose in that watcher like an abort controller and you define this on watcher cleanup in your watch function itself and then say, okay, please trigger to the board and then you're fine. That can be for a lot of side effects. We're like, okay, the user has some new input. Stop what I'm doing.

Alexander Lichter:

Let's do something else.

Michael Thiessen:

Yeah. There are a lot of use cases for resetting the side effect in that way. So the example in the blog post is with a fetch. Your fetches in mid flight and the search parameters are now different. Well, then you don't need that previous search.

Michael Thiessen:

So you might as well just cancel it, clean it up, trigger a new one. Yeah. All all sorts of side effects need things like that where you don't wanna just, like, leave them hanging around.

Alexander Lichter:

Yes. And the the like, as you said, there are there are tons of scenarios where it could be good. And also this not only works for watch plus for for watch effect. And watch effect is just, the the function you can put straight in there as well, just an on cleanup and you're good. Then this is the function that's passed in the first argument.

Alexander Lichter:

So it doesn't come out of nowhere, let's say.

Alexander Lichter:

So I have watch effect and an arrow function, first argument cleanup, then you could call it with whatever logic you have in there. So, yeah, if if you ever wondered, how to stop things when rerunning a watcher, that's your answer. Here you go. Could be also, like, I don't know. A great a great scenario is it comes to my mind if you have a notification, for example, or like anything that's also a modal, with with, like, a setTimeout.

Alexander Lichter:

And the time out after it's it's gone, then, well, it will be cleared and then the model should disappear. But if you trigger it again, well, then if you don't clean it up nicely, then it will disappear before the new content is there or have, like, this weird scenario where it's, like, flashing. And, that's also a good scenario where it's like, okay, if the watcher is rerunning, then you should do something with the timeout because, like, you want to set it to the new thingy.

Michael Thiessen:

It's also worth mentioning the the effect scope API, which, is a bit more obscure, I think. But, if you're writing composables, it could be useful. So you're basically able to wrap a bunch of different effects into one scope and then, you know, stop them all at once, clean them up all at once. And that gives you a bit more control in in some cases.

Alexander Lichter:

That's a good point. Yeah. But as you mentioned, it's also quite quite advanced API. I know if if someone's interesting on an episode or video or a blog post on that, then, also there or leave us a comment. If you ever or if you never heard of it, also there.

Alexander Lichter:

Let us know.

Michael Thiessen:

I haven't used that one myself yet, but, yeah, it's, yeah, one of those APIs that's nice to have when you need it.

Alexander Lichter:

Absolutely. And as you said, I I think very important for our libraries like nVueUse, for example, I I think it's a it's a great idea to to have that because you sometimes wanna batch certain, certain effects, certain computers, certain side effects worth watching in one scope. It's like, okay, let's get rid of them altogether. So, pretty pretty good and important.

Michael Thiessen:

So with that, those are all the features that are the main ones for Vue 3.5. We will link to the actual blog post announcing it as well as the the release where there will be all of the updates and fixes and changes for Vue 3.5.

Alexander Lichter:

And also 3.5.3, .2, .1 because of course there were some patch versions already to make sure that, possible regressions are fixed. Luckily, thanks to Ecosystem CI, everything is green. So with a lot of confidence, these release can come out and also frameworks like, for example, Nuxt are tested against that. And also in Nuxt, with the latest version, you easily can have 3.5, already straight on, which means you can use native useID composable and what more. So definitely, yeah, time to upgrade.

Alexander Lichter:

It will make your memory consumption go down, which is great. New features, which is great, and lots of other great bug fixes, improvements and so on. And I think that's, that for this episode, Michael. Right?

Michael Thiessen:

Yeah. That's it.

Alexander Lichter:

Lovely. Then, as mentioned before, check out all the earlier episodes, with amazing guests. We have some more linked, some link down here, but also all there are a bunch of, check it out on your favorite platform. It can be on YouTube, Spotify, Apple Podcasts, your own podcatcher. And, one day we also have a list of them on the website.

Alexander Lichter:

That's, still a big to do, but, still you can find them all together. So check them out and see you as usual in next week's episode, always on Thursdays. So, yeah, see you then, and, have a great day, week, time wherever you are right now, and talk to you later. Stay tuned.