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.
Hey, everybody, and welcome to Deja View.
Michael:Your favorite Vue podcast. You just don't know it yet.
Alex:With me as usual is, Michael. He is an amazing instructor and content creator all around the Vue. Js ecosystem right away from, Waterloo, Canada.
Michael:And we've also got Alex here, who is out in Amsterdam, which might actually be just around the corner depending on where you're at. And he is a Nuxt core team member and does lots of other things, educational content online.
Alex:Exactly. And today, we wanna talk about one amazing Vue. Js feature that maybe some of you used not yet or maybe you did, which is teleports. So one or other has heard about it. And maybe, Michael, you could just introduce here straight away and tell us what exactly are teleports.
Michael:Yeah. So teleports are a feature. It's a built in component that comes with Vue. And it lets us take whatever content that we want and render it in a completely different spot on the Dom. So we're basically teleporting it from one location on our page into a completely separate location on the page.
Michael:That's what that component is, you know, at the at the very highest level.
Alex:Interesting. Okay. So it's built into view. You can just use it straight away in any kind of project. You don't need any third party code for that.
Alex:Right?
Michael:No third party code is needed.
Alex:Perfect. And so when we have the teleport, say, okay, we have some content that should be rendered somewhere else, like, I think the the classic case that, we all know is, like, hey. We have a button that opens a a certain window, also known as a modal. And then we we don't want to be to have the modal, like, be part of the button that's that would be a bit weird, like, structure wise. So that would be a typical use case.
Alex:Right?
Michael:Yeah. So I think if you've ever built a model or used teleport, then you might see these things as being, 1 in the same thing. And the trick with with modals is that you want it to appear over the entire page. And so to do that with HTML, you usually have to put things all the way at the bottom of the page so it comes last. And then you can do some fun CSS things to make it the whole page and all of that.
Michael:But sometimes if you're in the middle of your app somewhere and you want to render a model like that, you can't really get to the very bottom of the page. And so this is what that helps you do. You can use this teleport component and then whatever you put in that slot of the teleport component, it will teleport it all the way to the end of the body or somewhere else, depending on how you have it set up. And then you can you can get around all of that.
Alex:And you you can also run it to different parts of the application. It doesn't have to be the body, you say. You can also say, like, okay. I have, like, an own element. There should some things go in, or, I don't know.
Alex:Like, I have I have a header element. I want to have some things teleported up there, even that works.
Michael:Yeah. Yeah. So you can teleport things however you want all the way around your, application.
Alex:Smooth. That's pretty cool. And so you say that we just we just discussed that. Right? Like, a model as the the typical use case.
Alex:Do you have any other scenarios in mind where you think that's, like, that kind of teleport would be useful, either to make it easier to style things or, as you said, like, to have them in a better structure so they can go on a full screen or a p where they should appear.
Michael:For me, I I guess I kind of group all these things into, like, a modal like thing, and I don't know. I I may be imp not that precise with how I use the word modal. But but if you have, like, an image gallery that you wanna display as, like, you know, that light box style where you click on the image and then it expands to to be the full page, the full screen, that's something that you wanna do, or notifications or toasts or whatever you, whatever term you like to use for those, those you wanna put it somewhere near the end of the page. So again, they can appear on top of all your other content. You know, there's basically, anything where you want this content to appear on top of everything else, that's a great use case for it.
Michael:But I'm sure there are lots of other use cases. I just haven't come across them.
Alex:And can you can you also nest them? Like, I just imagine having a model inside a model. Like, please don't ever do that in production, folks, but I guess sometimes you have weird requirements, and you you can't do something about that. Is it also one scenario? Like, can you nest teleports?
Michael:You know, I have not tried that, but I would imagine that you couldn't. Is that possible?
Alex:It's it's an interesting part. Like, if you think about, okay, let's render a content somewhere else, and then content from there is also rendered somewhere else, I would I would imagine it works, but I don't see why it's it's necessary. Of course, once again, we need requirements. But I can imagine that that can cause some confusion to people reading abilities. Right.
Michael:Or or teleporting something into another teleport so that it just gets teleported to a a third spot. Right?
Alex:Yes. So There's already like, already in my head sounds very confusing. So
Michael:Yeah. Yeah.
Alex:I think in in general, when it comes to teleports, I I have the feeling you you would use them rather, like, sparingly. Like, not not every application necessarily has teleports.
Michael:Yeah. And and you would want to be careful with them because they also break the flow of of how your code appears. So the the nice thing is that it separates what gets rendered to the DOM from the the code as it appears in your your project. But then that also is gonna be a source of some confusion potentially, or could lead to some bugs where, you know, you've got any component in your code base can now teleport to wherever it wants. And so you can have code ending up in all sorts of places that you didn't re you didn't expect.
Michael:It's the same it's kind of like global state in that way where, you know, anything could be put in there. So, yeah, I I would I would guess that you would want to have things and use this sparingly.
Alex:That makes sense. And what about I know I know we haven't discussed it in-depth by now, but what about, like, async components or suspense? Have you ever tried rendering, like, suspense content or asynch components inside a teleport? Any chance ever ever did that? Because I I remember I tried that, and it somehow it failed.
Alex:So maybe you have a bit more experience on that.
Michael:I actually haven't tried this myself, so I would be interested to know how that works and how that interacts with, with that. But again, it's like, one of these, these things where at least my understanding of how it actually works under the hood is, is not that strong. And so then how it interacts with SSR or a sync and suspense, or, you know, having multiple things teleporting to the same spot is like, these are sort of questions in my mind of, are these good things or bad things or, like,
Alex:you know, where Did you ever do them? Do them? Did you ever do them? Yeah.
Michael:Yeah. Fair. Yeah. Yeah.
Alex:Fair point. And, yeah, when when we when we come to to these scenarios, do you can you imagine any other, like, pitfalls or problems when it comes to teleports? Now you mentioned, okay, like, nested might be a bit strange, and we agreed, like, we maybe we shouldn't. It might work, but, we'd be interested. If anybody of our listeners has a a scenario where it makes sense, I would be super curious.
Alex:I also remember, like, headless UI, for example, from from the Taewon people also uses their own, like, portal component, let's say, to somehow mimic teleports. That was also very interesting because there you can have, like, nested dialogues more or less to have, like, a dialogue and then something nested because they don't tell you how to style it as well. And, it still it's it it can get quite messy. And I remember some some bug reports around there too where things disappear in certain scenarios. So it's it's tricky.
Alex:Yeah.
Michael:When you have a lot of things going on, then it also becomes a UX question of, do you allow, like stacked models or, or do you like, can you open a model from another model? And like, what, like is that some people don't like models to begin with, and they just say, like, you should just open up a new page. And, you know, there's all those questions that are, you know, beyond the scope of this tel port component itself, but interesting to to think about as well.
Alex:Absolutely. And now that we that we already mentioned, like, your UX question, we can also jump over to accessibility straight away, because there is I think since 2022, there is this dialogue component in HTML that finally, in a way, allows us to create models on our own. Have, have you ever, like tinkered around with that Michael, by any chance by now?
Michael:I saw this component being, being shipped and I was, I was glad that it was there, but I haven't actually taken a, taken a look at that. I think at the time I was working in a place where we had our own component library, and so we were happy with that and not looking to to do any major refactors or anything like that. So so I haven't actually managed to, take a look at that. Have you have you tinkered with that one?
Alex:I I did quite a bit because at first, I was like, okay, it's amazing if I can do things natively, if they work the same way, of course. And Yeah. As I'm usually not very tied to component libraries or, like, just spin up a small project, I was like, okay, let's try it. And actually, it works quite well. We still have a few things with, like, accessibility concern because it's still recommended to set, like, focus, I think, manually when you create it and so on, so on.
Alex:So there are a few things that are still up to developer eventually. And there are also some scenarios that don't work because the dialogue is the the, like, topmost component eventually. So let's say you have a dialogue, and there, you have a word. If you wanna hover hover over the word, you have a little, like, label. It'll pop over explaining a word, for example.
Michael:Right.
Alex:This doesn't work anymore because the dialogue is the topmost element, which also means I haven't tried it, but I guess no nested dialogues. And then things get a bit tricky because you you're limited in a way there and have to fall back to to other ways of doing that, like with a div and a portal eventually.
Michael:Right. So if you're just gonna do like pretty basic, like confirmation dialogues and things like that, then that is a good use case for that one. But
Alex:Absolutely. Yes, that
Michael:is. For if you're gonna do like a settings model where you're gonna, you know, have all these tabs inside and wanna update your user account or, you know, more complicated functionality, then
Alex:it's not
Michael:not as good for that.
Alex:Yeah. It can be tricky for sure, especially if you realize, okay, you build the thing and then then you're like, oh, I I need the the popover, for example, and then
Michael:Right.
Alex:That's that's always unfortunate. But, also, there's this popover, I think, API coming to the browsers. I think it's already shipped in Chrome soon, so that will solve that problem again. And then we we're good again. But that that that might take a little bit of time.
Michael:Yeah. I the more things being shipped natively, the better it's just that, you know, you, you lose some control. And so there's always, always trade offs there with, with that.
Alex:Oh, of course. Of course. But, yeah, I'm I also agree, especially when it comes to models. I'm very happy if I don't have to build it all by myself again. And then once again, don't forget things like, okay, you need a useful close button, of course.
Alex:You want to have a focus strap so people can't navigate out of the model when it's open, like, accessibility wise. I still remember I like to use the keyboard a lot and always when I use tap and then jump out of the model, I'm like, that's that's unfortunate. And and, like, all these things, like, there there is lots of work to build a pretty decent model, especially if you really start from scratch, If you use, like, a a functional library, like, headless UI and and others to help you, that's already a good start. But even there, you have to deal with these things on your own, like, with the focus. It's or the the focus might be even solved, but, like, with, okay, where to place the close button and where to make sure that that certain other scenarios are considered and so on and so
Michael:on. Yeah. It's it's a lot of extra stuff and the teleport component only solves that one piece for us. It's an important piece and it, you know, you shouldn't help us solve all these other things, but it's, it's a useful thing to have in the the framework. I remember before the teleport component came in, the strategy that I recall using was having some sort of, like, a modal manager component that you specifically rendered at the end of your application, and then you had some sort of Vuex store at the time that kept track of all of the content on the models and which model was active and
Alex:Mhmm. And
Michael:all that kind of stuff. And then elsewhere in your application, then instead of rendering directly the model, you could sort of set, have a, a mutation that you you set that would trigger this model. So that was one way that it worked. And then you have this, like, management layer that kind of deals with all these things. Probably more useful for things like notifications and stuff where you, like, want it to pop up for 30 seconds and then disappear and all that kind of stuff.
Michael:But yeah. So I I think with the teleport component, we still need that kind of system in some way?
Alex:That also means we're a bit more flexible. Right? As we mentioned with Swift dialogue, it it gives us limitations. And for a model, that might be fine as we discussed before. But, yeah, we need some business logic in there.
Alex:And then standard not necessarily can help to relieve relieve from them. We need the business logic still, and we need to implement it. And we need a way to do that. So I also I also just mentioned notifications, which is a great example for Teleport as well. I think I use it even on my own site for that because it makes things easier.
Alex:But as you said, it just allows us to render certain content there. But about appearance and what should be rendered exactly, that's still our job.
Michael:I'm trying to think of other use cases for teleport that are beyond just this modal notifications thing, and I'm I don't know. Like, are those the only categories? Because so if you have like a chat application or like a chat chat window for support, let's say, lots of sites have have this and there's, like, you know, that floating button at the bottom. Right? Yeah.
Michael:You can click it and you can chat with support. Is that like, you could use teleport for that, but is that a model? That's just like a popover thing.
Alex:Yeah. I think it's
Michael:it's it's
Alex:more or less it's another element you wanna render down there no matter if it's if it's, like, notifications you can click or or a button, like, also these, like, scroll to top buttons. I think it's also
Michael:Oh, yeah.
Alex:A good option. Though even with them, it depends if you want to render them on your, like, app dot view or on your page level if every page needs it or if you say, okay, I define that that element that should hold it and then teleport over there, which is also a fair way to do. But, yeah, I think as as long as you need some dynamic ways to move things over, that can be used. I've also seen applications where the header was like, there was an image for the header. It was teleported over there because it couldn't be changed on the place straight away because the information wasn't there.
Alex:So that was also an interesting way to to see that used. It's not something I would recommend, I think, because it's still there are better patterns for that, But I know that people also use it as escape hatch more or less.
Michael:One important thing to mention is that the teleportation, like where where it gets teleported doesn't have to be inside the Vue application. We can teleport outside of the app. So if you have a progressively enhanced website, that could be an interesting use case that you might need to use teleport for, where you have your app rendered in one spot and then you teleport some content out into another part of the of the page?
Alex:Interesting. Yeah. Especially when you don't, like, have Vue or Nux fully built by your like, your front fully in that language. That seems like a compelling version too, indeed. Interesting.
Alex:Yeah. That's a really good point. I I didn't think about it too much because, usually, like, most of applications are fully built with with you, or Nuxt in that case. But, yeah, the progressive enhancement, that's that's a really good point too. Nice.
Alex:Great. And while we're at it, have you have you used models or no. Sorry. Have you used teleports back back in Vue 2 times, Michael?
Michael:I don't think I have.
Alex:I I still remember, like, the the core team member, Linusborg, aka Thorsten Lundborg, came up with with a with a module or, like, basically, an MPM package for that saying, hey, Let's have, portals, as it was called back then. I think the packaging was, like, view portal, to also have exactly that functionality and allowed us to move things over. I remember I I used in quite a few applications just to make notifications or models being a bit nicer to style and to show and so on and so on. So and it's really nice to see that they are part of the core now, which is once again a great thing of, Okay, it's open source. Somebody released a package for it.
Alex:And, Okay, in this case, that somebody was a Vue core team member. But it could have been in a in, like, a user as well, a developer newcomer. And, eventually, we see that in the core because it's an important part.
Michael:Yeah. It's nice to to see that, like, borrowing from other packages and and other things in the in the ecosystem and, like, pulling it in where it makes sense. And yeah.
Alex:Great. And I think then there's just one more thing to discuss. Now we we talked about progressive enhancement. We talked about the client side of teleports. Maybe we should also talk about the server side rendering together with teleports because by by experience, I know this is, a common thing, and there are also some pitfalls there.
Michael:Yeah. So in, 3.11 in Nuxt, there was a new feature that landed, which I think you might know something about.
Alex:Yes, indeed. That could be because I I wrote, I wrote that, indeed. So the idea is that hydration, which is the process of converting the HTML from the server to, like, the client side, the viewer representation, this is a bit tricky with teleports because so you you have basically 2 options. In in view, if you do, like, a teleport to body, let's say, it will be always, appended at the end. And in Nuxt, we couldn't really do that because then we don't know where the hydration should end and will give some mismatches.
Alex:So none of the service side rendering apps will still work. So we had to, prepend them, so put them on the top. That started, another issue where people say, hey. On the client side, this works differently than on the service side, and we align that behavior. And, also, yeah, we want it at the end for for styling purposes, which makes things more complicated.
Alex:So then the idea of, app teleports was born. And app teleports, well, the idea is we just followed recommendation that Evan had a while ago anyway, and the link to that is also in the show notes as for all the other things we talk about. Because he said, yeah, even in a client side view application, you usually shouldn't teleport to body. You should have an element that's next to your application, as you said, Michael, so, like, outside of your app, and then move everything in there to have control over that. And that's more or less what we implemented for Nuxt.
Alex:Js as well. The target is, by default, hashtag teleports, so just as an ID. But you can change the name, and you can also change the tag if you want to, if it shouldn't be a div, but whatever. If you have interesting business requirements, go for it. And then you just say teleport to teleports, and that will simply work, meaning that now the hydration will work as expected.
Alex:Your things are listed below your application, so you have the proper way of styling them there below so the the tech can lie over everything, and you're good to go. That's more or less the the whole feature.
Michael:So now Nuxt is adding in this special element at the end, specifically for teleports so that we can make it SSR safe. Right?
Alex:Exactly. That's that's mainly for that. And as I said before, it's more or less also just just, quote, unquote, following a strategy that Avenue suggested in the beginning. But, of course, as not everybody uses teleports, especially not on the server side because that's also it's not the most common thing to do that on the server side, but it's still necessary sometimes. Then we thought, like, okay, there there is an issue around it.
Alex:And I was like, let's let's fix it. Let's see what we can do. And implementing that little extra tag was the way to go. And, of course, you can also disable you can enable or disable it as you like. So if you never use it and you want to save that one dumb node, you're free to do so.
Michael:So with, this feature, what are things that get server side rendered inside this teleports component, this teleport component. Because I would imagine that for most models, we are only rendering those on the client side and, and probably even lazy loading these components based, you know, depending on how heavy they are, and notifications and things like that, probably not rendering them on the server side. So do you have any specific examples that you can recall of, of rendering on the server side into the that teleport component?
Alex:Yeah. Like, I agree with with most of the things. If you use teleports on the client side, you will never use that, that teleports on the server side, and that's fine. You can still teleport to it to make sure everything works as expected. Right.
Alex:Sometimes, like, okay, you want to open a URL, and it should open a model straight away. Like, I don't know. You want to jump to the confirmation of something or you have some interesting case with the light box where it say, hey. Show me that straightaway in that area, and that would be the way. So you see the same as we do on the client side, but straight away from the server.
Alex:And it's also like, you you don't have some kind of layout shift because you just see the site, and then on the client side, you render it. And it's once again like a black backdrop. You're like, oh, the site was just white a few milliseconds ago. So it's also there to improve the user experience. But, of course, if you don't have to render any modal or light box and so on and so on on the server side, then you're good.
Michael:I see. I see. So, like, deep linking straight into a model being opened.
Alex:Yep. That would be one of the cases.
Michael:That makes sense.
Alex:Exactly. And also notifications, you can do that if it's not like a user based notification, but more like, oh, hey. This is like a general way of telling something if if you want to. But I think even on my side, I mostly rendered them on the client side. Though I also use static side generation, so that would be tricky otherwise.
Alex:But yeah. And I also I checked to to cycle back on on the suspense part. So there is apparently a bug right now in vuecore that was created by Daniel, lead of the the Nuxt team, that says you cannot, right now you you get hydration errors with suspense elements in teleport. So that's broken at the moment, which is also a little bit unfortunate because that also is appending server components and so on in Nuxt. But we're getting there.
Alex:There is a PR on the way I've seen already. So the the Vue core team people are on it, which is amazing.
Michael:Yeah. Always always things to iron out and to improve. And I mean, that's that's the great thing about open source is that we can contribute to that and, yeah, push things forward, always Absolutely. New stuff.
Alex:And I'm I'm very happy that also people take the time to create these reproductions because this makes it so easy for us to dive into these issues because I think we all we all seen it every now and then. We're like, okay, there's there's an issue in the framework. Let me quickly do a reproduction. And then you figure out, oh, wait. It's my own code.
Alex:I never have to send it. And it also means I don't have to wait forever or for a week or a month for someone else to tell me, oh, I can't reproduce it. It might be your own code. So just, like, as a as a developer, the skill of creating a reproduction is so invaluable just because it will help yourself so often saves you lots of time. And even you say, hey, I want to show it to a colleague or it's an internal library or it's a legacy project, whatever, in all cases, this will come handy.
Michael:I found it very helpful to learn new features and also debug things when when they're not working as I expected. A lot of times these apps that we have are there's a lot of stuff going on and there's, you know, there's extra state, there's we've got pina stores all over. We've got, you know, SSR, we've got all this stuff. And so it's easier to isolate, like, what you're actually trying to do and get rid of all that noise and just, like, spin up a quick sandbox and and test it out and say, okay, it is working something so then something else is going on that's breaking it in my application. Or, okay, what I thought I would work actually isn't working.
Michael:Now let me tinker in the sandbox, and then I can figure out what, like, how to actually make it work way faster, and then I can take that knowledge and and port it over to my actual app. And then I found that to be a much faster, much better way of debugging things than just like trying to constantly tinker with it inside this app. And then, you know, there could be any number of things that are affecting that thing and breaking it. So
Alex:that's the thing. Like, it could be your code. It could be your colleague's code. It could be your 2 days old code or your 2 years old code or the framework code or library. There are so many moving pieces.
Alex:And I totally agree. It's like debugging is way easier that way or also learning new concepts, just like trying out things. And if you say, oh, it doesn't work, and you're in a sandbox, then it's it's way, way easier first to share and to ask for help because nobody wants to dig through your whole project, and nobody has time for that. Like, that's also a harsh truth in the end. But it's also easier to then understand, like, okay.
Alex:That does the work, but this works. So where where to go from here? So the learning, create your reproductions. And and also learn to express, like, oh, hey. Not only here's the code, but when I click here, this is happening, but I expect this to happen because whatever the docs say so because it was this blog post from 2012 mentioned that in the footnote.
Alex:Who knows? But that's also, like, one thing. As soon as you write a code, then you can also, like, take 1 or 2 minutes to just describe it because just because I have the code, it's not necessarily clear what I have to do to reproduce it. You're you're the one with the problem, and you're the expert in the problem to describe it. So yep.
Michael:I like that framing of you're the expert in this problem and, yeah, transfer that knowledge.
Alex:I actually got that while I was working my thesis. I was talking to my supervisor. Hi, by the way, if you're listening. It could be a very, very fair chance. And the idea was also there that he he was saying, like, yeah.
Alex:Look. You're you're the subject expert. Nobody should be, like, deeper into the topic scientifically than you are. So now you have to more or less summarize it, dump it down, and tell us what you found out and how you did it. And that works with a reproduction in code the same way, but luckily, you don't have to write 97 pages for that.
Michael:True. True. So I think we've covered a lot of, teleport and the component and how to use it, what to use it for some pitfalls, how to use it with SSR and suspense. Hopefully soon, we'll be working with hydration and all of that.
Alex:Exactly. And we also seen the dialogue element, how that compares to teleport, and that it can solve some issues, but it's also not perfect. We still have to write some business logic.
Michael:So that is it for us. We will see you next week.
Alex:And maybe you haven't listened to any previous episodes, so then go all the way back, check them out because they're really cool with some amazing guests on there and also with the 2 of us. So, yeah, see you next week, and stay tuned for everything upcoming.