Qwik Framework Deep-Dive Full Course with Misko Hevery (The Creator of Angular & now Qwik)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I would like to give you kind of a background on from a technical point of view of like what makes resumability different and so um the the kind of the key thing to understand is the way normally the system works is you server side render and once it gets declined you have to do a bootstrap and this fat Arrow over here represents the fact that huge amount of code has to be downloaded and executed before you can go on to the next step so what is the the goal of all this the goal of all this stuff is to get an interactive website right you want to get interactivity and well how do you get interactivity well you have to render the page because rendering is a place where you attach listeners to the UI right so in order to get interactivity you have to do rendering but in order to do rendering you have to have a state of the system so you have to uh you have to have a state of the system but also you have to have that all the templates present and so in order to get here you kind of have to work backwards and say well I need to render in order to render I need to have templates and data in order to have that I have to download everything and so you end up just downloading this huge app right up front and so the trick of reasonability is that you start in the same place you do SSR and our bootstrap is super tiny it has nothing to do with the application instead it's just a essentially a global listener I mean it's super small it's about a kilobyte on a modern device you know it can take about one millisecond to execute maybe 10 milliseconds on a mobile device that's super slow but it's extremely cheap and what this piece of code allows you to do is basically bypass everything and go straight into interactivity and once you're interactive you know when you interact with the page you might have to download more code so all of these arrows that you see over here represents areas where more code can show up more code can come to the UI and make things Interactive and so instead of having one huge big fat Arrow here you have many small arrows all throughout the execution of the application and these this arrow is not necessarily represent downloading of the code although that can but really what this errors represent is the amount of code it has to be executed it's about delaying the execution of all of the code up front yes if you delay execution you can also lazy load but it's not about laser loading the primary thing yes so just a point of clarification we're reloading is more loading into memory yes for execution's sake rather than like shipping code across the wires okay yes so the the expensive part is well all the bits are expensive right shipping the code over the wire is expensive but um usually when we talk about expensive in terms of time we're talking about the the fact that the browser has to parse the code execute the code Etc and the the problem usually you get into is that um it's proportional to the size of your application so if you choose an architecture where things are proportional things might look okay during the Prototype stage but as the application gets larger and larger and larger you're like death by a Thousand Cuts right you're slowly decreasing the performance and there isn't an easy place where you can just say like this is where things went bad right like it's like they slowly over time jobs got worse yes Spa approach or the response to that is oh well we'll break everything up into microfinance yes so then you have a limit let's say you have a thousand apps each of those apps is only as large as you know that subset of routes or whatever yeah um but having building single microfinance is not trivial with the querying Frameworks that really weren't designed it's possible people have done it but they're just just an optimal way of doing it and so one of the things I want to talk about is how quick is particularly um um you know designed in a way that makes microphone ends particularly easy to do with quick um and so before we kind of dive in here I have this fun little uh you know three slide presentation that I think is is fun to talk about so uh I'm sure you're familiar with the cap theorem right in the databases that basically says you can choose any of the three things you can have consistency availability or partition tolerance but you can't have all three at the same time and then Google comes along and says you know what we're going to break this cap theorem by installing atomic clocks in our data centers and through the uh fact that we have a clock that we can guarantee is the same through all the atomic clock centers we can actually build a system called all three it's called spanner and it is available you can use it on Google Cloud platform and I think it's kind of amusing that you know you you know there's a theorem that kind of was broken not really so we're gonna as a joke but I think it it kind of points it out is that I think there is a front-end cap theorem as well which is that you have all these Technologies and all these Technologies give you three things but you can only have two out of the three and then basically there are capabilities in terms of like what you can build with a particular technology you can have an awesome DX and you can have a good startup performance and it turns out you can have two out of the three right now so for example let's let's pick on react or angular most most Frameworks we have today fall into that category and so what you get is that you have awesome capabilities right there is very little you cannot build with react angular salt and so on and people love the DX of these Technologies you know they may be necessarily allow all of them at once but like you know there are people who say like yes the the developer experience is great but but we know that startup performance of all these hydration systems is really not that good and so you can't have starter performance so then it comes along Astro and says we have amazing startup performance or 11t and people love using Astro you know they have also a good developer experience uh but guess what you can't just build anything with 11t or Astro right all of a sudden the kinds of applications you can build are greatly diminished and so again you're in the situation where you get to have two out of the three things um Google is is the internal framework that I kind of mentioned yesterday for building uh fast performant applications so Google Wiz actually you can build just about anything you want in terms of the capabilities uh and it has amazing startup performance as I talked about you know it's powering um Google search but you know it it's public sorry the Google list is private so you can't see but I can tell you that building web applications with Google Wiz is cumbersome it is not easy there are many constraints in there in the system to make it fast and so again you're in a situation where you're only having two out of the three things and so the thing that we're trying to do with quick is to put it actually in the Middle where you can build anything you want with quick you do it in a developer experience that you enjoy and you can have a startup performance that you you want you want to have all three in a single framework and I think there's a new set of Frameworks that are kind of coming into this uh this category one being uh quick the other one I think is Marco and so on um but I think this is the kind of the future of the things is that we've been too long stuck in in choose two out of the three and really you want to be in the world where you can have all three all at once so let's go and let's build some stuff I think the most interesting place to start is that let's take a um I'm going to choose react because this this happens to be a a place where I can easily get react up and running and let's build a small app in the react and let's say we want to get lazy loading or resumability in and so let's see what kind of issues we're going to run into okay so here is a simple react application I think this one is all in the client there's no server-side rendering but you can imagine that you know let's say we have server side rendering um the thing that's that's interesting here is that react needs to be able to run your application to figure out are there any listeners anywhere and so whether or not this application is actually interactive this one isn't right because there's nothing in here uh react doesn't know that and so it has to go and execute all of the code in order to figure out like where are the listeners and sorry I I don't mean to pick on react this is true of all Frameworks right so we're going to talk about react because it's easy to get it up and running in this browser but the same thing will be true of angular swelled solid um whichever framework is your favorite these things are going to be all true in those Frameworks as well so let's uh let's build a new counter so let's um let's say we want to have a counter and uh let's see how good my react skills are so let's see we need to have a const we're going to have a state so count set count use uh date do I have to import I have to import something uh import use state from react okay there you go um return uh count is count button is plus one on click is set count plus one okay uh uh Hey what why is this possible oh because I have to say initial value of zero okay so now that we have a counter we can say counter you state New State fresh oh it's just way down okay okay okay okay delete this there we go there we go now there we go okay sanity has returned okay so now it uh that's counting as you would expect so um let's do another thing so let's say we say okay we want to Lazy load a particular thing so let's say we want to Lazy load the counter so the way you would do that in react right I believe you you download lazy and suspense and now in here you say whoops you say const lazy counter and then here you say it's a function that does import lazy counter Dot this and then I think do we have to do a weight here and then say default right okay so now that we have a file yeah did I mess something up so you have to export oh so I'm going to move it here so I am going to create a new file called counter.tsx and then we're going to move the counter here oh that didn't do it so I have TS6 we're going to take this um counter TSX export and then uh do you need a default keyword yes thank you the export D fold function counter and then we have to import use State from react okay so that should be that and then we go back to the oops DSX then we have our lazy counter uh cannot find my errors corresponding equation does it have to be that Js I think that's without JS here right it has to be relative to oh yeah TSX thank you thank you thank you is the JS required here no do you know no it's not okay so now we do suspense and then in here so it spans in here we can put lazy counter see if we wait ripples out of sync what what your closing tag is missing a character long time yes is that gonna work Moment of Truth no no why not it's not liking your import oh I'll wait no I'll wait so since the counter component is the default you you don't need to mark that uh the factory that you're passing into lazy that can just be a function that returns import dot whack counter like this I do have to have a weight in here or no okay so I can skip the async part there we go ah look at that it's working now there you go and so uh I want to point out a couple of things first of all that was a lot of work right and um there's many things we have to do we have to come up with the name we have to put an import um we had to have the suspense boundary there's many many things we had to do in order to kind of create this lazy loading thing and this is again true not just in react but in any existing framework but um the whole point of lazy loading this thing was to say like hey we don't actually need this thing or we may or may not need this right but guess what it doesn't make a any difference because when hydration is running the problem is react has no idea or the existing Frameworks basically have no idea where the listeners are and the only way to figure out where the listeners are is to start at the root and just visit every single thing so the fact that we entered or created a lazy loaded counter over here we helped nothing to kind of make a point here the realization is that the only time the lazy loading actually helps is in the case when the suspense would be behind an if statement and the if statement would be essentially false right and then it becomes true later on and if you think about it routing is just a very complicated if statement right so the point to make here is that lazy loading isn't actually helping you in the case of um of when the component is inside of the uh the rendered the render tree so that's kind of one problem but let's keep going so let's say now we say okay but you know what the thing that we don't actually need is the um is the the on click button can we make the on click button lazy loadable right so we can say no problem we can take this uh piece of code here and move it to another file increment.tsx and let me do again export default um I think just thought right okay so now we have problems now we're like we don't know what set count is yeah that's true so that's because originally it was a closure and now it's a function so we need to do something so we need to basically say we can pass in the set count and we can pass in the count those particular two things right and now it's not liking it because okay yeah because it's any so let's just cheat over here and ignore this for a second this is a number um but this basically gives us the The Lazy loaded stuff and so now we can go to counter and say great so what are we going to do here well the thing to do here is to say import um increment and here we do have to do a weight and can I just call it directly or do I have to say that default async dot default and then we pass and set count comma count and let's see if it works yes it's still working okay again I want to point out just how much work it was to make something lazy loaded but notice what we didn't actually solve we we made the code over here lazy loaded but now that it's laser loaded you have all these problems like well yeah but like what if you don't click on it until later or the first click is going to be slow because you're not prefetching it so now I have to go and say like great this particular thing is lazy loaded but now I have to go and somehow tell my boot up sequence to start pre-fetching these pieces of code so that it's going to be fast for the user and again the situation is that it's a lot of work I have to figure out a name of the file I have to figure out uh what to export it as now my application code is now spread across multiple things but it's even worse because what if this button is something that's clicked often like how do you make sure that this particular button is eagerly available or is put in the correct bundle because now the bundling system has no choice but to create a separate bundle right you have forced the bundler to have a separate bundle like there's no way for the bundler to be like yeah I got you you don't actually need this right and so you know when we talk about how quick has all this lazy loading and all these capabilities it is easy for people to say like actually I can do the same thing in my favorite framework and in a way they're not wrong you can but you can see how very quickly you're gonna just run into all kinds of problems and the the main problem that you that we did not solve here is the fact that the framework needs to know that there's a click listener and in order to do that we again have to go and execute everything and once we come across this on click listener guess what there is a state count and set count that needs to be passed into the the closure and so we now have left behind basically just yet another different kind of closure we didn't get rid of this closure we just moved the problem somewhere else and so it turns out that if you want to get rid of this particular closure it is not trivial at all this is the the hard bit that you cannot solve and and we're in a strange world where you know when you end up with a large application people will come to you and say like well that's easy just do lazy loading but then you actually try it and you realize it is not that easy at all and even like how do I know which of these listeners matter which I have to pull out which do not matter how do I prefetch the code how do I uh break it up and I still haven't solved the problem that there is hydration there's this eager execution of all this code in order to figure out what the listeners are excuse me um would it be fair to say that uh you know Frameworks like react angular have a de facto assumption that they have immediate or they have access to the full state of the application at any given time and since they're architected that way you want to do anything different you're going to have to explain every case where you want to break that pattern because it's not so much the fragmentation that's the problem it's the coordination this is the microservice issue sure individual microservices are faster but now you rely on the internet to coordinate them that's right that is an excellent way of looking at it it's um it's my observation as well right the bottom line is that all of our existing Frameworks have been written with this idea that when they run all of the code is already available for them right you know this is an assumption that's perfectly valid on a desktop application system and I think many of our Frameworks were inspired by similar Frameworks on a desktop I know when I was building angularjs I was heavily inspired by Flex and and flex just was probably inspired by some desktop version of it as well and so it just made an assumption that all the code is just available to you I don't even think there was a possibility to do lazy loading of code and action script I don't even know if there's possible or not but that just wasn't even a thing right and so all of the existing Frameworks basically just make this assumption that when they run all the code is available and that's the fundamental assumption that we kind of kind of want to break right we basically want to say like no that is not the case and once these Frameworks realize that you know that all the code is not available they try to introduce lazy loading into the system but the thing that's difficult about lazy loading is there's two problems one it is in it ensure it produces the problem of of asynchronicity so this on click is a synchronous thing and one of the things you're supposed to return out of the on click is prevent default like should the default be executed or not and that has to be returned synchronously but now when I put async in here if I wanted to go to to here and return um you know return false it's essentially going to be ignored because um the place where when it's over here is not available so you know even if you try to insert lazy loaded stuff the problem is that the whole framework is designed with synchronous apis and there is no easy way to get asynchronicity into the system and yes there are workarounds such as um the the suspense where's the suspense right here there is suspense right but if you think about how suspense works is the framework fully executes everything synchronously and if you decide that it's missing that particular thing it basically aborts waits for the data to show up and again starts from the root and tries to do the exact same thing continuing right so it's not fully asynchronous it's like it's an illusion that there's this asynchronicity in the system and again this is not specific to react all of the Frameworks work this way right and so the the fundamental difference is that we need a framework that understands the fact that data or rather the data in the sense of the code right may or may not be available for you synchronously then you may have to put a synchronous boundary anywhere you want and so um in quick one of the main things is that asynchronicity is just built in like I can data bind to a promise and it just works because well it just how everything about quick is asynchronous so let's do something similar in quick let's let's build the same exact app and quick and let me show you the kind of the differences that occur okay so let's let's take over this Hello World app right so I'm just going to take over the Hello World app and we're going to start implementing Parts in it Okay so hello index okay so here's our Hello World app and I am going to delete the content over here and let's say we want to put a counter in this location right just like we did in the other system export default um sorry not default counter count is um so const ant count is use store or use signal so that's kind of a first difference and let's talk about that in a second why that is and then we have a button on click count Value Plus plus yep that that sounds all good let's just say plus one to make it the same the important statement looks wrong import statement and why is this complaining oh then because I'm missing the parentheses it's trying to import a counterfeit location that's okay so now we have a counter and look at that we have a counter over here uh that we did so we basically wrote the same exact thing without thinking about lazy loading or anything like that so what happened differently so first of all we have these dollar signs right and what the dollar signs tell the system is that this is a potential lazy load and Boundary a potential right like we don't know whether this is a good idea or not right so the point of the framework isn't really to Lazy load everything into pieces but rather to introduce places where the lazy loading can happen and one of the things we talked about is is Promises by the way so let's see if this is going to work so if I do promise value and let's just say one two three why you're not liking it uh resolve or we okay so notice it prints promise over here right so the the weird thing about quick is that everything could be asynchronous and it has to be right because if it isn't then you can't introduce a laser load a boundary and so This Promise here it's not that the quick was trying to render it and came across a promise and then you needed to give up and you know retry the rendering from the root no it's just like oh it's a promise let me just stop and I can stop because everything needs to be asynchronous it's just a fundamental property of this framework and then at any when the promise resolves the framework can continue right so if I um if I instead of Promise let's do a delay so let's see function delay let's see if we can get this implemented um what is it set no uh earn new promise right is that right set timer resolve yeah I think that's right oh so we put the delay number delay and so here we have delay one two three and let's say one thousand seconds and so actually yes let's do that and what is another difference ah great so this is the laser loading trick again that that okay so let's actually go in detail over here before I just skip over this so the problem is that it says there the identifier declared at the root the delay it needs to be exported in order to be used inside of qrl right so this thing here may or may not be imported but because it may be imported right from a separate file the code might be moved somewhere else because of that it won't no longer be able to access delay so we have to make sure that this is exported and then this should be happy uh you because it's a promise of number all right perfect so notice we wait so here let's print uh hello do you see what just happened like isn't that crazy let me let me do this uh let me do this hello world okay value let's do T t here okay so hello uh oh because both both of these promises kicked off at the same time so let's do this one as two thousand world count and then the rest of it shows up right and it's streaming right so as these things are resolved it's streaming and because it's streaming you're not allowed to go back right you can't just be like oh I tried but it didn't work so let me retry it like none of this is is possible and so this is the kind of the key property of the system yes would you mind opening the network uh tab yes I'd love to see what's going on under the hood there all and yeah what would you like to see what just happened what did I click on uh collapse it hit Escape yes okay so yeah no it just literally created HTML uh where is the HTML here oh can I not search this is not a thing okay hold on so this is the error boundaries they don't count whereas oh right because it needs to be formatted hold on let me format it and this is the error boundary this is the head this is the styling uh this is main it'll go right nothing in the output tells you that there were promises in there it literally was just streaming right it came across a promise and said well I have to wait for the promise to resolve and so it pauses promise resolves I said okay there's an X promise I'm going to wait over here and then continues streaming uh to the rest of it yes in the headers is there is it like chunked or something like that that you can see that it's streaming like a streaming response um transferring coding chunked I think is how you can tell I mean it's a network right everything's always streaming in a network is there a chunked response header um I mean if you think about it it's just how networks work right like I want to send you a large file I don't send it to you in pieces or synchronously send them bit by bit over to you yes I'm sorry I'm confused about that response is that did we miss an earlier transfer no this is the transfer right like it's just this so what are you confused about um so if you could just do a clear cache and re refresh just want to see the whole thing again what I'm not understanding there so what we initially see versus what it resolves to right so the the the the the server I do a response let me look at it again the server starts sending all this HTML and it sends it all the way until until it hits the uh the hello right so it stops right here it sends it all the way up to here and at that point it says you know just flush the data because I don't have anything more and pause you know and just Waits and finally the promise resolves and the promise resolves the world world right so then it sends over the world's string right this is invalid HTML it's unterminated right but the browser is like yeah that's what I see is up to this point and that's what I've rendered and I'm just going to assume that it's terminated in a normal way right and then the question mark and count and everything else shows up so so things are showing up in sequential order it's just that there happens to be a one second delay between the colon character and a w character and another one second then they lie between the D character and exclamation point gotcha gotcha so then I guess if you were to resequence this where you have something loading later but earlier in the document right so if I put 1000 here and two thousand here well the first one is going to block and the rest of it shows up right and um that's how it works today one of the things we want to make sure it's possible is out of order streaming this is not something we have implemented just yet but it's relatively straightforward for us to implement and and basically what I we would like to do is when we get to this location right here let's let's uh find this actually let's go to network where is that here's the color so in our case the exclamation point result first right so what we could do is we just left leave behind a basically a marker a um and div or something right saying like something goes here we don't just yet have it go and render everything else so stream everything behind it and then when the world resolves we know the dip and it has some kind of ID and we can put in a tiny amount of script tag that basically says query selector on this ID dot inner HTML equals this thing and then the whole thing works now it gets a little more complicated because well what happens if the user starts interacting with the application before uh this the promise resolves so actually when you do this trick you have to send two things over you have to send over the HTML and you have to send over the actual result value and so then when if the if you're in a situation that the user hasn't interacted yet so the application hasn't been resumed then inner HTML is the same thing to do but if the application has been resumed then inner HTML is not a safe thing to do instead uh just tell me what the value is and let the JavaScript on the client take over and do the right stuff so both of these modes are um pretty straightforward and they are very consistent with how the quick just works out of the box and so this is why we think that enabling out of order streaming would be a super cool property we think it's pretty straightforward to do and it will enable all kinds of interesting use cases let's break up the the thing a little further so one of the things we saw in the react application is that the system had to start at the root walk all the components and visit them and as it was visiting them it could figure out where the listeners are right so if you look at the HTML that we have here there's a couple of things first of all we have this comments QV means quick virtual node you know historical reasons why it is it's not really the important but basically these text nodes tell the framework where the component boundaries are so in order for any framework to work it needs to know what where the components are if you don't know that information Frameworks can't do anything useful right and so quick is no different quick also needs to know this um but instead of figuring this information out by executing all the components and kind of building up the graph that way the graph is serialized into the HTML so just by looking at the HTML I know that there are three components in in this particular location I know there's a component here around body and so on and so I can if I find my component this is my div right here right so this my component started here and ended over here so just to kind of prove a point let's get rid of these um let's say this has two roots and let's say we can span hello world okay let's say we have these two Roots right when we get over here you see that this and this these two divs are inside of this QV right this is the beginning component this is the ending corner right so this QV represents our component now um let me for a second just remove this button so what's the easiest way okay let me just remove this button so this is pretty straightforward right right now the application is completely not interactive there's nothing I can do to make the application Interactive and because of that if you look at the amount of code that was serialized this is the civilization of the system right here it says you know there's nothing that needs to be serialized like it's empty and at the very very top it has this thing called the container and we're going to talk about containers kind of um more in depth later but what it's saying is that this container is paused it was also rendered by this particular version using the SSR and this is the URL where all of the code can be downloaded from right so we tell it where the code lives we you can kind of see what version was used for rendering it and basically just saying that this particular container is paused meaning the resumability has not yet happened what that means in practice is that this Crypt tag which contains the the Json State hasn't been parsed right and so in this particular case the script tag is you know this Json over here is essentially empty there's nothing of interest in here um there's V let me ignore wheat and this is for pre-fetching so we can ignore this um this is for error handling this is all Dev mode error handling so that it also doesn't count um right so this is beat this is error handling for wheat this is error handling for beat uh this is beat itself and so the and then this is pre-fetching um of the code so in this particular case uh the framework looked at it and said there are no listeners right there are we didn't leave any listeners in the Dom and because we didn't leave any listeners in a Dom there is nothing that the user can do to interact with the system right and because there's nothing the user has to do to interact with the system there is no need to even send the quick loader across right quick loader is the thing that sets up a global listener so let's set up a listener so now that we have a listener we have this button things are have changed over here mainly that new script act showed up this script tag represents the quick loader what the quick loader does is it sets up a global listener on the document and in this case it sets up a click listener and it knows that because the system said like oh there's a click listener in in there when I was doing rendering I saw that the user the developer has placed a click listener somewhere and therefore quick loader has to set up a global click listener right so this piece of code right here tells the quick loader to set up a global click listener and now any clicks on the on the page will bubble up and will be intercepted by quick loader and then when the quick loader gets a click event it basically says is there an attribute you know looks at the path right the event has a path and it says is there an attribute in here that tells me what to do and so it's looking for on Call and click because click is the event that happened and so this button has this attribute which basically says where exactly should the piece of code be downloaded from right and so this is the the file name and this is the symbol that we need to download now if you remember in our previous case where we were looking at what happened to it uh uh what happened did I minimize it okay in our Rebel that it seems like it's no longer here okay this Ripple one of the problems we had is that we couldn't just lazy load this code that code had closure right he wanted to know about set count and it wanted to know about the value of zero so you can't just lazy load this thing um or to put it differently the entry point to the system right in order to make the system run I have to enter in the app so that the app can run all this code which eventually gets to the counter so that the framework can create set count and that said count can be passed in here but that means that the entry the initial entry point with the system in uh starts executing is always here this is always the initial entry points or more specifically the entry point is is always this right this is the the place where the application always has to start all existing systems work this way like there is equivalent of a main method right where the execution has to start executing and everything goes from there so the thing that's unique or different about quick is that the the initial piece of code that we execute is not the main but rather The Click Handler right and so we have a problem now if you look at the click Handler you realize that the click Handler needs to get a hold of the count so do we have to execute the component use signal in order to for us to get accounts so that you can get over here right that's kind of the the tricky part that you have to solve and so the way this is solved is that if you look at the Json this Json originally was empty but now this Json has additional information and in the information that it has is basically that there is an object or there's a signal that contains zero over here right and this object is really just one of these special objects as you can see over here this is just the escape sequence for a signal and this is the value of the signal and this particular object happens to be the first object inside of this array and so if you go to the this uh thing there's a bracket zero over here what this means is that when this function executes it needs to close over the signal so the signal has to be brought back to life before this function can execute but we did this manually in here right we basically said when we had a counter we manually um passed it here but in order to be able to pass it we had to create it which means we had to execute the component before we even set up the listener Etc which completely defeated the purpose of lazy loading right so the the hard part is to create a new entry point to the system right existing applications have one entry point per application and no matter how many lazy loading stuff you do you're not changing the fact that the entry point is the main method whereas here by creating a click listener we have created an entry point into the system and the execution can start at this place you know independently from everybody else so if I Implement another button that instead decrements right now we have two buttons which have now two entry points in the system right the the execution can start either at button a or you can start at button B those are two separate places where the execution can start from the system and so what's happening is every time you have really a dollar sign in your application code every time you see this this is a potential place where the system can start executing and this is the bit that existing Frameworks don't know how to do and because they don't know how to do it reasonability is not really possible with them yes is there any benefit of essentially each of those buttons has its own functionality it's in this case a very obviously simple but is there any benefit as you transition into more complex functionality to introducing yet another opponent dollar sign as a potential uh lazy yeah so you can absolutely do that right so we could say that this Behavior here so let's um um create a new function const add value right and then this one says um right and then we could say count dot Value Plus equals value right oops and so then in here instead of adding plus plus we can say add value 1 and here we say add value negative one right and so this would work right this is not what you had in mind it's red and I'll explain why it's red but yeah um or or even external to this component I mean I guess that I guess I'm understanding that component dollar sign is a potential boundary correct and I guess I'm wondering at what point as you're introducing uh this nested functionality at what point does it make sense to introduce another potential boundary I think that is dependent on you know what you're building like it's a it's a decision that the developer has to make right like the framework's job is to make sure that whatever you come up with the right stuff happens on our side right you as a developer need to decide like is it worth refactoring to a common place or not right now what I wanted to point out over here is that you you would uh be tempted to do something like this but the problem is we would not know how to serialize this bit over here right and so again this is giving you this error saying like hey this thing you gave me this add value is not serializable I don't know what to do with it right and so uh if you want to pass functions around you have to add you have to wrap it in a dollar sign to basically tell the serializer like hey do your magic here so that this becomes serializable oops right so just by wrapping it in a dollar sign you basically told the serializer okay make sure this is a function and now this closure doesn't close over the use signal it closes over another closure so let's look at what actually happens first of all it still works um but notice that now it says I'm pointing to object zero right uh and if you go to the Json you will see that let's see context objects right and so um now you have this additional thing over here that basically says okay you will need this other thing this counter component add value whatever right this bit here you're gonna have to download yet another function lazily in order to make this thing work so we that Cole basically introduced this information and this information contains a bracket zero that basically says like hey that function internally is capturing this other variable and so this kind of gets nested yes so is it fair to understand this that you've tagged the placeholder value which would be zero in this case with a ref with the reference to the Machinery you need to calculate that's exactly what's happening so if I click this button and I look at the network tab what we get is sorry I wanted to see JavaScript we get our closure right and notice that we have to restore the closures the the closed over variable the lexically captured variables right and so we do this by calling use lexical scope and what the use lexical scope does is it looks at this this additional bracket zero and uses that information to go into the all the data that's serialized and says okay what do I have to recover what do I have to rebuild right and in this particular case it says you have to rebuild this this this uh other function right um so let me simplify this because this is unnecessarily complicated so I'm just going to show this off but let me just put it back it was to kind of make it simpler okay so when I click I um I need to recover this count this count in this particular case is a signal right so this use lexical scope basically knows how to go into our quick Json right and inside of the quick Json it knows to find this thing this ID over here 0 121 basically says you need to create a signal with a value of zero for me okay and then this particular signal gets passed into both of these entry points right so in that way it simulates the situation where these two closures close over the same variable so the the hard bit that quick had to figure out and what makes all of this other stuff possible is that quick knows how to serialize a closure right closure is a function Plus data we know how to take that and serialize it and that's what makes everything possible because if you think about it like what happened is this code executed at a server and when this code was executing we created a closure here and this closure was serialized and attached to this button in such a way that on the client you could just continue and the thing that makes this resumable is the fact that the client no longer have to execute all of the components in order to figure out where the listeners are it can just look at the Dom and be like yep I know exactly what the listeners are yes I just need to kind of follow-up summary um so it seems to me like the way you've defined the way you the program the optimizer defines closure blocks uh limits quite a bit the amount of polymorphism that can happen in that space so here we've got zero we need to trace back from zero to this ad uh our ad functions and that's our option we can't get lost the we can't go to another function we can't go to another uh we can't manipulate another variable because we have this why would you say that um polymorphism here so let's say we have um odd positive uh is that correct well I know let's see if there's an ad okay here and that's a count oh value number count okay I'm tired of Value Plus value okay come on and then we can do subtract uh minus value y why why are you Red what are you not liking here um do you need or you shouldn't need to pass I'm not expecting what oh oh right right because it's uh count value equal no plus equals value and then this is minus equals value but you're still not happy what are you not happy about oh because okay this is okay sorry extra parentheses okay that's just complaining that nobody's using it okay so then const Adder equals random oops Rand no math dot random there we go so now the adder is one of the two cases okay I'm gonna argue that's polymorphic I totally agree like you have no idea what's gonna happen right so this math random I would say you do have an idea of what's going to happen what's going to add or subtract but you don't know which way right based on your inputs you do right so so you know now plus is negative as negative it's positive right like you just don't know what's happening um and and the reason for that is that this Json basically this this function here will be one or the other so right now it's the 690x4 right and if I refresh it's the other one now voxk and I refresh again and it should be back to the original one yeah so this gets at the way I didn't ask the question because it's more confusing but basically you've now confused your co-product space you can't uh with the way you've introduced polymorphism you've uh muddied the context of the operation that by which you go backward by introducing the variables so we can easily arrive at zero via increment and decrement but when you put in the random function yeah we can't go backward along those because we've got the the arrows start to get confused yeah but like it does work like it does yeah it does work the question being that within the scope we confine it to this small decision problem with uh with how you with the with reference we can still confuse the decision problem but the scoping creates a very tight uh equation and and in that case like so we can confuse the co-products here but if we go back to your other one we have a very clean space to do induction over yep and that has so the question just in sorry that got lost here but was the way that you're defining the scope of that uh or I can't remember the word you used it started with an S I'm sorry uh um for uh hash values that you're using yes um the way you define those gives us a way of saying only these number of things can happen between point a and point B that's right um so yeah so maybe this is related but it was only executing one of those functions yeah every single time you press the button whereas I thought mentally on the client side it would actually execute the random logic and then pick which one right so so you're thinking about it from the point of view of react yeah yeah and in the case of a react you keep re-executing the function over and over again um here we're trying to be smart and not do it so in this particular case so let me let me do a simpler version of this thing right so let's say value is math math at random um and so if it's greater than 0.5 then it's becomes one and becomes negative one and so here we're just adding a value and adding a value here right so if this was react then this code would re-execute over and over again so let's see what actually happens it's always the same thing right in this case it was negative Let me refresh now it's always positive right it never changes so let's see what I actually downloaded on a network so the thing that we downloaded was this Handler function right we introduced this extra line over here but we just really downloaded the extra Handler function um if we go over to the thing here notice that it no longer has zero now it has zero and one right because What's Happening Here is now this closure closes over to um variables it closes over count and it also closes over value um and that's why that's why it says 2 over there so now if I refresh and I go to um my my Json you'll see that it has both 0 and negative one those are the two values that it's closing over right and this is how it recovers them and if I refresh this it might change to we have still negative one if I refresh this it is still negative one uh come on I have to apply for a lottery here there we go um so now it becomes one right and and the the whole thing works now the other piece that is important about um resumable systems is that they have to be reactive this is why we use use signal rather than use state the problem with state is um when we change the state in here using the set count right that component and everything below it is subject for rendering because you just don't know what's happening right like who knows what's happening underneath it right but that would mean that we would have to re-render Too Much basically typically what happens in real application is that the state slowly migrates upwards right to the root component and that means that your root component all of a sudden becomes the thing that you keep re-rendering over and over again which means the moment the state changes you basically just download the whole application and you've basically undone the all the hard work that we have done so instead what we want to make sure is that we are um truly reactive meaning that when you change something we know exactly what we need to change right we have to have true reactivity and you know the old uh joke is that react is not reactive right like it looks like it but it really what it does is it reruns everything all the time in order to figure out what has changed so when this was running on a server we came across this count.value we read the value property from the and actually value is a getter and so when the getter Got Run uh got executed the framework learned that this template needs a this value which means it learned the fact that if this value changes then this template has to re-render so that creates a subscription but we've gone a step further and we basically said hey if this subscription changes the only thing you have to do is you need to change the data property on object number eight and if you go and look for that it should be here you notice that this object has has an ID eight and it's currently zero and so if I go and increment that value of of that particular State then the only thing I have to do is change the data and so because of that if I click here the crazy thing is I've downloaded the the Handler I've downloaded the the framework what I didn't download is the component itself like it's just not needed yes so as you're clicking uh the buttons the on with the on click Handler you said the only thing you need to do is alter the the data in that location so is it patching that uh on the client side went by patching is it is it essentially updating the data in place or is it uh is it talking to the server or is it all no no it's all on the client right so it literally just gets a hold of that Dom text node and just says textnode.data equals whatever the values would it be like the inner text or inner HTML I think it's actually data isn't it isn't it like if I click here and if I how do I get the console here Sub Zero right dot data yeah so if I say data equals like it's literally the data property of that thing so what I'd like to do now is take this idea of signals a step further and bring other components into the view so we can see what happens with with other components so instead of having a count here let's make a new component called display and let's make this a super simple component and all we're going to do is we're going to return oops value colon and now people would like to put the value so you know standard way of passing things in we say props and props.value now here we have to say what it is so we have to say that a value is um let's do the wrong thing first just to kind of explain the wrong thing and then we're going to do the right thing so let's say you say like the value is a signal of a of a number right that's important and then well hold on let's so it's not confusing let's say count and it's count that value okay so let's do the wrong thing first this is the wrong thing this is not what we expect you to do so then instead of uh having this you will say display and so now you have to pass an account and you pass in the the count like this right now why is this the wrong thing to do because you declared it as a signal like it's going to work it's going to do the right thing you know it's going to work the way you would expect but it's the wrong thing because um you're saying that you want a signal of a number so if I for example say I have another display let's let's have another display here and I want to just say one two three it's going to complain saying like one two three is not a signal you ask for a signal for me so the proper way to do it is to just say no I just want a number like this right and then we don't have to do the value in here we just do a number and so we um do count that value right because the count is a signal so the value part is the actual thing and so this also works the way you way you would expect and you get the value that's directly available over there everything works as you expected but here is the the kind of the strange thing so first of all let's go back to plus one and notice that we download the the code that we need and sorry this is Veet being Veet one second let me refresh okay plus one we download only two things right we download the the component itself the the the the Handler right the thing that downloads and then the framework itself and that's because the framework was able to uh in the Json in the subscription say oh if you change the value of this particular signal go update that thing over there but if you're coming from the react World you should be like wait wait what just happened like how does this like here we have unwrapped the signal right and so in here we we did the right thing we kind of made this work so let's say for a second that I say plus one over here if I refresh the code and I do plus one notice from the network not only did we download The Listener and the framework we now had to download the display itself right this is the thing that kind of unwraps it but what I find interesting is that even though the value has updated this particular thing didn't have to re-render so even though I say count that value even though it looks like I am passing A Primitive value here it's the system underneath knows that this primitive value is actually a signal and so this doesn't get unwrapped right so that when a um when a change happens only the display has to re-render not this component right here so this component doesn't re-render even though it looks like I'm changing a property over here I'm not sure if I'm explaining this right so you probably have gazillion questions one thing we were talking about about during the break was do you think it should warn you when it's about to unwrap the component and download all of its code to re-render um because it seems like a really easy case to get into right so so as of right now you know doing the plus one so if I do plus one here right it will have no choice but to download the the components so these let's see uh where is it this is the hello world right so this hello world there's div so here this is the component right here right it had no choice but to kind of rerun it but this is going to be fixed soon we if if the uh the operation you do here is pure like adding plus one we will be able to deal with that it's only when the operation would be unpure where we just like sorry we won't have to do it so we think we can get to the case where like good 95 of the cases we can handle um in general like is it a good idea to tell the developer that actually you're doing the optimization here um probably we could probably do that it's not a um I would have to think about it if it's a straightforward thing it's not a deal breaker but it is um good to know type of thing it is though in the sense that like even if we do the optimization we're still like miles ahead of existing Solutions right because if you think about it the existing Solutions always run in the optimized way right so in that thing Alone um we're doing the right thing so the kind of the thing I want to point out is that we're very intelligent about the whole system right so in here we cause the Diop here but because here we know it's just a value we never downloaded the um the the other component right like so so if I deact in both places we will download um both of the components so this is one component gets downloaded here and then display component downloads here but if I don't de-opt in here only the component gets downloaded only the the top level component gets downward right so the system is pretty intelligent about like passing this stuff across and in a case like this where um we can just pass it all across we don't even download the components um we can just double downloading again I don't know why this happens indeed I apologize let's restart it we really only have to download The Listener itself nothing else so um my only Point here is that the system is pretty intelligent about the reactivity graph and it can go and update the right thing most of the time yeah so I think one of the things that that as as he was saying we were discussing during the break is when when things behave differently when I change how I've coded it in an unexpected way when now all of a sudden it is downloading and running on the client and I'm getting different behavior um that's that's I think gonna surprise a lot of uh you know newcomers especially you know you and you're doing a great job of calling out like comparing it to the react mental model because you know most people in the community have been steeped in that for quite a long time so I think it's a good kind of analog to continue to draw um what was interesting is the reason the display value was changing was not from a react perspective that the props were changing rather there was a direct reference from when this signal changes I need to update this part of the Dom and I know that because that's how the code executed on the server when we serialized everything so I think driving that those kinds of points home might help to get people to shift their Paradigm and and kind of appreciate some of what's going on here um we would like to get to the point where we are like solid in a sense that we execute this exactly once and there's no surprises um we don't know whether it is worth the trouble as of right now so that's kind of the situation we just happen to be in um but yeah an excellent point I totally agree with you um your mental model just has to be adjusted for the fact that like the component function may or may not execute you just don't know and so you better make sure that it's item potent if it does yeah here's something that could resonate are you saying that I don't need to worry as much about memoization correct you don't that's that's amazing you do not have to so so the standard right so so the the standard um uh memorization kind of uh thing is is the clock demo right um clock let me just add a clock here const um clock equals what is it const time is signal only then look at that um uh use client effect and so in here we do yeah is that all right he yes but here we want to just do in string so here we want to do that to locale time strength no why are you not happy to do you need to wrap new date in in oh sorry oh there we go okay balance and then here we just do return okay so this would not work in the reactor right like the the issue here is that um the the react would assume that the value is always the same thing and so this clear interval I think just accumulates over time and you just make a mess out of the system right so in this in that sense we're more like a solid like you just don't have to worry about the memorization in that sense and that's nice right it's a nice property I mean that's that's more than nice so I feel like I spent the majority of my time reviewing code and fixing places where people were not doing memorization missing exhaustive depths we had custom lint rules that would catch exhaustive depths that were nested objects like it's a huge pain point so yeah that's awesome yes so so that category of things just should not be an issue in in signal-based systems right because the reason why this is the issue right is because react always reruns the code over and over and over again right and that means that you like set intervals or clear intervals uh accumulate Etc so uh more of a clarification question on line 18 where you had the display uh yeah in this code base but on our page line 18. uh oh excuse me line 24 um where you have the display count dot value so um is what is the lesson here that the there will be some assumption if we give this a stream it will assume it's a stream it will wrap it in a stream or we'll think it's yeah so let's look at what happens under the hood because um I the follow-up question is when you put in plus one right you're no longer expanding by a constant you're expanding by an operation on a constant yeah yeah and is that the kind of confusion point that is exactly the thing so let's uh let's refresh this um let's see network and we downloaded the not the clock the counter right here it is so here is our um display and notice the read was wrapped in a getter so that read is actually delayed it's not an eagerly read it's a delayed read and instead we create an additional property which says see if the count is a uh a signal and try to read the value off of it and this internal stuff is what basically says like is it a signal if so I know how to do my magic without actually causing a read Because if I cause a read I'm essentially creating a subscription and I want to avoid the the idea that there's a subscription over here right I want to prevent that because if I do make a subscription that means it has to re-render all the time right and so I'm trying to say like I know it looks like I'm passing the value over here but I'm not eagerly reading it and therefore it's not a subscription so in the case of quick for like line 25 uh subscription and functional dependence would be mostly overlapped the the two concepts where if you have a functional dependence like the plus sign yeah line 25 you also have it so that would be equate to a subscription but the thing we're trying to do is we we would like to create a transformation function as part of this thing right if we if I was able to just pass in a transformation function in this location and says plus one is happening here then the whole problem would go away right and the requirement is that that transformation function has to be pure so if I can at compile time detect that it's a pure transformation function then I can just inline it in this location and then the whole problem just goes away and in 99 of cases the right stuff will happen yeah it's the guarantee of Purity that needs to be that needs to be in place yes okay thank you yeah the the other realization that's Dawning on me is is all of the complexity that we deal with in in react with you know uh when you're when you're using react Hooks and you have to set uh call out specific dependencies uh and you have this process of your nested contacts trigger re-renders and things like that all of that complexity goes bye-bye so actually let's go and explore that a little bit so first of all before we go explore that uh let me show you some particular thing that I've done here I said props dot count what I specifically didn't do is I didn't do this oops I didn't do this bit I could do this and um it it is uh something we're still working on but what happens is because we read the property before we get to the jsx we don't have a chance to intercept it and so now you've created a subscription whether you liked it or not application still works exactly as you intended but so let me get rid of the clock because it's just confusing the situational here um it still works but if you look at what's being downloaded is that we are eagerly downloading this display right because we don't actually know what's happening to that thing um just because it is structuring because this because the structuring is causing a read right and and we are working on a um we haven't decided yet but this will either become a lint warning saying don't do that or we think we can transform it into during compilation we can transform it into something reasonable so as long as you don't do a read anywhere else we'll consider that okay I was gonna say that that latter option seems uh vastly preferable because you know in terms of readability as you're working with the code we use object destruction all over the place on so again you can do that the application works exactly as you would expect it you just end up downloading slightly more code right so but even in this situation where you're downloading slightly more code again you are Miles Ahead of hydration right because you've only downloaded a tiny portion of the whole thing now let's undo this bit and Google props count okay so let's um let me show you another important bit so let's say we actually print the count directly here and let's say we cause at the optimization by doing a plus one on here it's confused again okay okay so wait why do I have a clock in there all the clocks in there that's why that's what's happening okay so when I click uh this button um we obviously we don't have to download the entry points we have to download framework and now we download the top level component right so we download this component right here and this component has to re-render it does no more rendering right this component right here but notice what didn't download what didn't download is the display which is a child and this is an important point because in normal systems when you grab get a hold of a top level component you're getting hold of all of the children below it right and in this particular case click was able to say like you have this component in the middle of the tree and I can wake it up independently of its parents or of its children and at first you might say like well the parents is easy right not so much because the component may have props from the parents like things like children right and you don't want to force waking up with the parent just to get its props and at the same time you don't want to have Force waking up with the children just because you are rendering because maybe you just happen to be a component that's high up in the render tree and you don't want to cause all the stuff below you to get downloaded so the reason why all the components are wrapped inside of this dollar sign here is so that we can refer to the display component without actually deferring to its content so if you look at what actually gets downloaded um let's see children where is our display here's our display right we are referring to display here but if you look at the definition of what the display is if I think if I go here here if you get look at the definition of display it just says like yeah dynamically import this thing if you need it right and so it's not just about breaking up your um listeners it is also about making sure that if you get a hold of a component in the middle of the render tree you don't automatically Force the download of the children as well and you don't automatically Force the rendering of the children as well and again existing systems we can't do this because yeah there is a way to say don't descend into children in existing systems but at least once at the very beginning the framework had to descend to the children to kind of figure out what's in there and then subsequently it doesn't have to right and the fact that at least once it had to do you've already lost a particular game right like you've already eagerly executed the code and so you have a problem um and so those are kind of the all of the main pieces of of the system let me just pause here see if you have questions and then we can go other places uh well this sort of relates to have you guys been thinking about uh developer tools to help like help with understanding when you're de-optimizing them and uh also a little easier to navigate the Dom versus looking at all the comments and parsing the comments mentally um uh yes so there's a couple pieces in there so uh first we have eslint like you've seen like if I forget to export this particular bit like technically I don't need it like it complains and says like actually I might have to move this and if I move it I'm going to have a problem so make sure you you make this export it right so we already have that there's also a uh you know devtools in here we don't quite have that yet but it is something we are thinking about about you know again early time of the project right so not the whole world can be done here we have uh one open source contributor who did this super cool thing where you install a special plugin I think if you hit the control key and then all of these things become clickable and then you can click here and it takes you to the source code in vs code to a specific line where this that particular thing is defined that is super cool um that works as well uh so so we're getting there but you know it's a new project uh but for the most part because it uses jsx and because the Transformations we do is just moving code from point A to point B and then we add a little header we don't actually touch the code itself um The Source Maps work as you would expect the debugger works as you expect there aren't many surprises uh in there the only thing that's strange about debugging is that well you can't you know the way you put a breakpoint somewhere is you navigate the source and you click on it right the problem is no code has shown up yet so you need to do some operation or to get the code to show up and then everything works as expected so for example if you place a debugger right this is literally the code you have written if you look around like this is this is what I wrote nothing in here tells you that actually the code that was downloaded was just this pity right here right and the point I want to make about um the breakpoints is that if you look at your variables local variables none of them here will in any way hint that the transformation happen because we're not moving the variables we're not creating extra variables we're not doing any of that stuff we're just putting the little uh header in here I think the only thing you'll see is that this count is if it would be truly a um uh captured in the global scope there would be like a parent thing over here that you would have an extra place but other than that you know you have account you can change it you can see its value et cetera so the debugger experience is very very normal um you do have to understand though that so let's say we want to place a debugger um inside of here which we can also do oops right this debugger we will never hit right so no matter what I do what's going on yes yes okay I didn't hit the debugger statement right and the reason is because that's on a server that's not on the client right so so you have to understand that like okay let me just you know Dev dot debug so I'm going to run the server in a debug mode now now I can open it up right and here now I will hit it so here we go now I've hit the the bit that I expected um I'm not sure why the source maps are not here so smart should be here as well um just like in there in the browser right but the social smile should apply and you should see the same exact stuff um so so in that sense um it is more complicated because you have to understand that some code might execute in the server and some might execute in the client and sometimes it executes in both places right so if you close the de-op and function reruns on a client then like well now you're going to also have to be be ready for it in the client so in that sense it is a slightly different mental model but debugging works the way you would expect like nothing nothing there is is changing let me get rid of the debug mode here come on oops okay oops okay so um here we have the code and if I can click plus one write eight updates but by updating I have now created a count in my window remember I assigned it this particular thing I assigned at the moment so I got a hold of it and this is what I mean by the system being reactive if you go value and you say equals one two three it just goes and updates that like this is what we mean by system is truly reactive rather than you know sort of reactive like reactor angular yes so I'm sorry I missed the part where you implemented the The Binding to the window can you go back there yeah I just took the uh the count and I just assigned it to the window Okay so curious because in other uh environments that handle uh SSR or SSG you have to explicitly test to see if window exists in order to not throw an error correct and break the build so here you don't have to worry about that well this is a click listener so I know that click listener will only execute in the browser it's impossible to execute it on a server so that's that's how you were safe doing it within there but but yes you would have to do that you would have to do that if it was outside of a click listener yes so if I and that's also why I didn't put it here because I knew that at this point this is going to execute on a server and so I know that this isn't going to help me right so and it will break and so there you know you can import um you can say if is browser um what is it you can do type of uh window yeah but like we actually have a thing for you um but I don't know why it's not coming up I think it's uh import is browser I'm not sure why it's not completing no that's not emotion I don't even know how did you get emotion here um is it build I think that's what it is so now this is safe right it says you only execute this if you're in a browser um and so you know it will work exactly as you expect and I still have a access to it and I can just say interesting another uh reactism can you do the if statements interspersed with use no okay that that is the same same okay same rule so you can't not do that and use signals it also means you cannot have a promise up here so so you can have promises inside of your jsx that's fine but you can't have a um an await statement before the return the jsx must be returned synchronously inside of the jsx it's fine to have promises but not that it has to be returned seriously right again it um it just happens the way how nothing in the framework itself requires it but that's how the use methods work and so um we we kind of just follow the same convention because we don't want to like have yet another thing that's different so yeah um sorry I keep on trying to orient myself to the world of react because that's okay what I've been swimming in for a while now and I'm sure a lot of the audiences too my question is you know in in react one of the one of the cool things that I think helped people to adopt it and use it is the developer tools and now the profiler because you need to be able to analyze and understand what's going on under the hood but because if I'm not mistaken there is no Shadow Dom right so you no longer have that mismatch or that duplication and you don't have the the flame War uh in the flame graph of the the optimizer so is there even a need or would there be any kind of a benefit for a Chrome extension or something that would provide quick specific I'm just trying to imagine what that would even look like or or where the benefit would be because the the reason why those extensions exist is to solve a pain Point yes well you've eliminated a ton of pain I didn't yes a lot of so all of the active systems this is not specific to quick if you go to solid.js the same benefits will apply because it's truly reactive system right all reactive systems will have these benefits um having said that you know developers are creative uh and so I'm sure we can figure out a way to uh make something slow even if you know remove a bunch of pain points so I think there's always a need for understanding what's going on like that that problem never uh disappears but as you can see like many of the common pitfalls just aren't there right it just you just don't have to think about them they're not there um the way the reactivity works as you can see over here that you can just assign to it and the right stuff happens uh is is uh you know it's kind of a mind shift but because you have reactivity then this whole clock business goes away right the clock business problem the set integral problem is a problem that reactivity just kind of solves and says like you just don't have to worry about it's just not a thing right by the way I know I showed this yesterday but let me show you the clock again I just love this demo I say div and I'm going to say Style height right so clocks below the fold no um nothing was running when we scroll the clock in view JavaScript shows up that is just a you know a beautiful demonstration of like um how just out of the box the framework forces you down a particular path that is just like that's the path you want by default right you shouldn't have to think about the other way now it I can um fasten another variable in here and say actually I want uh see what is the value it's eagerness is eager I can say eagerness like is that right uh no it's visible oh I'm sorry not visible load there we go I can't say load and in this particular case when I come here you see the code just immediately loads right it just is eager because like you said you wanted to do it eagerly but I think it's a it's a nice kind of demonstration of like just out of the box the right thing happens we can now talk about like well what exactly is happening here come on why is Okay sometimes that happens where the dev tools just gets confused okay so let's tools crashing you have to close it and reopen it's just reloaded okay here is our div so notice what what what is happening here is the way quick Works everything has to be an event it's all about the events because the events is the thing that drives the system and one of the things quick does is it just tells you what events exist in a system right when we service at render we know what events we saw we saw a click and we saw queue visible and this is how we're telling the quick loader like watch out those two events might come now the Q visible one is a synthetic event it is not a real event and so the the quick loader understands that it has to create an intersection Observer for this particular thing and then it fires this particular event right so if I say uh in here for example click right when I scroll down the time no longer does anything because it's waiting for a different event right right but when I click on it uh the time shows up there is the delay because the set interval Waits a second before it actually updates actually the proper way to do this is say this is update in const update equals this and then we have to run it eagerly before we wait for a second right so now the right thing just happens it immediately shows up okay so that's use client effect and our convention is do you have the word client meaning that we're guaranteeing you this will only run on the browser so you don't have to worry about this ever executing on a server but um let's say um we can do other things for example let's say the clock actually let me uh let's let's kind of start from scratch there's so much stuff in here all right let's just delete all this so we have a signal we have a count I'm just simplifying the whole thing again okay let's go to the the simplest possible case here right let's say we now have a new one called double count that spell and so not only do you want to print count we want to print slash parable I when people are watching I cannot type okay so let's see where are we so we have a double count and obviously you know this won't do anything right we'll only update one of them oh by the way um an interesting bit right now is that if you look at the state of the system what got serialized quick Json let's make the double count just for fun one two three just so it's easier to find notice that one two three never got serialized if you look at the what all the data that got serialized one two three is not part of it right because the system looked around and said like well there's no way for you to change it like why do I bother serializing it right now if I for example calls a d opt as we said earlier with the plus one um I'm gonna refresh it again now the one two three is in there because now it understands that like hey you know I'm gonna have to re-render the whole I'm gonna have to rerun the jsx and because I'm gonna have to read on the jsx I'm gonna need that signal and so now it's there so it's kind of just interesting how automatically without any effort the system just does the right thing but what we want to do is we want to make sure the double count is twice of the regular one right so you would do this in use client effect in in react the trouble with the use client effect is that it always runs after render and I think there's a case to be made like well sometimes you want to run before render and sometimes after render because like if you're on a server you want to delay the rendering and compute the double count before you actually continue with everything right so we could do it as a use client effect but I think that misses the point this is not what we actually want what we want is we want to basically create a use watch and we use watch is is just like use client effect except it also runs in a server but specifically it runs before the rendering right and so we can say that double count value is equal to count that value times two okay now that's nice but this isn't going to work because well I mean it is going to work in a sense that um let's start with the initial value of 10 here notice that it correctly does the work right we can be even more fun and say a weight um sorry I think and we can um to delay one second so now I have to my delay function again which I lost value milliseconds love this thing how does it know that I have no idea well you T there we go okay so now we have to put a weight right so why is it oh because it's forgot to do export okay notice it still does the right thing the server understood that hey there is a delay did I put a thousand delay why don't I see a delay in rendering oh yeah I see it's spinning and then it renders right so there is a delay that happened on a server because that's what I asked for and then it computes so use watch it's kind of like use client effect but it runs before rendering not after and if there is a synchronicity it actually blocks and waits before everything continues yes um two things first of all could you scroll up because when there was an error being thrown up there oh why why are those errors throwing oh it just it just they're unusual planning that you have unused Imports um okay so then use watch uh essentially is along the lines of like a used get server props it doesn't have to be it just uh executes well this is incomplete uh actually implementation let's just finish implementing it first because notice it doesn't work that was my other concern is that you were when you initialized the double count it had if you scroll up a little bit it had one two three as its initial value yes but then this overwrote it right because this is guaranteed to run before rendering unlike use client effect which always runs after rendering right so we make a distinction of before or after like react world's just like run after rendering and then cause another re-rendering to happen it's like ah yes but like that doesn't work with streaming because one of the things that quick really wants to make sure it works is with streaming right and then when you have a use client effect and if you have something like this where you wanted to load data or compute something you won't be able to do it now this thing is doing the wrong thing because uh it doesn't update this number right and so what we need to do is we need to tell it about it so there's a special function called track that you can import and then in here you just say I want you to keep track of count and now oh because of this delay it's causing the delay in rendering um so let's let's remove this delay uh let's just say one second you can see that they're now in sync right so the the track is the way you tell so in in react you give it an array on the end but the problem with that array is that it assumes that the main function keeps running over and over and over again but in our world we don't have that guarantee that the main function runs over and over again and so we actually need to know what you passed into us we need to create a subscription and so that's why you're using the track method to create a subscription and that uh that track method if you think about what's happening is this used watch executed on a server so here let's put a console.log oops double count yeah perfect so notice on a server it executed right but then in the client and if I go to console it executes on a client as well so now you have a piece of code that executes both on a server and on a client but when it executed on the server the track created a subscription to this particular thing right so on a server there is now a subscription that we know about so if you go here and we look at the subscriptions we know not only do we have to update some Dom location with it but also we have to update a second signal with it as well and so the subscription information got built up on this on a server so that we know like oh if you change this value not only do we have to update the Dom but we also have to update the second subscription which then causes another down value to update yes so if you go back to the code again because I noticed you're using object destructuring on line 14 that I imagine would be a safe place to use it because it's operating on the the server it's the apis that we have given you this is not any props of the component right props of the components are the only problem place where the the structuring is problematic um okay so let's do one more thing here so we have our on click here and uh I want to do the again window as any count equals count so I'm going to write it out over here again and the the thing I want to point out is if I do count that value equals one two three let's say notice not only did the Dom update it but the constraints between count and double count also updated right so the two parts are now uh coupled and tight and this is what I mean that I'm saying that if you want to have reasonability true reactivity is a requirement right because if you don't have this then the answer becomes like well just recompute everything and then all kinds of crazy stuff happens um I'm gonna point out one more interesting thing is that currently we're talking about signals but there's other way of doing this we can for example talk about state and then we can say use uh not uh store sorry store not state and so in here we can say count is zero and then we can say d count double count is whatever one two three and now we can delete this and then now we track store dot count is what we care about oh and I think we have to pass in a closure in this case and then we have store so we don't need to do this we can just say store that double count store dot count uh stored count you know start double count right use store has to be imported until we're done okay same exact thing but instead of using a signal we now have a store so what's the difference in the signal in store um a signal the idea behind signal is that you have a a bucket a closure basically something that has a single property called value that represents what you want right whereas a store is an object just that has properties but whether you're using one style of doing things or the other style of doing things it works exactly the same there is no difference as a matter of fact under the hood a a store is just a collection of signals right so same exact Behavior we have over here and I can say store dot count equals let's just do count plus plus it will update right but notice if I do store double count I will update the double count but not the watch didn't run because I specifically said that the thing I'm trying to track is just a store count I'm interested in account changing and that should trigger me re-running not the other side around right and okay so so right now we are getting hold of the store by clicking a button but I can do another trick I can just say use client effect and I can say that oops too many curlies window dot window as any done okay so I can eagerly export the store right so even before obviously the the client effect code had to run right but now I have a store and I can go and update it right so it just becomes interactive from the get-go okay where are we with uh would this functionality provide what would pass through some sort of memorization in the system or would that be better thought of differently no it's meant it's total conversation right like um you don't have to worry about it re-running all the time and a typical use for like use watches for example let's say you have like let's say you want to know what the weather is like right so you have the user type in zip code and a change in the zip code triggers a watch to go talk to a um you know some service some HTTP fetch whatever right and then that returns and updates the the data and not just you have a track you can you know you can have a cleanup function in here I forget what else do we have here uh use watch is watch function which oh sorry it's just extra track or cleanup um but the it can be asynchronous right so you can delay stuff or if you don't want it to be a synchronous you just return eagerly and then do the asynchronicity in a separate path so you you have all the choices one of the things that I think is important is when you're building things in react everything is fully synchronous so there are no surprises of like the order in which things happen right it's always predictable and because everything in quick is synchronous we actually go through a lot of trouble to make sure that even though it's asynchronous it will always execute in the same order so we won't go through all kinds of trouble to make sure that things look synchronous to you and um this is done intentionally and you can always as a developer Escape that by just creating a promise and doing whatever you want over there right so but out of the box we want to make sure that it's predictable now that actually kind of points out to another interesting bit which is that when you render a component you want to make sure that you don't see intermediate values if the the operations you're doing are asynchronous you don't want to see incremental values so the rendering pipeline actually collects all of the updates to the Dom and it wins until all the promises are resolved and then applies everything at once so you don't get to see intermediate values in between um before we change topics any questions yes yeah this might you can defer this until we get born deeper into streaming but uh is the page interactive as it streams or do we have to wait until it's fully streamed let's go and talk about that let's go and talk about it um because you're you're showing a delay here so that's why yes so here is um an application was built with our friends on cloudflare and you can see how it's streaming the body right but I want you to notice that there are boxes in here there's the blue box the red box um there's the blue box on the bottom and you can actually click on it I think um and what's Happening Here is each of these boxes is a separate container so let me let me show this to you again so notice how the container is paused there's a container presenting the big app there's a container representing um the smaller application and currently it all says that it's paused as a matter of fact I believe there is there's four containers on this this application if I remember correctly query selector all um cue version right so we have the HTML the body the header and the footer right those are the separate applications what's actually happening on a back end is the separate applications are rendered at different URLs and then there is a kind of the multiplexer the kind of the root container that talks to the other applications and assembles everything together and because of that there's an interesting property which is that I can interact with the top before the content even shows up on the bottom and that's huge right because you can't do this in a normal world like you have to wait for hydration to fully download fully execute and only then can you interact with it and so this I think is a kind of a huge huge Improvement the other thing I want you to point out is as of right now okay they all are running the same version of quick but it doesn't have to be but notice that the URLs are different they're actually coming from a different URL actually let me show this to you on our home page so on our homepage we have this header over here let's just zoom it out a little bit we have this header over here that is rendered as part of um part of our documentation website but then the landing page is actually rendered as part of Builder i o so this Builder i o provides headless visual CMS and then you can drag and drop and move things and we want our marketing department to easily go and edit the content that's on pages right so what happens is the the top level thing is is a quick version over here actually it's resumed it doesn't have to be oh legal resumes that's interesting um the the there's a top level container here but if you go into like this place you realize that there's a separate container right here that's paused and notice the version here is not the same thing as version here not only is it not the same thing the Cubase is the location where the code should be fetched from is a completely different server like this app that's embedded inside of it is fetching code from completely different place than this location over here and of course there is a service worker that knows how to deal with all that stuff and prefetch all this stuff so you don't have to worry about it all right so let's let's get back to we're talking about containers right so in this example right we have multiple applications we have um the HTML the the body is is another app the header is a separate app and so on and so forth and as soon as the container gets closed with the quick Json right so each one of these containers has its own Json as long as soon as you have the state of the system that particular container becomes resumable and you can start interacting with it and that's why in this particular case as soon as the the menu shows up even though the rest of it is not showed up I can start interacting with the page because only that component is is resumed the other kind of cool thing to kind of think about is that the individual we call them containers are fully uh contained right so what I mean by that is let's say I take the container here and and I can't right click because the thing crashed again let's try this again it happens sometimes that the dev tools just crash okay so let's go to the header and if I go and if I make a copy and then let's just make multiple copies of it right we can just go and interact with whichever one we want right so the HTML alone fully defines the application so to put the application in your output is a matter of just concatenating the HTML because that HTML fully contains location of where the fragments are where the code gets downloaded it contains information about what to prefetch how to download it it contains information about what events you listen to basically everything about that app is fully contained in that HTML yes so uh essentially that's an encapsulated State yes and your I guess I'm confused because aren't there ID references uh quick virtualization ID references in embedded in that so when you duplicated it's all scoped down to the container all these references are local to The Container interesting so you could have two IDs pointing the same thing it's not a problem interesting call to the scope to The Container yeah interesting okay so now uh let's say we live in a world where we've got a requirement for framework agnostic uh serving up of components so like what if you had like that footer you wanted to be an angular app and another one like the body or something within being a react app or a felt Kit app what how would that look right is that possible so quick is friendly in the sense that um it doesn't just randomly change your Dom structure right the Dom structure is built by the HTML and for the most part unless you specifically tell that you want to delete something or update or delete or modify it in some way quick will not touch the Dom and so in that sense it's very friendly to coexist with others how exactly you bootstrap the other framework that's up to you right but you're you're root Dom node that client-side rendered react app could register to could be nested somewhere yes so quick will not like actively destroy or move Dom nodes or anything like that and that's that's kind of a side effect of resumability because we we can't move things around because if we did what if later we need to wake it up and then by moving it we would kind of destroy our ability to do so right so that's just a natural consequence of things and so as long as you can guarantee that the other framework will not mess with the Dom structure quick can be embedded inside of the other framework as well and because everything is scope to the container you can have as many copies as you want or you know you can put it anywhere you want on the page so like I made you know several copies of the header up here but you know I could put it on as you know behind the footer I mean I can just go and replace the footer with the header and I'm gonna click outside and now I just have a header at the footer right and it's fully interactive just like all the other ones right because the HTML or either the Dom is the source of the truth and so this property I think makes it extremely uh useful for microphones so one of the kinds of the microphones we would like to do is um personalization and personalization of let's say e-commerce website so here's an example of e-commerce website and you know it looks like a normal site um you know your reviews products there's your shopping cart you can add an item to the shopping cart like it shows up over here there's items in here like in in that sense it's a pretty straightforward thing nothing special but the way it's put together I think shows off the kind of the power of the whole system so let's let me click on this button because it says show scenes and what it shows is that this application is broken up into containers and specifically um you know there's a header container in this URL so quick dream demo so quick dream here okay I can go to the URL and it serves up just the hero image and nothing else right so this uh oops here this hero section over here is literally the same thing as this thing over here right um here it doesn't work because the quick loader is not loaded but here it works just it works because the quick loader is present here and what's Happening Here is that we hit the roots uh Edge worker and the edge worker you know has to compute the output but the single edge worker doesn't have the kind of the computational power or the enough time to actually do this so it branches off and says I need the header so the header or rather the the menu as you can see over here is quick uh this should be menu is a completely separate worker and because the menus is always same for everybody this worker sets the cash such that you know it's cached for a whole week or something like that I don't know how long it takes an update in the menu right so when the rendering is happening at this level at the root level the service worker says I need a menu and the menu just responds from the CDN says here you go but notice that the menu over here does not include shopping cart the shopping cart is a separate service worker so then you go to the shopping cart and say service worker I need your response and the shopping cart is obviously specific to the user so that can't be cached in a CD and then it has to do a full render but it's not rendering the whole page it's really just rendering a tiny sliver of the application which is the shopping cart right and then you go to the hero and then maybe you say you know um different people have different interests based on the cookie that you're logged in so maybe you come here and and me say like oh you like 3D printing let me show you let me do Let me Go fetch from a subworker uh Edge worker that knows how to return a 3D printing hero image because if you think about it another day your marketing has created limited number of hero images or hero um banners right maybe there is a thousand of them it doesn't matter at the end of the day it's it's a limited set and so after a while you will essentially have just cash hits for every single one of those hero image so to render the hero image is extremely cheap because you just go hit the CBN and comes back and the hero image is fully interactive you can do other things it's not a static piece of content right that just shows up and then the same thing happens with the shoe right so the personalization becomes either do a full render for something small like a shopping card or choose one of n for for more complicated things such as hero images or product um placement ads or anything of that sort and finally you want to print out what's below the fold and so if I actually Let me refresh this oops let me go here and if we go and disable JavaScript and I refresh this notice that it doesn't actually have the shopping cart so the reviews it says loading right because this particular component right here C has on visible right so what happens in practice is I can enable JavaScript it's only when you scroll to that position does the the content actually shows up so you're solving two problems first of all you're delivering less content to the browser so you're faster that way and second bit is that many parts of the stuff that you're delivering are cachable right but what's not cachable is the overall page but that requires that things are assembled and so assembly in quick is essentially trivial because it's just concatenating strings but um you know when you for example add an item to the shopping cart clicking here updates your shopping cart over here and that's across going between containers What's Happening Here is that clicking this button is firing a custom event and because events is one of the things that we can serialize the shopping cart can listen to it so let me let me show this to you in a slightly different way Let me refresh this let's find the shopping cart and the shopping cart is uh currently oh okay so for some reason they care about visibility so it's eagerly resumed so the shopping cart is already resumed but notice that the shopping card uh is listening to undocumented session token received event I don't know why they named it that way but uh oh no I'm sorry order change event this is the event that they're looking for right so the the button here fires an order change event if I click here let's go to the network tab clicking this button looks like yeah that sets the order and some room here we should see that we are sending a custom event can I search this no I cannot search this oh no you should be able to search what was the name again uh custom well I don't know where it is somewhere in here basically just says you know dispatch oh here it is look at that dispatch customer band right so just saying look I'm dispatching this event and with him I am passing the correct information that the system needs and because everything works on events that automatically goes and wakes up this container right here right and this container is listening for this order change event and it has a Handler that executes and wakes it up so you have intercomponent communication but it's not just component communication right you have you still have this property that the container is is you know not resumed and what resumes the container is the event so everything here is event based so the the way the containers communicate is the one container just fires off an event into a document which is a you know common place and then the other container can listen to it and the way the listening happens is purely just by this attribute on order change event right that attribute alone is the thing that um sets this up I I see so the last bit to kind of understand is that somewhere in here oh here it is somewhere in here we have to um tell the system about it so when the container shows up it basically tells the quick loader that oh by the way I expect this event I don't know if it's going to happen or not but I don't want you to eagerly wake me up and allow me to run some uh client effect or something like that to set up the events because it might never be fired right so all I really need to do is to tell the quick loader like this event may happen and then you can do whatever is necessary to kind of get it up get it kind of configured yeah so now taking that one step further what if you made the the quantity within the cart uh adjustable would would you have to do what would change or what would need to change in order to make it so that it would be bi-directional the the the the shopping cart would have to just fire an event that's it you fire a custom event with a custom name and then you expect that somebody will listen for it that's all and it you can reuse the event name you sure yeah he will probably also receive it yourself but yes it's just events that on the end of the day was always happening it all comes down to the fact that um the you know the way you listen to events is you say add event listen around Adam the way you listen to events in quick is that you add an attribute in the Dom and that's a huge thing because it means that just by the presence of the attribute the event will be received and you don't have to eagerly execute code to say that I need this event you there's no eager execution of code right let's just you just declaratively say I want this event and only when this event happened does it wake you up and um and execute this is it fair to say that he our listeners effectively when when they they know what to listen we've just we've ensured that they know what to listen for and they can for lack of a better description they can look down and say this is the thing I need and and that field is uncluttered because they have an instruction they they know what to listen for and they know how to dispatch a response um from that tag is that fair yeah so as a as a developer right let's let's kind of play with this a little bit let's go back to our demo as a developer uh we still have our okay we're playing with our I'm just going to simplify this thing here a little bit as a developer the only thing you really want to say is use um say Doc or use on document right and so let's say you say our custom event called Foo and if so if the event happens I want to do console.log um why are you Red oh sorry because it has to be wrapped in here and for some reason this doesn't add Auto Import okay okay so this is kind of like proper this is the equivalent of ad event listener right that you just did the what's unique about this is that this code executes on a server it's at the server time where we are setting up ad event listener and then it comes to the client now nobody's firing this event right but if you look into the the generated code it's not here that's the Json here we go so it says I care about food like even notice that you set up a full listener and so it says I care about a fool and of course I care about a click and so no um where is the network tab no JavaScript whatsoever here right no JavaScript is is present so let's fire a event so document dispatch event new custom event and I think you could do ah if I could type or whatever whatever you you happen to be passing across right so this event alone is what causes the the JavaScript to wake up and start downloading Etc right and you can see that the code woke up and it printed it back out with all the details so it's kind of interesting right that the mental model you have is just that you know an event gets sent uh and then the right stuff just happens without the developer really thinking about it and and the nice thing about this piece of code here is that it was able to execute it on a server right the subscription was on the server the other interesting bit about it is that there is no need to do cleanup after yourself because it's just an attribute right if this um if this Dom element goes away right what is the dominant right here if this dominant Dom element goes away so does the attribute so if the component disappears so does its attribute and then everything just gets cleaned up so I love this demo because I think you could do proper level personalization right like with this you can create a personalized site and this demo is incomplete because one of the things we would like to do is actually show how if I change a cookie I will have different header image over here maybe different shoe and so on and so forth and the the Insight what makes this easy is that is that instead of trying to Cache the whole page which is not possible because it's personalized you start caching individual subsections of the page and that is very possible and what makes it kind of easy from a developer point of view is that um it's easy to concatenate things together right there's no complicated step that the edge worker has to do to put everything together it's literally just cut and pasting HTML into the output and because it's cutting pastination of the output the output now is streamable and we keep talking about out of order streaming so one of the things we would like to do is that when the whole thing is being rendered let's say the shopping cart takes a long time to render wouldn't it be nice if you could just say loading or something in the place of a shopping cart and continue pushing every all the rest of the HTML and then when the rest of the HTML shows up you can go back and update the shopping cart right out of order streaming across Edge workers how far out do you think that's going to be so I think this demo already shows all the key points the only them part that's missing here is the automotive streaming and the Art of Order streaming um I think is it's just a question for us whether we want to focus on um getting the product out of beta or we want to focus on the audible streaming the streaming itself is pretty straightforward all you have to do is when the edge worker is reading a stream from a separate Edge worker right because it's like kind of doing a pass-through you use comments as kind of uh instructions for the edge worker and so let's say this is a shopping cart the root Edge worker starts talking to the shopping cart and the shopping cart comes back with a comment that basically says I have outstanding promises that I don't have yet so you know do whatever you feel is necessary but I am pausing the streaming because I am missing some data and then the root Edge worker sees that comment in the Stream and says aha okay so no problem I can continue passing all the other uh data across right so it's going to continue doing the header the body everything else and at some point the shopping cart comes back with another comment in the Stream that says I now have the data and I'm ready to stream and so here is the result of the Stream and then the the root Edge worker can just find a convenient time in the mainstream where it can insert a script tag with the data that um was missing and when the whole thing is finished the um the edge worker closes the connection to the other Edge worker right so it's not like there's multiple connections going on it's all done through a single connection and through basically comment nodes that can tell the other side whether the streaming is happening or not and as long as the framework supports streaming out of order streaming then the common nodes basically allow you allow the coordination of multiple Edge workers to kind of build up a response and so um I think this is a an important demo because I feel like our industry is not doing a good job on personalization and the thing that's hard about personalization is that the moment you have a piece that is personalizable we don't know how to render just that piece we kind of are forced to render the whole page and the rendering the whole page is just expensive so that's one problem the other problem is that we have hydration and so even if we somehow modify the response on a server the hydration is going to come and clobber all over us and return it back to the original state so any kind of changes really require two things you have to modify the HTML of the server and then you have to modify through some mechanism the hydration process on the client which is why most people what they do is they say you know what forget it we're not going to personalize up the server instead we're just gonna render a generic thing and when the hydration happens on a client it basically calls back to the server and says like is this personalized content should I personalize it and then does an update or we insert an extra script tag which then modifies the way hydration happens Etc and this all stems from the fact that hydration is an afterthought it's not a fundamental property of how these systems work but if you can have a system where you know the server-side rendering is the fundamental property of how the system works then personalization becomes pretty straightforward and if you can break the page up into individual containers then you can start caching individual pieces or putting them out of order Etc so I'm actually super excited about this uh demo because I think it allows um you know basically anybody to go and build a proper personalization site without having the resources such as Amazon right like Amazon has sufficient resources to kind of bulldoze through these problems but most people just cannot and so can you have a proper person like Amazon level personalization without having Amazon level uh investment into it yeah so this is what we're kind of aiming for this is the the ultimate goal that we want I think we're about 80 there so we still have to figure out a few things but pretty close so suppose if this is having the different container and one container is a react Tab and another container is angular app now I need to pass the props right so how I will pass I mean one uh maybe the react is expecting as a props but the angular component is expecting somewhere as a property or something so yeah so the inter-container communication right now is just through custom events and that's a good thing and uh in a sense because one of the things that it um enables is that notice how I showed you the different parts of the system are actually running on separate urls that means those separate URLs are owned by separate teams it means those separate teams can deploy and roll back their things independently of everybody else right one of the problems with webback faradays Federation is that when team a decides like oh we messed up we want to roll back they can't the only the only thing they can do is roll back their code make a complete new build and deploy a new build and hopefully the build didn't mess up right hopefully they had the correct build right so so you can't do that whereas here the final linking the final thing that assembles all the pieces together is in the browser not as a build step right it's a it's a browser step and because it's a browser step um you can have each one of these containers that you see over here to be owned by a different team that they do their own separate build they can roll back or push new versions separately independently and the only thing that they're agreeing on that they have to be careful about is the name of the custom events and the payload that the custom event handles right so they have to make sure that between different versions The payloads are the same thing that you know the structure of it doesn't change and suppose one container is dependent on one event and then suppose the root component is loading and once it loads and based on the user interaction it will pass the object to the next container so it will wait till that time or how yes so this is all based on events and if you remember I kind of pointed out that as soon as the HTML is there that says that you can click on it it is guaranteed that when you click on it the event will be processed you might have to wait until the JavaScript downloads right but it's guaranteed that it will be processed now to make sure the JavaScript is is there eager prefetching is done through the service worker is kind of what kind of makes that happen but it is a guarantee one of the things we're thinking about is actually incorporating a very simplistic cue into the quick loader so that you can push things in the queue and for containers let's say there's a container below you let's say that the header fires an event saying whatever but the the person the container receiving it is below you so it hasn't streamed yet so in that situation would be nice if we could just push it in the queue and have a guaranteed delivery that it's sitting in the queue and then eventually will be delivered and that's pretty you know that's a pretty straightforward thing to do in a quick loader but it would really enable other use cases as well that would be nice will we get to see a local demo of building a container yeah I can show you that um it's pretty straightforward um we can do that next any and so I mean we had to do kind of the similar implementation as MFE so what we did like you know from the module Federation we just compiled as a component and then it was a react component and then another application which was built in angular they had to consume it it I mean they could not because they cannot pass directly the props so we had to wrap in the web element sorry web component and then we have to you know pass the data as a props as a property of web component so how it is different from the from the web component like it doesn't seems like well web component requires eager hydration right or big component requires that some JavaScript runs eagerly and sets up a listener right and that alone will probably mean that the whole application is downloaded right because nobody's going to do the the trick where you're like oh yeah I'm just calling this JavaScript to set up a listener and then I'm going to Lazy load the behavior like in theory it's possible in practice Nobody Does it right so really what you're saying is that if you want to use a web component the whole web component the whole of the code associated with the web component has to be present before you can talk to it and so one of the things this is solving is as you as you pointed out as I pointed out over here again is that when this code shows up right when the application wakes up there is nothing no JavaScript right so for example if you don't click on a button to add the shopping cart the shopping cart just doesn't doesn't get executed right and it's only when you want to talk to it by firing an event only that causes the download of the associated JavaScript or rather the execution of the associated JavaScript right the download might have happened earlier because the the service worker eagerly fetches the code because it thinks it's very likely that you will go and execute it but the execution of the code is delayed until you're ready to do something useful another way to think about it is if you were to look at code coverage of the code in quick you will be pretty close to 100 all the time right because you're only downloading code that you're planning on executing immediately and any code that's not um being executed right now is probably sitting somewhere behind a dollar sign somewhere and so it's not being downloaded one more question like in the container when there is a source rate there will be some kind of a URL so how it handles the course issue like will not be there any course issue like if one component is in different URL and one component in different so yes so let's look at it here so this is our home page and so in here we have one container here you can see it says Q container and it gets its code from slash build and then in this particular case this is actually fetching the code from a completely different URL over here right so we have to make sure that that server sets the correct course headers right but that's just a standard thing that browsers do but by setting the correct course headers um we can we can do this oh yeah let's talk about prefetching and also you asked about the containers so we showed I kind of showed you the microphone and architecture uh the personalization um the the streaming we only have we kind of talked about streaming like we only have kind of in-order streaming so far but out of order uh streaming Automotive rendering is something we're thinking about uh very heavily but let's talk about prefetching it because I think a lot of people have a lot of questions you know or concerns that you may be in the world where when you interact at something it's going to be slow to interact right your first interaction is going to be slow like how do I make sure that when I click I'm not fetching the code lazily so um a good example for that is actually our home page here we are in a div mode right and so when I click on a search box I'm sorry so zoomed out because otherwise the it shows kind of the mobile and then the search box disappears but um let me just clear this when I click on a search box notice huge amount of uh JavaScript shows up and um you know individually they're not big but it kind of adds up and it says this is not a good experience so that's because in development mode we have two things going against us first of all we have we put every single entry point into a separate file and the second bit that happens is we don't have a service worker doing the prefetching right so the same exact page when I go to production same exact thing go to the network tab let me just zoom out so that I can see the search box when I click the search box oops now it's when it's start with the blank and we're going to click notice only a single file showed up and that's because um in in production we were able to concatenate all the symbols together and tell the build system like you know put everything together and the way we did that is through Veet config this file over here and this file basically says all of the symbols inside of the algolia search that you are listed over here make sure you put them together into the same symbol so we kind of collocate them as of right now the the list is manual but in the future we're going to have a service that you can use you don't have to that will automatically cluster them and tell you like oh based on how the users use your website you need to make sure that these symbols are together and so you're going to have ideal bundle sizes because I got a question so the thing you were talking to me about earlier which is when you have disabled cash enabled yeah so let me show you that next yeah it just to make sure that we're on the same page you you were saying that disabled cash is a bit of a mislabel because it also disables the service worker yes so so in this particular case looks like few things are executing eagerly so there seems to be some client code here and notice right now it old comes back with service worker right so this these files are essentially instant if I disable the cache here and I refresh um it still says service worker what is going on here okay I don't trust this tab of chrome anymore initiator right so prefetches things what yes it does a service worker but now it seems like it does not to any difference uh maybe Chrome changed the behavior but this button right here when it used to say disable cache it would say disable cache and disable the service worker and so a lot of people would try to disable this and then refresh and say hey everything is slow because the service local is not being hit but it looks like it no longer does this thing so I'm kind of confused what happened to Chrome is that they changed it in the latest version um not sure what's going on in here but let me show you the service worker so when you navigate to this particular page to make sure that this button of clicking the an algolia search is instant the system starts prefetching the code immediately and it does so through the service worker so if you go to the application you'll see that the application contains a service worker and it contains a cache so if I go to this URL all of these things the service worker eagerly prefetched right so before any interaction happened on the user side the service worker immediately started fetching this so I can delete this cache here and I can go and delete the service worker as well by unregistering it and this is now showing me what it looks like when the person navigates to the site without it for the first time right so we can try to go refresh empty cache and one of the things actually let's do this as uh fetching Let me refresh this again so let's go back to application unregistered service worker take the cash delete go to network tab I can see Fitch xhr when I go and empty cache on how to reload one of the things I will see all of them start with q don't invert why are they not here now the service worker is oh because it's disabled ah I have it disabled again let me try this again uh uh sorry application delete service worker unregister okay Network tab there we go so the service worker immediately prefetched these ones right before I even interacted all these Q files got prefetched by the service worker um and so now when you go to the application you'll see that the cache got filled in with all of the stuff right so before the user even triggered anything or any kind of behavior the code eagerly started to be downloaded and the nice thing about breaking that into pieces is that if the user would have clicked before the service worker had a chance to do that because the individual files or few number of files it can change the order in which you download them whereas if you have one single chunk there's nothing you can do you have to download the whole chunk and and be done with it so the point I'm trying to make here is the disable cache button is kind of dangerous because it doesn't quite do what you think it does it oftentimes disables the service worker cache as well and so a lot of people will go and demo quick and be like look how slow this is and then they click this button thinking they're pretending to be the first time navigation but what's actually happening under hood they're disabling the service worker magic and so the proper way to do it is to keep this enabled clear all the caches and then navigate as the first time and you'll see that immediately the service worker fills in all the data so that when you can when you're ready to interact with the page uh it's there and available okay if there's questions otherwise yes I so what it's I think you just explained and please feel free to correct is that we have the normal stage or the you know nine out of 10 case where I as the user probably won't be fast enough to get to a part of the page before I have the the shards to to run that page but if I do there's um we already have the case covered where if I'm at what I'm asking for it will be prioritized yes okay so all of these things are basically done like this is in my opinion the most efficient way to download code right like that I can't imagine what else we could be doing to kind of improving the situation right if we remove the code that we know it's not going to be needed on a client we download the code in the priority order and the probability in which we think you're going to use it we eagerly download all of the possible interactions that you could possibly do and we have resumability which means that we don't have to eagerly execute all the application code we can just continue where we left off right so I can't think of any other trick we can do to kind of improve the situation even further and again uh the lovely part is that this just how the system works out of the box there's nothing special that the developer has to do all right so one last thing to talk about is um react and specifically how do you run react code inside of quick so one of the things we have is is that you know react is a huge ecosystem of UI libraries and so both for the purposes of reusing existing ecosystem and also for the purposes of a migration we allow you to run quick code sorry we wanted to run react code inside real quick and so let's see this particular demo again starts with no JavaScript even the react code doesn't show up over here but then when you hover over it you know the JavaScript showed up so hovering over the the the code you know hydrated the the reacts or react got downloaded hydration happened over here Etc so that we are now ready to work with the slider and so you can see that this slider is a material UI slider this button is a material UI button uh this button I believe is a is a quick button and this table is a table that's lazily loaded so all of these things um we can kind of show you that we can just use the existing components so let's look at the code base how this actually works let's see if I have the correct yep that's the correct one okay so here's our component click react uh demo right so that's this one over here and we have our select and the select is just a regular select and it says on value change we have a callback right to go and update a signal in this particular case I believe yep it's a signal um and then here we have a material UI slider so do we have oh I see this is the select over here I see so this is a regular component but this slider is a material UI slider right and so the material UI slider actually has to be imported from a separate file so we created a separate file called react integration since we have alert button and slider so let's look at a slider one of the things we have to do is the reason why it's in a separate file is because we have to say like any jsx that you see here is not quick jsx it's somebody else's jsx right so the kind of the compilation has to change in here and this pragma is what tells the system is that the jsx you're about to see is not to you know it's not quick one so don't mess with it so it's the react one let's react to its Tech and so in here you import this quickify function and you pass in a button from Material UI as you can see over here and this function then returns an equivalent component that is a quick component so it has all the so you can be dropped inside the quick application as you would see fit um and you know we can see that the we can for example specify that in the case of a slider we want to hydrate it eagerly on Hover so as soon as this is what kind of what you saw is that as soon as the the user hovered over this that's my whole JavaScript kind of executed is because we think you're about to click and execute so we prefetch all this information for you now the nice thing about it is that we Bridge all of the pieces so let's go to the slider notice a slider has on change and so we produce for you unchanged dollar sign so that now you can lazily initialize it right so even though the hovering downloaded and brought the material UI to life through hydration uh when I once I start sliding it there's yet another piece of code which is the Callback that gets downloaded and executed right so this is normal kind of behavior that you would expect from um from Quick um here is another example which is now we have a material UI button but you know normally material UI button has like this fancy um uh Shades behind it Etc notice what we've done actually over here I'm going to see if I hover over here no JavaScript is being downloaded whatsoever so this one is configured to never actually hydrate on the client but notice I can still click on it so the reason for that is because we're saying you know what I'm the host element because we're gonna have to put you inside of the kind of the Box on the host element set up a click listener so we had the benefit of rendering a button but we're just not even bothering and hydrating it because like we don't think it's worth to have that fancy animation over there but we still want to be able to trigger listen to The Click events on this particular thing and so we can register a click event without actually hydrating it so the component the button got rendered on the server with its Styles and all the important parts but on the client you know we're not paying for for any of it um this shows yes so let's say someone does want those fancy pants animations yeah so we colloquially refer to as the bloop animation bloop okay um is there a way to yeah so it's as simple as basically telling us when do you want to um when do you want to uh hydrate it so you you effectively opt into how you want see now you have the fancy animation see that the bloop or whatever you call it yep it's there so I'm just kind of showing you different possibilities that you have here right the other thing we have working properly is that notice this one there we have a material UI alert and inside of it is a quick counter right so this is an alert that is owned by material UI and inside of it through its children we project a container so this quick counter is a quick pixel code but the outside of it is a material UI piece of code which runs inside of react as well right there's a 3js here how do I if I click on something how do I get it running pardon me but before you move on there I wanted to understand the boundary of the reactivity um and the I imagine that uh when you're incrementing that that number that nested quick counter no below below that this is a warning from quick I could have sworn okay yeah I'm just projecting a quick element inside yeah container so I guess what I wanted to understand is every time you're doing that you're um incrementing uh something that's then triggering an event passing it up to the document and then the this is the thing that crosses over the the boundaries that and then that mui container receives it as a prop and it triggers a redraw no I don't think so I don't I think um uh I think the way it's set up is that it this follows the the the quick rules not the react rules right so the quick container is rendering itself independently of emui alert movie alert doesn't even get awoken like he has no clue what's happening in there it's not part of the render tree at all interesting so if you quickify enough things then you get rid of that re-rendering yes on the unnecessary re-rendering that's right so if you think about this with quick react you kind of have um kind of Astro a better version of Astro for free like if you want to like lazy hydrate components Islands whatever sure do it and it turns out it's even more fine-grained than what Astra allows and we properly pass the state around which is what Astro doesn't do so what's the what what's the drawback they've been around longer so they have more of a mind share right um I you know when I talk about drawbacks I think there are two kinds of drawbacks there is the intrinsic and extrinsic right so extrinsic drawback to quick right now is it's it's new and there's no ecosystem and there is you know no mind share right but time will solve that particular part an intrinsic uh what's what I'm looking for intrinsic downside of quick are things that will never improve right or will forever be this particular way and that's a much more complicated discussion because um you have to learn new rules like the dollar sign has rules right we talk about them like you have to learn those rules you have to kind of think about the fact that like the main thing about the dollar sign is that it's asynchronous and that it forces serialization so you can't just like randomly serialize something and assume that magic will happen so there's a new set of rules and those rules are unlikely to ever change right so those will be kind of the intrinsic drawbacks to the system but I I'm going to argue that those are actually very minimal compared to the benefits that you get right so as of right now the most of the kind of drawbacks of quick are extrinsic to the fact that we are new the the the documentation might be not as good the number of videos is not as good um the the community is not there the third party system is not there but that will be solved in time whereas you know the intrinsic things of for example react is like making a clock example is complicated because of the way uh the thing works and it's just not going to change because it's just the fundamental property of react right and so the dollar signs have meaning in quick and that's not going to change because it's a fundamental property of the system sorry I probably went on a diet trade over there yes was the dollar sign that is also a convention right like observables uses the dollar sign convention for streams and things well but it's not required in those cases here it's required it's required yes so the dollar sign has a meaning to the optimizer so the optimizer is a piece of code that extracts this so actually a good place to go you see we're going to go quick uh proper Zoom okay tutorial what happened to the playground it's not there anymore what oh I see there's no opening playground all right so we have a Hello World let's open in Paragon and I'm gonna up the font size how's that so right now there's no dollars well there's only one dollar sign right so you can look at the symbols that are exported and kind of see that currently there is um basically just this content right here that's exported right once I add a on click right the optimizer doesn't know that on Clique is special or anything like that purely the only thing it cares about is that it's a a symbol ending in a dollar sign that's all it cares about right and so here if I add on click that alone is going to make now a separate entry point for us right so the optimizer is really in just in the business of purely just I see a dollar sign I extract it over here that's all it cares about nothing else right so there isn't like some complicated set of rules or special things Etc the reason why this is important is because now as a developer you want to create your own use method that ends in a dollar sign you can right because we don't have a special set to us it's just it's a method called ends with the dollar sign if that's the case take the first argument and yank it out and do this magic for it does that imply that uh the line you just added on four would be included within the scope of the component dollar sign symbol so would it would comp would on click close over right so let's look at it so the app component got hoisted out it's a top level thing right this is the closure here and notice that it says that wait what there's more P what happened on click Let me refresh this there we go so here's our on click and it basically knows that whenever you see a dollar sign on it take the first argument and do this to it move that function somewhere else actually it doesn't even care if it's a function right it just says take that argument whatever that is move it to a separate file and then leave behind a dynamic import and then tell me what symbol did you put it as right in the dev mode we also put additional information about uh things in here but it's just the dev mode in production that's not there but you're effectively inlining a reference here instead of the you're leaving a reference instead of closing over the function that's right and so when these things got moved if you look at the bundle um so in this particular case the the if we don't close over anything right and because we don't close over anything even the framework doesn't get included so let me close over something let's say we want to say uh okay so now that I closed over it and it doesn't I have to refresh it yes see now it inserted the lexical scope right and because I had to insert a lexical scope now it caused an import from it from the framework so this thing here is the framework itself and oh by the way none of this stuff is stuff we do we just rely on roll up right so this is normal roll up stuff right like we're not trying to reinvent the world our only job is to produce extra files that we can then feed to the rollup and Rob does its magic the only other item that I can give you a very quick overview is Builder so let me actually zoom in this a little further out ah doesn't zoom out more let me disable JavaScript on it and refresh this page so when you come to our page um turns out half of the page is missing it's not here see it just says loading let me zoom in here it says loading right and we do that because if I enable JavaScript because there is more stuff that's below the fold but like a refresh this there's more stuff below the fold but we don't want to you know ship it Etc until you start scrolling because until you kind of get to the bottom like why send it and one of the important reasons why we don't want to do that is because there is where are they there are Twitter testimonials is this it yes here we go here's the Twitter testimonials and I don't know if you looked at it but the Twitter testimonials download like megabytes worth of JavaScript and they take forever to bootstrap right so we have a home page we're retiring how important it is to have a fast startup uh it would kind of suck if our own homepage was slow because we happened to have Twitter testimonials in there right so the way we solve this particular problem is we just put them below the fold and we tell the system like don't bother downloading it and the way this actually happens is when you first navigate to a page let me go here first now I'm going to get to page query selector we have two containers right the container that comes from the site itself and the container that comes from uh Builder when you scroll more containers show up oops so now if I run the query now we actually have three containers like additional container showed up that the bottom part of the page is actually yet another container that just lazy loads and shows up when you scroll and because it's literally just inner HTML into that location um there's nothing really to do like the code for it is beautifully simple if you go Network search for lazy there we go the code for it literally just says um remove the on Windows scroll event reset the style height and inner HTML the content into it it's really that simple nothing else and that's it it works as you would expect because you're just concatenating stuff into the HTML so um this this site here is a site owned by uh you know by us inside of the repo that you see but this content over here is not it turns out if you go to Builder IO command load um the the middle part of it is handled by our CMS system so if this loads you know what's going on here okay the middle part you know is is held by the um just get this URL fixed here under equals SDK okay so notice now our marketing department can go and change anything that's not in the header right the header they can't touch because that's rendered by the application itself but the center of it they can so all of this stuff is editable by them and of course the footer also they cannot touch because that's rendered by the the open source repo so to speak right but everything in the middle is completely editable so anything I do here like for example we previously added too many question marks exclamation points rather I can just publish and within couple of minutes this UI will update so what's going to happen is that at some point the caches will expire in the CDN I mean they probably set up something like one or two minutes so normally when you come to our page you're hitting a CDN cache but then the cache expires like in two minutes and then every two minute basically it's a full SSR of the page and so in about two minutes from now when the people will come and navigate it will now start showing it without the extra exclamation points right and the cool thing is you could do behaviors too so you can click on it says copy to clipboard whatever so this is super easy because we can just hand it to all the marketing people and say like hey make ours a nice web page and they just go and edit anything they want and they're not kind of constrained by what we what they can do we can also add components Etc and so that's kind of the kind of kind of falls into it so that was pretty much most of it I'm kind of out of ideas of what else I can share with you so unless you have questions yes questions so you had mentioned some uh way of aggregating user statistics yes I you know we don't need to give it the full download but I am curious uh as to how that uh how that works yeah so it works as I said everything in in here is based on uh events right so what happens is you can set up an event in document add event listener and you can listen to quickly use symbol if I remember correctly that's going to give us an event and we can do console log and then we can say event dot detail dot symbol okay so if you do that then you see the symbols showed up if I click on stuff a whole bunch of symbol shows up so as I interact with the page basically symbols are showing up right because every time the framework says I need something it does it by firing this event it fires other events but basically everything works through the event system and so it's very easy for you to observe what is going on and the idea is you take this information you collect it you run through some clustering algorithm look at the timestamps or whatever right so um actually Let me refresh this page a more appropriate system I think would be um to not only print symbol but also to e dot timestamp I think you have a misspelling that's time stamp okay let's try this no is it not time stamp that's not time step uh there is an event somewhere on a detailed like I don't know what it is that gives you the time state right so we're doing the timestamp and um the symbol you can create clustering information you can basically tell figure out like what are the users clicking on more likely and what things are always come together and then you can feed that information into the build system and so when you uh when you when um Optimizer creates these extra files so that the rollup can do its magic it can create the files in such a way that the rollup will automatically put things together the other thing that maybe wasn't clear is normal Frameworks have no idea about what's happening under the build side like they're completely clueless in Click build information is fundamental part of the the information of the the framework the framework needs to know where are the symbols where do we download it from what are the relationship between them all of that information is a runtime information that's available to the framework so when you create when we create a build for you the last step of the build is something we call the Manifest manifest contains the Full graph of all the symbols the relationship to other symbols which simple Imports which other symbols which file they're located in basically everything you could possibly want to know how big these files are where they are everything you possibly want to know and that information is available to their framework at around time and so framework can use that information to do all kinds of optimizations right and that's kind of unique because usually that's not how systems work so you can just basically collect this and then you can um uh go and and use that information to feed the the system the other thing you can do and I can't remember off the top of my head so give me a second there is a script tag that sets up here we go Cube prefetch so no that's not Q prefetch no module here we go no it is Q prefetch you can fire custom event with a set of bundles you want to prefetch right this line here this piece of code here that's Auto generated is when the framework ran on a server it collected all of the listeners and said when I rendered the SSR on a server I saw all these possible listeners and those are the possible entry points for the system and so it includes them in here and says service worker make sure you have these because these are things the user can click on but you can augment this and you can add more things into this list so if you augmented this list and just gave the whole thing to the service worker then your app essentially becomes offline immediately right because you already have a service worker that prefetches and that's it Etc the the Q Dash whatever hash that is um fetched that is cachable forever like that hash is a hash of the content of the file if the content the file stays the same that hash is good for the future right so if a person comes and navigates your site and only part of the application has changed then only some of the hashes will change in this list the ones they haven't they can just reuse so they'll have an improvement so again this is a benefit because today when you show up to a site and you have a new version It's usually invalidate everything because your chunks are humongous right uh and the other thing to understand is that the symbols are stable between the builds so while the hashes of the Q files are not the symbols are stable and that allows you to use knowledge of previous build to to augment the next build so I mean you just showed like how the symbols are listing up in the console so when you said like we can collect this is there any framework provided right so we're going to provide a framework for you and it's going to be a service we're going to provide for free so that your application you can just give it you know set it up so to send the data to us and we will give you the answer for free but if for whatever reason you don't want to give us data or whatever right you're welcome to do it yourself there's nothing proprietary in here I'm just going to show you that every time a symbol is needed it's the custom event is fired you just have to collect those events and then send them to your own system and do whatever you want right out of the box the the bundling system I think has four different ways of bundling like you know put everything in the same file put everything in a separate file put everything by component uh and those are kind of the default heuristics that we have but then the idea is that as you collect behavioral data then you can really fine tune this information and again I want to stress that this becomes a configuration information right you don't have to change anything about your application the way you've written it Etc it like nothing changes it's just some person who who wants to optimize the heck out of the application right twiddles some bits and the rest of the engineers don't care no go ahead so yeah kind of on on the topic of like Engineers don't have to worry about it one of the things that we talked uh or we kind of glossed over quite a bit yesterday um and I'm really curious about is developer conventions and when we were looking at how quick city does routing and um you know determines which layout to use there's a there's a whole lot of conventions that are defined um are those configurable are they um you know it conventions are something that a lot of developers develop a lot of strong opinions about and if they if they disagree with you know I don't want to call it routes I want to call it uh areas or something I don't think as of right now that's configurable now yeah I think it's all of this is kind of hardwired in um are they configurable in like next.js and stuff and salt kids no I don't think they are yeah I don't believe so yeah there is huge amount I know that was one of the like major attractions when react was new is it was unopinionated and at the time the community is pendulum it kind of swung away from you know overly opinionated and you know just let me let me Define my own routing mechanism and you worry about the rendering of my thing so you know finding a balance between overly opinionated and under opinionated is always a challenge I was curious kind of how how quick finds itself striking that balance um it is yeah it's it's pretty opinionated I think well in the case of routing it's as opinionated as next.js or next or salt kit or any of those ones right in terms of the actual quick itself the the framework minus the miner framework um I think it's about the same as as react like you have the methods and we don't have statements for you like what you should or should not do so reacting to that though you were talking about uh opinionated versus unappiniated when it comes to routing I'm thinking through what are the drawbacks of a file system based router it manifests as a problem when you're limited to data fetching on a on a route by Route basis that goes away when you have the ability to do tree shaking of your data and have that granularity with the signals and if I'm not mistaken I I think the the thing that makes you want to back away from a strong opinion there is that you can't have your your cake and eat it too you know um but I think this decouples the advantages and disadvantages like I'm still trying to figure out what are the disadvantages aside from not enough people know about it I think that's that's the main one um you have to learn new things you have to reprogram your brain to think about it in a different way right that's definitely the falls on the category of extrinsic the the disadvantages but like as far as what you can build with the framework it should be the same as what you can build with angular quick or any one of the other ones but like we were also talking about the the other aspect of it is you know for Enterprises that are used to being able to just serve up static files and have everything rendered uh client side uh there is you know at least for some Enterprises there's going to be a change in how you know where does where does the uh build occur you know what's what's doing the surveying and where does that live so you can have SS G right or is it static site generation right you can have a SSG system now in most SSG systems will not be an application because it doesn't make any sense but in case of a quake why can't it be like yes that's the initial state that you ssg'd on a during your build but like from that point on you can do whatever you want it's totally interactive you can fetch data you can manipulate data you can use use client effect to kick off operations Etc um so all of that just works but at that point you're you're getting an initial page load that's faster because it's SSG yes and you're reducing the amount of JavaScript footprint but then from that point onward you have enabled essentially client-side that's right for that for onward you're essentially an SBA and you can do that right so quick really blurs the line of what is a server what is a client what is an Spa what is an MPA what is a you know all of these lines are just really blurred and it just becomes like well it's kind of all together at once and at first it might look scary but I think what it enables are is amazing mark a question from online unscrolling can the lazy Behavior be customized to be more like greedy or like pre-fetching like rather than when it fully comes into view prior to it fully coming into view yeah so those are all separate things right so um when the prefetcher loads your your data that's controlled by the service worker that controls uh basically when did the the JavaScript downloads that's independent from when you actually start executing the JavaScript so you can for example say I want to start prefetching the moment you scroll or you can say you know I just want to prefetch immediately at the very very beginning and then the second question you can have is like when do I insert the HTML do you want to insert when it becomes visible in which case you're running the risk of slightly seeing loading dot dot or you just want to immediately insert it the moment scrolling happens which means it's way more eager than it has to be but it probably you'll never see loading dot dot setting a threshold of like 200 pixels yeah so those are all like things that you as a developer it's now in your hands to choose right before it was not in your hands to choose like you just couldn't do this like there was no easy way to get this Behavior and now you have a relatively easy way of customizing whatever you want so in I mean in case of the in case of the MFE uh suppose in big Enterprise maybe we cannot influence like main website will be become a quick application in one day so if we start from say like the smaller MFE in the quick and that is getting consumed in the reactor or angular F how it is possible like how it will consume the the events in the quick way it should all just work because um as I said like as long as you have you can tell your framework not to mess with that Dom right not don't don't destroy it as long as you can do that then into that inert Dom you just load um quick it's just as simple as string concatenation right the dot inner HTML just load it in there and as long as the quick loader is the script tag is somewhere on the page it just continues running that's the kind of the beauty of reasonability it it doesn't differentiate whether it's loaded into something or not or how the HTML got there all it knows is that if you click here go update that thing over there right but then how they will include that MFE code in their say like they I mean say react or angular they don't support the container or all these right so they might so the way I would do it for example in react is that I would use uh dangerously set inner HTML or something like that right I would just grab the HTML I would have a separate click server that renders SSR renders the application or the content right and then I would grab that HTML content and I would just dangerously set it inside of the react and make and tell react like do not descend into this Dom tree this is not yours right and as long as you can do that then it just works and how it will receive the data from react because it is like custom based event I mean attribute based event right oh right so how do you do uh communication yeah um we are exploring the possibility of doing kind of the reverse of quick fi so that you can take a quick code and do it in react like it should be relatively straightforward but for now you can just use the event system right just Fire custom events um to kind of get it going all of the components you're living inside the window and you can use that as the as the universal communication space is that right yes but that would require for this kind of scenario we'd have to have we'd have to provide our own events and event handlers is that right yes okay yeah but that's still way more convenient than another scenario I could imagine trying to glue two Frameworks together yeah yeah so okay so um we were looking for documentation to demonstrate how to use uh multiple Frameworks in an MFE type environment has that has that evolved since yeah that documentation is something I need to put together so that's homework for me actually um yeah I I think a lot of concerns will be allayed if we have a chance to take a look there is some discussion of it in containers Concepts no maybe Advanced oh it's going to be Advanced containers right here um so yeah some of it is kind of explained on a high level here oh look at that even there's a section of microphone but it probably has to be flushed out more there's also this button that says edit this page so and I guess the the one other concern that I had is you were showing how each of those separate routes uh those micro a front-end containers could be rendered individually um you know in in different environments I could see how for security reasons you want to make sure that that route cannot be accessed directly it can only be accessed from the the host app that's weaving all of these pieces together um and do you have a method of protecting against that so we showed you the login page yesterday right where we said like make sure the cookies said or something otherwise redirect to different URL like there was a request Handler at the top level um other than that I think that that's on to you like how do you make sure that you don't serve up the content into the wrong hands right um I think one thing I can show you about regarding the containers is that if you go to the root there is a file called root TSX right so that lays out your HTML but even before that it's entry SSR and so this basically says render to stream the root component right which is basically the whole HTML and gives you the pre-funishing strategies you know how to get code Etc all kinds of options are passed in here and by the way here's the Manifest right this is the information about all the pieces that the framework needs anyways um in here that this defaults to the HTML tag output but in here you can pass a uh forget off the top of my head where it is but in here one of the options on stream streaming stream writer no somewhere in here there is an option you can pass that basically says don't do it into HTML do it into a div tag for example and now what you get back is just a a div tag that you can insert into anywhere you want Mark a question from online um could you talk to resumability in a situation where there's many people working on the same document like in the case of a collaborative text editor I mean an end of the day it's just events right like the events are either coming from the user that's sitting in front of the computer or they're being fired through um some kind of a stream right that the the server opened up to the client and so um this should work just straightforward like I think streaming there's a streaming API right and I believe in the browser and it just will fire events for you and so you just have to listen to these events and this event listening will automatically set up um lazy loading and all the other stuff that we've seen right again it all comes down to that the whole Machinery is all based on events and as long as it's just events it just works right um whether the events are coming from a separate um worker thread or they're coming out of a stream or their events that are coming out of user interactions like the system doesn't care it's just an event that's that's bubbling up through the Dom like all other events do should we call it a day all right well you guys been awesome thank you so much for uh you know listening to my crazy ideas Etc I also want to send a shout out to Adam Bradley and Manu uh two guys who are doing most of the code behind here um and they just did an amazing job Manu is the guy behind Quick Adam is the guy behind click City and so the all the amazing stuff you've seen is mostly goes to them I'm just the guy with a crazy ideas that's all thank you [Applause]
Info
Channel: Frontend Masters
Views: 3,717
Rating: undefined out of 5
Keywords:
Id: dc6mUwXnyqE
Channel Id: undefined
Length: 200min 56sec (12056 seconds)
Published: Mon May 22 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.