Vue.js is a frontend framework. But the different modules, such as the reactivity engine can be imported on its own. Let's have some fun and explore possible use cases for Vue reactivity in the backend.
Taking Vue.js to the Backend
Hello and welcome to my talk about taking vue.js to the backend. My name is Marc, I am a self-employed software developer based out of Luxembourg. I work a lot with vue.js and Nuxt, also with node.js in the backend. And I have a podcast, it's called Decoding the Code and you can always find me on Twitter. I'm quite active there, so if you have any questions or raising up from this talk, just hit me up and I will follow up with you of course. So yeah, vue in the backend. You might think yourself, are you insane? Why would you do that? So yeah, a quick disclaimer, this talk is not about a very production way of how to build vue backend things. It's more of a thing of how to provoke the thought for some things we could use vue in the backend for and this is vue reactivity. And I got the idea for this talk earlier this year and I even tweeted about it. I wrote to Evan Yu, hey Evan, do you see any problems using vue 3 reactivity engine in a node.js backend? And I was glad that he replied, so he wrote, just be mindful what you want to make reactive. The api defaults to deep reactivity because that makes more sense in the browser environment, but in node.js you'd want to avoid deep proxying node, node buildings. Make sure to use shallow ref and shallow reactive. So yeah, so we basically have the thumbs up from Evan Yu to do this. And I got another reply from Alexander Lichter. He actually pointed me to that Oscar Spence had a talk about it in vue Conf US. He wrote this totally great talk by Oscar Spence about vue 3 reactivity in the backend context, which was exactly what I wanted to do. So some of this code that I'm going to write today is inspired by Oscar Spence's code, a little bit different, but the idea bases a little bit on his talk. So thank you Oscar for the groundwork you made for this. All right, so we want to use vue 3 reactivity in the backend. So before we get to that, we first have to know what is reactivity really. So reactivity is when you change one thing and you update it wherever it's needed. So in order to do that, we need to listen to changes and we need to notify when a change happens. So we can do something that's called an effect, a side effect, something that should happen when something changes. For example, a number value changes from 3 to 5, so the slider has to be on another position, for example. All right, so yeah, this is the observer pattern. So vue 3 reactivity, in vue 2 we use the object.define property and in vue 3 we override the getters and setters for object properties by leveraging the magic of ES6 proxies. And we are going to go a little bit deeper into that. So what's a proxy? So if you create a proxy from an object, by default it behaves the same way as the object. So for example, if I write a value to this, it writes it to the object, to the target, and also when I read from it, it returns the value from this target, so it behaves exactly as we think it should work, which is great. But proxies have a superpower, and this superpower is that we can intercept these two hooks, as it's called, set and get. Of course you can intercept more hooks, but these are the two that are interesting for this use case. So you can write whatever code you want to replace the setter and getter methods with. And in the demo we are going to see what we do with this. So yeah, let's get this party started, or better, let's get this live demo started. First starting with getting a little insight into ES6 proxies, and then we are going to make a little live demo where we see how to implement some vue.js backend. So let's see. Alright let's get started with proxies. To show you how it works, I will just create an object first, it's called person, and this person has a name, mark, and it has an age of 34. And we create our proxy as such, new proxy from person, and it expects a second argument, which is called a handler, and we are going to see in a bit how that works. But for now I can play around with this on this side of the screen. So let's just see first what's in there. So it's this proxy, and what we passed here. So nothing spectacular so far, but when we go there now and say proxy.age is 35, it sets it to 35, and when we read it again, it actually updated. So this is pretty much what we expect, how it should work, and that is how the proxy is shipped by default. But we can modify the proxy by overriding some so-called traps or functions in this handler. So the getter function, it takes two arguments, target and key, and let's just see what it is, console.log target, target and key. And let's see. So this is invoking the get method. So here we can see it logs out what we wanted to log out, the target. Now we can see what is the target. The target is nothing else than the real object, and the proxy is just the front of that. So this is what is in the back of the proxy, if you will. And the age is the key we want to get, so in this case age, and when we say the name, well it says name, perfect. So let's just call this here get, so we see what we're working with. And you might have noticed that it always replies undefined. Why is that? Well, because we're not replying anything. I told you we can completely overwrite these functions, but now we broke it, so we have to re-code the functionality. So what we're going to do is we're just going to return the target with the value key. Let's see if that worked. Like a charm. Perfect. Now let's overwrite the setter. Setter takes one more argument, value. So let me just be lazy and copy this. Set key to value. What happens when we set the name to Jimmy, for example? Yes, set, and then name. What do we want to set the name and to which value? To Jimmy. So now when we output the name, it didn't change. Why? Because again, we didn't set it. We just overwrote our original function and broke it. Okay, let's fix that. Let's set the key in the target to the new value and let's try again. Name is Jimmy. And then when we try to read the name, hey, it updated. Perfect. Now we intercepted these functions, but what should we do with it? In view reactivity, we do something like, in the get, we track. Do something that's called track. And here in the setter, something that's called trigger. Well, it's actually, we pass the target and the key here. So what this does is the track is, so we noticed that there's something that in effect, something that wants to be observed. So we just take it in and we write it in as a dependency. And then when something changes, when we set a new value, we trigger that. So we tell the system, hey, something changed here. But that goes all way too deep. And I have another conference talk, various conference talks about this topic where I go a little bit deeper into the view three reactivity. But for now, this is enough. Also in the real version of view three reactivity, we don't use this. We use something called reflect to solve some caveats, but I'm not going to go into that too much. But because we are looking at something different now. So yeah, view three has a function called reactivity and it's more or less something like this. Function, it's not called reactivity, it's called reactive, sorry. So we pass here target. And what do we do with it? Yeah, we just make a proxy out of it, just like this. And we return the proxy and it's not the person, it's the target we pass. So now if we want to make an object reactive, all we have to do is reactive this. Okay, let's try it out. Let's go. All right, let's go ahead and get the value. For example, the age. And yeah, so it invokes our get hook where we lock things out and in the real version of view reactivity, we track. So we tell the system, we want to know when the age changes. And then when it does change, we trigger it. So we tell the system, hey, this changed and then do your thing and execute that side effect that needs to be done. All right, so this is proxies. Now we're going to move on to some demo where I'm going to use all of this in the backend. All right, this is my backend, nothing impressive going on here. It's just my express server, boring, and three routes that I work with. One is join, leave, and message. They also replicated to in my rest client, it's called insomnia. Login is just passes the username, message, which username and which text, and then we leave and again, the username. So there's no identification here. There's no real interaction with real users. Those are all stuff that we have to imagine that will be added later. But for the moment, let's just focus on the reactivity for this one. All right, so the first thing we have to do, we have to add actually vue.js in our backend. How do we do that? Well, yarn add vue.atNext. If you do vue.atNext, it's version three. All right, it's installed. Perfect. Let me hide the sidebar. Perfect. Okay, so let's first import a few things that we need. Require view. And what do we need? We need the reactive function we saw earlier. We need effect. We're going to come to that later, what exactly that is. And we might use a computer property. All right. So far so good. And let's create a reactive array that's called users. Users is reactive, and it's an empty array to start with. All right, so far so good. Nothing happened yet, because we didn't write any real code yet. But let's start by join. When we execute this, we want to add this user to the array. So this is the easiest part. We just go users.push. And what do we push? The body of our request. All right, which is exactly this. So just the username. All right, when we do this now, nothing really happens yet, because we're not reacting to it. So that's our first effect. And so I told you I would explain what this effect does. But to do that, let me write the effect first, and then I'll explain this. So here we console.log usersChanged. And let's just go to the length of the array. So when we go there now, we say usersChanged 1, 2, 3, 4, 5. So this effect, how it works is you pass a function here that if something inside this function changes, then execute the function again. So it might seem a little bit complicated, but that's the easiest way to put it. If something inside a function changes, execute it. So in this case, the length of usersChanged, so it's executed. So it's an output. All right, but we don't want to access here only this. We want to do something like this. User this and this joined the chat, right? And it's going to be something like user.username. We just have to get the user first. So the user is going to be the last one in the array, because yes, when you push something to an array, it's on the last position. This is convenient for us, because it's an easy thing to do. We just access the index of length minus one. And here again, because here we access the length of the user, this is executed when it changes. So hopefully this works. It did not work. Why? Because username of undefined, of course, it's undefined at the beginning. So we have to make a small check here. If there is no user, just return and ignore the rest. All right, let's see. Okay, now it works. Then we send the request and bam, it worked. This is perfect. So the user mark joined. Awesome. Now to leave, that's the next thing we're going to code. How when a user leaves. And this is a little bit more tricky, because we're going to do something a little bit more unconventional. So let's say the username, we have something like this, right? What we do is we set the leave to true. So this user is leaving. And then our effect is going to catch that and it's then going to set left to true. So we know when a user wants to leave and then we know when the action is completed. So that's what we are going to do. So first we need to use that's leaving and we are going to do it like this. The user is, we find a user where the username is the same as we pass here in our request body. So request body, come on, body username. And also if they haven't left already. So we filter out the ones that have already been marked as left. And then again here, we might run into some trouble if there is no user. So if there isn't a user, just do nothing and if there is, set the user leave to true. All right. So yeah, this is going to find the user with the, what the username is the same one as we pass here and which hasn't left yet just on what he wanted to leave, but the operation isn't completed yet. So to do that, we create an effect and here we are going to do the following. I filter the users for users that are leaving, leave and, but not that haven't left yet. So and not left. And for all of these, we do the following. Let's go in the next line. We set the left to true and we log out the user, this and this left, and this is going to be user.username. All right, let's try it out. Let's first join, mark join. Perfect. Mark left. Perfect. Again, not working because there's none in the list. Okay, perfect. All right. The last part is to send messages for that we need another array, a reactive array messages. And here we need to add the message messages.push request body. Awesome. And then we need a similar effect to the ones we had for the users. So I will just sneak that and I will replace user for message and we are going to log out another message. So we put the user in parentheses and then we write the message. So it's message.username. Awesome and then message.text. Okay let's try that. Let's log in. Works. Let's send a message. That works as well. Awesome. And let's leave. Awesome. All right, unfortunately we are done. I would have loved to show you a lot more, for example, computer properties, but that's just not in a time. But this is how we could use vue.js in the backend. Of course, this is not how you would exactly implement the chat, but just to visualize or to show you what is possible with vue in the backend. With that, thank you very much for your attention and of course for not falling asleep. And if you have any more questions about this, make sure to send me a DM on Twitter. I will respond to you and yes, have a great rest of the conference.