 Okay. Yeah. So how many of you use Vue.js at your company or personally or whatever? All right. Pretty much everybody. How many of you have tried looking into how the reactivity system works? So a lot of people, that's great. But then if you have already taken this front-end master's course against, can I have show of hands if anybody has taken this one? Okay. Or have you read these two articles? Maybe you have. So the thing is, if you have read those articles and taken this front-end master's course, you probably don't need to attend this talk. My job is done. My talk is done. We can all move on and have Chai again. But if you haven't really done that or haven't understood the concepts in those resources, I'm going to help you out. My take is however going to be slightly different in that I'm going to take you into the unknown using all the known pieces that we have, we have been using so far and solve the problem step by step one thing at a time. So yeah, I'm who am I? I'm Praveen. I work at an amazing startup called Voices in. We are a voice tech company and we are great with doing speech to text for Indian languages. So that's what we are good about. And if you want to know more, you can talk to me and one see who here is my colleague from Voices in and we'll be happy to blabber. I also do CSS things on court men like the wallpaper on this slide or the other images that I've stuck up there. Yeah, I also love Indian railways. So that's there. Couldn't finish my truck though. So that's what I do. And sometimes I take up CSS challenges like this one where each flag is a single empty div, no text from JavaScript, your CSS. So I do things like this. And if you are interested in talking about all the CSS things I do, please come to high. And now we can go back to our main talk, which is reactivity. So I keep saying the word reactivity, right? And I hope this would work. Just give me one second. So what is the presentation without a hiccup, right? Internet hiccup. Going to start presenting. And so these are all the flags that I talked about. Maybe you haven't seen them on the slides, but let's get back to reactivity. So I keep saying the word reactivity, but what is it really? Let's take a dumb example. If you come to me and tell me, well, Praveen, your talk was the crappiest talk to have after lunch. It's giving me acidity. My face is going to be like this. And then if you give me an uppercut, because I most obviously deserve it for coming up with this dumb example, I'm going to be totally and obviously dead with these dead things. Or say that did not happen and viewday organizers gave me a bunch of t-shirts for free. I'm going to go crazy with stars literally popping out of my eyes, but I know that's not happening. But this thing though, that something that changed outside and it made my face change is called reactivity. Now we don't punch screens to get things done. We make buttons that click and then we release them, release them as our design system and show list and draw some charts, et cetera, et cetera. So how many of you been building some kind of dashboard? See, that's what I'm saying. Let's take a real world example. When you click the follow button on Twitter, a bunch of things happen and suddenly you are following that person. Let's try to describe what happened here. Clicking the follow button triggered a click event, a piece of code that developers at Twitter wrote reacted to that to get everything done. It fired an API request and got a 200. They changed our UI and we see the blue following button. But here's the thing. What made the text change from follow to following? Or what changed the appearance of the button? We can imagine that behind the scenes somewhere in the Twitter UI code, this may have happened. The initialize is following to false and they calculate the value of follow button text should be following or follow based on whether or not we are following. And after the send an API request and get a success, the change is following to true. And voila, we have our UI updated. And that is what pretty much any major framework allows us to do. They allow us to build, modify, update and change our UIs from data declaratively. They also make our UIs react to those data changes done in future automatically. And they give us tools to do all of these magical things without ever actually touching the top. The question is how do they do it? Because if we know even a little bit of JavaScript, the problem becomes apparent. Let me give you an example. So here we have a variable number initialized to 10. We calculate the value of square by multiplying number to itself. And as expected, we get the value of square to be 100. But now if we change the value of number to 20, we aren't going to get the value of square to be 400. We can say that changing the value of number hasn't affected or updated the value of square. We can now imagine why in the case of our Twitter example, changing is following to true at a later point of time won't change the follow button text anymore. So then all these frameworks must be doing something extra to get a code like this to work. And update our UIs accordingly. The answer is they build a reactivity system. Now, what is a reactivity system, you ask? In the simplest of terms, a reactivity system is like a spreadsheet. In the example above, we have two columns and the value of one column changes based on the other. What we want is a formula to calculate the value of square. So now the talk becomes, how do we make JavaScript act like a spreadsheet? And say all the people sitting in a room, we wanted to come up with a competing framework with this awesome name and totally original logo and open source it. We would have to solve this core problem. Without that, we aren't going to get to the 100k plus stars that you has. And now we need to look for some inspiration to architect our solution. You know what? We don't have to look too far. In fact, we have been doing all this whole reactivity thingie, all our lives using ad event listener. Anybody remembers ad event listener? Good show of hands. So browser have an event system that has been into place since the big bang. If you have forgotten how ad event listener works by writing all your framework code day in and day out, let me give you a refresher. So what we do is we start by saying, hey browser, we want to listen to the mouse being moved around over the body element. And whenever that happens, could you please go ahead and execute this function that prints the value of x and y? So then we move our mouse around and browser does what it promised. So in this case, the mouse was moving diagonally from left top to bottom right. And if I have to say it the other way, our handler that we passed, which is the function that logs x and y, it reacted to the mouse being moved around. Seems like the right direction, like writing to get inspiration from. So let us understand how ad event listener works. If it dig a little, we can see that ad event listener does roughly three things. Number one, it stores the handler we passed to it somewhere against the event for which we are listening. Number two, the browser tells the tells ad event listener, well, hey, the mouse is moved, an event has happened. So and when that happens, ad event listener goes ahead and then finds all the handlers associated with that event and executes all of them one by one, right? So, uh, and don't just take my word for it because we have deaf tools. And if we go ahead and check in deaf tools, we can execute our code and inspect the body element and go to event listener staff. And surely enough, we can see our code being there, right? So maybe emulating what ad event listener does can get us to the solution, right? Now the talk becomes how do we replicate browser's event model so that, so that seems like a simpler problem to solve than the actual reactivity jargon. So let's start by writing some code. And again, I need your brains to be focused here and there's going to be a lot of code. So please be with me. Number one, we know that we need to store our handler. So we create an array called handlers. Next, we need to initialize our data. In this case, number is being initialized to 10 and then square is zero. We create a variable called parent handler and set it to null. And you'll see why we introduced this in a moment. We then, uh, define ad property handler function, which is similar to what ad event listener does, uh, which essentially stores the current handler into our storage. Finally, we define notify handlers, uh, which is going to go ahead and execute all the functions that we have in our handlers list. Now this is all the set of work. Now we proceed to execution. First, we set current handler to the function that calculates the value of square. Remember, we want the value of square to be calculated again and again. So that's the function we want to store and rerun. Next, we call ad property handler, which does the actual job of storing. And we call current handler, uh, we call, uh, and we call current handler. So the value of square is initialized, right? And if we do that, and print the value of square, we get 100 as expected. Now we want to change number and get updated value of square. So we set number to 20 and announce, hey, number has changed and all of you handlers should rerun, which is what our notify handler does. Finally, we get the new value of square as 400, which is what we want. So that seems like a lot, but all we are doing is creating our store, keeping our handlers on a, keeping handlers in our storage and then executing them at a later point of time when we know things have changed. So, uh, that's all. And that gives us a way to calculate the value of square again and again. Now we can see how our spreadsheet example might look like in terms of code. So you change, uh, set the value of number to 10, you call notify handlers, you know, and you get the value of square to be 100, 400, 900, executive. But our final goal is this, right? Uh, where we can change the number and get the value of square immediately without having to do all the manual work that we are doing. And there's another problem in our code. So let's visualize how add event listeners stores our handlers and that might, uh, give us some idea of what the problem is. So for each handler, for each event, whatever handler we give it to, uh, give to add event listener, it stores it in a separate storage for each event. So if, if we had, if we were logging x, y coordinates for mouse move, it stores against mouse move. And similarly it stores the click event for click, right? But our handler, uh, our, our solution has only one storage. So all of our handlers go into the same place. That means even if you change just number and call notify handlers, it is going to read on all the handlers irrespective of whether or not it cares for their change. And that's bad. So we'll need to fix that keeping our goal in mind. We can say that we have three major problems to solve. Number one scale. We have a, we may have a lot of data properties and we need to store handlers for each property in a separate separate place, just like add event listener. So we'll need some kind of abstraction that let us do this repetitive task. In the case of browser events, uh, when we say we want to listen to a particular event, uh, uh, we, we pass the handler and add event listener goes ahead and stores it. But in case of, uh, properties, we want that to be done automatically. So that's our problem number two. Whenever a property is accessed, we want the function to be stored automatically in our storage. Number three, remember, we don't want to call notify handlers again and again. Right? So we should be able to get rid of that part and do that part automatically whenever a property is modified. So that's the major problem. Number three. Now, how do we solve all these problems? So let's create a depth class, which is going to encapsulate the functionality of storing and notifying handlers. Now why a class? Because we can create instances of a class and attach those instances to different things. In our case, uh, different properties. We start by creating our storage in constructor. It's a set. So a handler doesn't get stored twice, even if you try to. Next, we have the depend method, which is exactly what add property handler was doing, but it's just a nice name. And all it does is adds our handler to the list of handlers. And then we have the notify method, which does exactly the same thing as notify handles. All right. So we can go back to our, uh, first, uh, first solution and then remove all the jargon around at property handler and stuff and just use an instance of a depth class. So we first created that instance. We call that depend in place of at property handler. And then wherever we were doing at, um, notify handlers, we are just now doing notep dot notify. All right. See what we want to do is that when we, when square is calculated using number, we want that function to be stored against number, right? And similarly, uh, when the function to calculate message, uh, is to be stored, uh, we, we want to make sure that name is the property that is accessed, right? So that's what we want to do. But our depend method, which we defined in our depth class previously, uh, it just stores and stores the current handler. So how do we make sure that when number, when number is accessed, current handler points to the first function and when name is accessed, it points to the second one. And the solution is really quite simple because of how JS works. Uh, you see, JS can only execute one function at a time. So if we get hold of which function that is, and then call dep depend for different properties, we would know exactly which function is using that property. Let me repeat that again. Since JS only execute one function at a time, if we can get hold of which function that is, we can, uh, store that reference and call dep dot depend for every property. And that will allow us to know which function is using that property. So we can then store our handlers, uh, as we want. Let's move on and try to do exactly that. Here we are defining current handler as a global variable. We then keep hold of whatever our handler is and then call dep depend. So now inside depth dot dep dot depend, we are guaranteed to have the reference to the currently executing function. We go ahead and execute our handler for initial value and then we set it back to null again for a different handler to come for a different property. Also looking at this piece, it seems like we need to do this a lot for different properties. So we create a function to do that and that's just another abstraction and let's call it watcher. So now our code is much more reusable. We can pass our handlers to watcher and then it does all the word automatically. All right. That's a lot. Are you all so far with me? Yes. Okay. So, uh, we have done a lot of work to make things reusable so far, right? But we haven't really used them, reused them yet, right? We can create instances of depth class, but how do we know how to attach those instances to our data? Like I said, also it seems like we need to know when a piece of data was touched. That means accessed or modified because it might be a great opportunity for us to create an instance of that depth class and then do the dependency collection by calling depth depend or depth notify. Right. And that's exactly where object.define property comes in. It's an incredibly powerful JS API that allows us to arbitrarily create properties on an object and define what the behavior should be when that property is accessed or modified. Great. Seems like we can make use of it. So let's take an example. In this example, we are defining a property on our data object. We then say, hey, whenever a is accessed, which invokes the get method, go ahead and console log data a was accessed. Similarly, when a is modified, we were, we log a was modified. Amazing. So this gives us the opportunity to automatically call depth depend and depth notify. Right. So we go ahead and take the step in that direction by migrating from variables to store our data to an object that keeps track of all our data. So we convert our variables to an object like this. We then do some object.define property trickery. We start by creating a variable called internal value that is initialized to whatever value of number we start with. See, we do this because otherwise we would lose the initial value that we pass and get undefined. We then create an instance of a depth class. And then we go ahead and redefine the number property on data by saying, hey, call depth depend whenever this property is accessed and then return the internal value or whenever this property is updated, let's go ahead and update internal value and also call depth notify. Now this takes us pretty close to our goal because now we don't need to call notify handlers manually and because every time number is modified, the setter is automatically called and that pretty much does our job what we need. Right. There's another piece to solve here, which is we can have a lot of properties in our data. So how do we make all of them reactive? And the solution is a very simple converter function that is just the exact same code that we have written previously, but it's just looping through all the properties in our data. So the thing to note here is that the closure function that we use for for each is what allows us to create new instances of depth class and then each property and the getter and setter have access to that instance. So that closure allows us to create new instances for each property. All right. So it seems like we have solved a lot of our problems and we can go ahead and change our watcher function a little bit because when previously we were doing depth depend manually, but now since the getter automatically invokes that part, we can get rid of line depth depend from line number five and our watcher function is now a leaner function. Well, so it seems like we have pretty much solved all our problems. So we have scaled the solution. We have stored our dependencies automatically and we have also done the notification part automatically whenever the data has changed. Hmm. So here we are. We have pretty much solved it. Right? And if we do go ahead and make that JavaScript library that we were talking about, we can now set it open source it and call it a framework killer. All right. All right. But how does what does this have to do with all the render thing? Right? We use render function when and we use templates, right? So how does that work in here? If you think about it, templates are just an abstraction which get converted to a render function and this render function depends on component data. So when we pass that function through our watcher, all the dependency collection happens. Now whenever the component data changes, it calls the render function automatically and we have our UI updated automatically. Voila. We can probably go back and look at this diagram from Vue.js documentation and it might now start to make a little bit more sense as to what is going on. The system we have built so far is great because it's great. And but then it's not flawless, right? We know there are edge cases that we haven't covered. So our choices that we have took so far has made things vulnerable at quite a few places. And I'm going to go through all the bullet points right now. So the number one is we must declare or initialize all the properties we want to be reactive. Remember our converter function that converts all the simple data properties to reactive ones. That converter function runs only once during the lifecycle of a component. So if we want property to be reactive, we must declare them beforehand. So that's why we do something like this in Vue. And this leads us to another problem, which is, well, how do we add a reactive property after the component is created? Because well, the converter doesn't run, right? And Vue comes to the rescue by providing us with a special method called VueSet, which is a global method. And this allows us to create a reactive property on any object in your component. Now, we can use the same as this dot, this dot dollar set in all of our component instances. It just proxies the same Vue.set method. The last but not the least, and in fact, it's the most important one is that our reactivity system fails when we modify arrays or objects using the square brackets notation. It doesn't work because in this way, the setter or getter, which are core part of our reactivity solution, don't get invoked. And Vue helps us here by patching the original push method by slightly to make it possible to detect changes. And we can also go the immutable way and then assign an entirely new array to our data. So that works. And this, all of these bugs, all of these edge cases have kind of led the future development for Vue, which is where proxies come in. The new reactivity system is built on ES6 proxies. I'm not going to go through all the things that are there because that might be talking it itself, but I'm going to go through all the bullet points again. So number one, we don't have to use dollar set anymore because proxies allow us to declare reactive properties anytime we want. Next, we can use the array notation to update or modify arrays. And that works. So our code can now throw away all the hacks that we were going to erase to work. And since we are throwing away all of this jargon, right, that we used to create a setter and getter for all these properties, and it was a giant object mess, right? We were consuming a lot of memory. So proxies come in and they help us get rid of all of that by and make the memory footprint much, much smaller. It also doubles the speed than what we get in Vue 2.x. And we all get all of this due to this amazing thing in the Vue ecosystem that API remains same. You don't have to do anything on your user land code and all of these improvements you get under the hood. So hopefully today we now have a better understanding of Vue internals and the problems associated with it. And this I'm hoping that is going to help you write better and more robust components and make it easier for you to debug Vue apps. So thanks so much. Thank you for being a fabulous audience. Feel free to reach out to me on Twitter and LinkedIn anywhere or in the open space. Thank you so much.