Kevin Bridges - Responsive Svelte (exploring Svelte's reactivity)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Music] [Music] hello my name is kevin and this session is all about exploring stelt's reactivity so this is going to be a bit of a deep dive but we're not going to go too deep into the internals of svelt because we're going to be doing this from an observer perspective by visualizing svelte's reactivity first hand right within our application so there's a bit of mystery behind some of these concepts and we'll delve into some of the lesser-known detail that you may not have considered i should mention that this is not a spelled tutorial you don't need to be an expert but we're not going to be spending any time on svelte basics so the hope is that we will come away with more insight and be better informed on how to use this awesome product i think there's something for everyone in this session whether you're new to svelte or an experienced self user so let's take a quick look at the resource links that are listed you might have noticed that they're there here highlighted in yellow on the lower left of the screen i've also placed this on the demo screen in the upper right in case you missed it it's basically a bitly link so it's bit dot lee slash r dash felt for reactive spell this is a link into my web page if you click on the button or scroll down you go into the presentation syllabus and there's also a list of the resources that we'll use throughout the presentation the first one is uh there's a copy of the slides you can follow along if you so desire the most important link is the second highlighted link the demo link this is a rebel that we're going to be using throughout our presentation i've listed an article here i've written an article by the same name and in some cases it goes into a little more detail on what the presentation is does so you're welcome to look at that if you're on uh leisure and uh there's also a second rebel entitled reactive triggers and we'll be using that midstream within the presentation just briefly and lastly there's a link to rich harris's rethinking reactivity presentation so let's go ahead and get started i'm going to jump right into some code this is a reuser component and basically is a component that is going to display the characteristics of the currently logged in user the first thing you need to know is that the user import here is actually a spelled store which is a user object that has the characteristics of the user we should be the name and the phone number and then we'll actually reference those characteristics within our html markup you can see that we're referencing the uh username and the user phone number and we're also distinguishing some css styling based on whether or not this phone number is long distance if it begins with a one dash we're going to color code it with a long distance css which happens to be pink so let's take a look at this in our rebel so if you go back to the resources link just click on the demo link and that brings up the repo itself so i'm going to maximize this to try to get as much real estate that we can i'm not going to go into a lot of detail uh because we're going to focus on this great user component pretty exclusively but if you do look at the rebel just briefly the bottom of the app the primary thing that it's doing is it's actually combining an edit user component and a greet user component so you can see that the edit user is here on the upper part and the greet user is the component that we just reviewed very quickly normally would not show these two components together but in this case it merely correlates the reactive state between the two so we can actually run this if we change characteristics of our user i'll change it to genio let's add an extension to our phone number and if i apply change you'll see that that's immediately reflected in the user component as you would expect and then also if we change the phone number to have a uh one dash in it it will be considered um a long distance number and so applying that will apply the css styling change that we saw earlier so as a trivia point the phone number and the name that are used in the demo are actually very famous it actually may have been before your time so i would suggest that you google it and see what you can find so what could be simpler we're going to be using different variations as this component throughout our presentation so as a sidebar i'll be using the term snippet quite frequently in this presentation a snippet is any javascript expression that felt reactively manages and invokes when its dependent state changes so there are two forms there's a code snippet that is found in the script tag and that's demarked with the dollar sign label and spell refers to this as reactive statements and there's also an html snippet that's found in the html markup delineated with curly braces and spell refers to this as interpolation so code snippets are typically lightweight in that they result in changes to javascript state variables while html snippets are typically more heavyweight because they result in changes to the html dom but ultimately snippets provide the dynamics within our html markup i.e is reactivity so i'm using these terms to have a concise distinction between these two use cases code snippets and html snippets so i'm a brand new spelt user and like many of you i think svelt is so cool it all began in 1969 when man first set foot on the moon well i guess that's not exactly true this is actually my tribute to rich harris's presentation entitled rethinking reactivity if you haven't seen it it's a must watch and you'll see the course the correlation to the moon landing in the first 30 seconds of the presentation well needless to say i began my career six years later and 20 plus years before there was a usable internet and so i'm probably the old guy in the room but i remember when netscape was introduced with this new javascript language in the mid-90s i was all in and subsequently i worked on a number of projects that promoted reactivity within our application without any frameworks i.e pure javascript and believe me that requires a lot of code and some good architecture to ensure that code is maintainable so i actually skipped right over the jquery phenomena which is an amazing library and is on right right into these new declarative component-based frameworks so coming from my background i'm never ceased to be amazed at how much you can do with so little code so svelt is merely i think taking the next progression or going to the next level in that it provides all the benefits of these declarative component approaches without the bloated in-memory runtime framework so why is spelt so cool well primarily i think it is its unique approach to reactivity other declarative frameworks are focused around component re-renders and your atmos trigger reactivity for example the set state function in react it's felt even though it is component based reactivity is somewhat independent of the component reactivity is triggered rather magically at any time in other words reactivity is simply baked right into the application i think this is accomplished by what this felt compiler is doing for us it actually does the following things it isolates the javascript snippets that provide our dynamics and it determines their dependencies of each one of those snippets it monitors those dependencies for staleness and it re-executes these snippets whenever the dependency is stale ultimately this has the effect of updating our dom fragments that is the spell compiler in a nutshell so being the curious fellow that i am i want to see svelte's reactivity firsthand we might be saying of course you can see the reactive results of your production app through the state that it's visualizing but that's not what i'm talking about i want to definitively determine when spell triggers the execution of my snippets in other words i want to see svelte reactivity in action in doing so i can become more grounded in cell philosophy and it can give me bit more insight on spelt heuristics such as dependency monitoring and reactive triggers and dom updates and overall give me a better appreciation for all this reactivity that's occurring automatically all around me and we may just discover some detail that we hadn't considered well at first glance this seems like a difficult task because stealth is in control of this not us so how can we accomplish this well it turns out we can use a common developer trick to logically or a console.log prefix to each of our snippets so here's our original html markup with the production of expressions in these html snippets and then the second section shows uh what it looks like if we add the diagnostic logging probes so console.log actually returns nothing so because that's undefined the logically or expression is going to unconditionally execute the production expression and so the end result is we have the same result with the addition of the logs added to our console log so as an example if the phone number changes you're going to find phone section fired in the logs and that's based on this console.log within that expression so let's add diagnostic logs to our greet user component so you can see here that i've set up a series of probes which are just functions just to kind of make it a little more concise uh in the actual logical or expression and then down here we're actually monitoring them so i'm putting the probes in logically oring them appropriately so it's important to use a unique text within the logs so you can correlate which text came is associated to which probe so let's look at the demo repel of this version of greet user so the rebel actually allows you to select different versions of the greet user you can do that right here so i'm going to select the version with reflexive diagnostic logs and so i'm going to bring up the console log so you can see it and so now if we make changes to our user we're going to see that actually fired down here in the log so you can see the name section was fired and the phone section was fired so that's pretty cool and we can also change the long distance characteristic and you can see the appropriate firing that occurred so that's pretty cool for the first time we can now definitively determine when svelt has executed our html snippets well logs are great but depending on how many probes we have it may be tedious to correlate them to our snippets it'd be nice if there was a way that we could actually see spell's reactivity right in our application so here's a simple utility called reflective counter it's actually a reflective store that maintains a count of every time a snippet is executed in this rudimentary form it is a basically a simple counter however its api is tailored to be used as a reflective monitor so you can see here that we're actually creating a writable store and it has a single value which is a counter and the what is returning is a custom store and it has the monitor function which is actually updating the um the internal counter every time it's executed so the usage of this is both in monitoring and so it's very similar to our diagnostic logging probes where you have a logical or expression but we're using the monitor method in this and then in addition we're going to actually report the counts in our code or within our html so you can see here that i'm actually displaying the count of that particular probe and i've actually put this in a mark html element to actually highlight the fact that it's not production rendering it's a diagnostic so let's add advanced diagnostics to our greet user component so here you can see that we are doing a setup uh and it's very similar to our logging probes except we're using the reflective counters for the probes and then we're also doing the monitoring very similar to the logging probes as well with the logical or but in addition we're also reporting the results of these uh using the uh mark html element with the value of the number of times that particular probe has been executed so let's look at this in our reple so to see this you want to actually select the with advanced on-screen diagnostics probe and so there you can see that we actually have in addition the yellow highlights that's showing the reflexive count so if i update the name and update the phone extension let's say then we'll actually on the fly see the counts update so let's change this to a long distance phone number and apply the change and see the reflection right on our page so this is great our components reactivity is now visible directly on our page so i don't know if you have noticed it or not but there's actually some unexpected results from these probes and that is that html snippets are re-executed even when their state did not change ouch so you can see this by let's go back to our rebel you can see this by just changing one value i'm just going to change the name and apply change and see that all of the snippets re-executed in fact you can even just click on apply change by itself and all the snippets are re-executed now as a sidebar i realize that i can optimize optimize the user store to prevent this last scenario but for the purposes of this discussion it better highlights the points that we are driving at so this is really an unexpected hit what is going on the answer has to do with stealth's dependency monitoring as it turns out there's a big difference in how monitors objects versus primitives objects trigger reactivity per the entire object not the individual content in other words the stainless granularity is the object itself and this is what we were seeing in our demo on the other hand primitives trigger reactivity only when the value changes based on identity semantics so i have a second repel that demonstrates this let's look at it now so back on your resources link if you click on the link that says reactive triggers it'll bring up that rebel and i'm going to go ahead and maximize it as well so this is a pretty simple rebel it basically has two state variables one is a primitive called prim and one is an object called my object that contains a couple of primitives within the object itself so the rebel if you look at it is uh implemented in such a way that the button label is actually the expression that is executed so it's pretty obvious what you're doing by clicking the button and so i'm displaying both the primitive and the two object properties up at the top and it is also orchestrated with the reactive counters that you can tell what's happening there so as an example if i click on the primitive plus plus i'm actually adding a value to the primitive you can see that its reflexive count was increased as well as decrease also bumps up the count as well if i change the value to a hard coded 1945 you can see that it initially updated the count but if i do it again it's not going to consider its stale because the primitive value has not changed now that in contrast to how objects are handled if i just basically update uh the food property of the object then you'll notice that both the food property and the bar property reflects because again svelte is considering the entire object as being the dependent granularity um so again you can see that i'm updating the bar reference even though the only thing that changed was foo and here's an example of changing the entire object to a different reference has the same effect changing the foo property to a hard code in 1945 still updates uh both reflexive counters because again svelte is considered that object has been changed and even assigning the object to itself has that same effect so this is a very interesting tidbit while it's probably what you would expect my knowledge this is not mentioned in the spell docs so back to our re-render analysis the elephant in the room is the question is felt producing redundant and unnecessary re-renders of our dom fragments remember dom updates are expensive is this really true or is there more going on under the covers well a spoiler alert felt does in fact optimize this and we're going to discuss this a bit later but for now i'm going to take you through the same progression that i took when i came to this conclusion so it turns out there are app specific techniques by which we can tweak uh the reactivity so how can we impact this after all svelt is the one who's in control of executing our html snippets how can we alter this so the basic thrust of what we're about to do is to move reflectivity from html snippets to code snippets remember that code snippets have less overhead because we're merely changing the javascript state variables we can take that in combination with what we learned about stainless monitoring and do something with that the first one is applying a finer grain dependency management remember our discussion of dependency management and that primitive types also include identity semantics what if we normalized our reference state into primitive types so here is our user component that is dereferencing the user objects within the html snippets and here is the after we have normalized it into primitive types so you can see that we've moved uh into the code snippet a reactive statement that basically is denormalizing the user into a primitive types name and phone number and then we're referencing those primitive types directly in our html snippet so let's look at this in our reply and in this particular version we need to select the one with primitive normalization so now if we change just one of the values jenny the name itself you can see that only the name reflexed and if we changed the phone number only the phone number will reflect and if we apply change with with uh without any changes then uh no reflection is occurring you may also notice that the css snippet also executes uh whenever the phone number changes even though the uh the long distance distinction hasn't changed so that's going to be the topic of our next discussion so the second thing that we can do is normalize conditional logic into primitive types so here is our code that contains conditional logic in our html snippets and here is the after version where we have normalized this resolving the css class name within a primitive string so we've moved up here to a primitive classes string that's actually referenced within our html snippet so let's look at this in our rebel so this is the last version of our greet user that is entitled with variations in code so now if we change our phone number without changing the long distance classification only the actual phone number snippet has been updated but if we change our classification to be from long distance to local call then both the css class as well as the phone number itself snippets have changed so we've now refined the execution of our html snippets to only fire when the dom needs to change okay let's come back to our earlier million dollar question and that is is spelt producing redundant and unnecessary re-renders of our dom fragments it occurred to me that just because phelp decided to re-execute my html snippet doesn't necessarily mean that it resulted in a dom update could it be that spell further optimizes this process by ensuring the result of an html snippet actually changed if you think about it this makes a lot of sense for svelte to do and there are two reasons which we have already seen the first one is that spells uh the cell's overly broad dependency granularity and this is the difference between objects and primitives that we discussed previously the second one is that html snippets can return the same result even when the dependencies legitimately change and we saw this in our long distance css styling of the phone numbers so how can we verify this well one way to do it is through a very simple debugging session so let's go over to our rebel and i'm going to base this one off of the second version of our greet user component and that's the one that begins with gu2 and so i'm actually going to put a debugging probe directly in one of our diagnostic probes so i'm going to make this a full function where i can have multiple lines and i'm simply going to put a debugger pro right in my code so we want to be executing that second version so let's bring up the debugger now the theory is when i break in this point let's actually i'm just going to actually click on the apply change button and so now we're in the debugger probe that i set and so we're in our html snippet and the theory is that if i step up one level i should be in this felt realm because felt is the one that's actually executing my html snippet so let's do that i'm going to step up one level and sure enough here we are uh we are in some pretty cryptic looking code we've just executed line 492 or i mean sorry 942 and so um that's a pretty ugly looking statement it's a big conditional logic statement and if it's true it's going to set it's going to invoke a utility function called set data now my theory is that set data is what's actually updating the dom fragment so to prove that i want to set a breakpoint right on that set data and so i'm going to do that and now i'm just going to continue to run so at this point if i apply change without changing anything it's in my debugger probe here if i continue on it doesn't stop anywhere else but if i actually change the name and apply change here's my debugging probe and if i continue sure enough it has actually stopped it's getting ready to execute this set data function and so the theory is if i step over this function it should be actually updating the jenny to jenny o so let's try that i'm going to step over that statement and sure enough that set data is actually doing the dom update because the genio was updated so that's pretty cool we've now definitively determined that dom updates occur only when the content has actually changed so in looking at this code you can see that it actually has some app specific uh comments in it you can see there a reference to the dollar sign user it's looking at probe one in a comment here so it occurred to me that this could be this felt compiled code you know that tab that you're always afraid to click on so let's look at that a little further so if i go into this js output tab and look around a bit widen it out scroll down a little bit pretty cryptic looking variable names look there is the actual code that we were in uh with that cryptic uh conditional statement and the set data so i'm not going to go into a detailed analysis of this code within the presentation i actually do that in the article if you want to read that section but suffice to say that we've actually proven that spelt is very efficient in what it's doing is dom updates occur only when the content has actually changed so knowing what we know now is it really necessary for an app to apply the optimizations that we went through earlier well to be honest most likely those techniques will not significantly impact your app's performance in some cases we're just moving an optimization that's felt was already doing into the application realm however there are cases where our newfound knowledge can be useful consider this what if the discrepancy count between reflection and re-render were large where we were needlessly re-executing an html snippet many times with the same output our what if the overhead of executing this html snippet were extremely high and what if the same html snippet were needed in multiple places in our html well the bottom line is we have a better understanding of the finder characteristics of reactivity so knowing these details can give you an advantage when you hit those edge cases so here is an extra credit exercise in its current form the reflective counter is providing us a reflexive count uh the html snippet execution count can you think of a way to enhance this to provide both reflexive counts and re-render counts that is of the dom updates well here's a really big hint our invocation is going to change from a prefixed logical or expression to a function that actually is passed the production expression as a parameter so if you think about it the monitor now has access to the actual production expression and so it can actually execute that expression and compare it to the previous cache value that was returned from that expression and then it can actually maintain two counters one for uh the reflexive count and one for the re-render count i won't go through the complete solution i'll leave that up to you but there is actually a hidden easter egg within our rebel that reveals the solution so let's take a quick peek at that in the upper section of our original rebel you'll find an aleutian say link which is pig latin for solution and as an aside also makes our rebel bilingual well sort of so if you click on that particular link it'll bring up another uh rebel that is the extra credit solution and there you can actually find the enhanced uh reflexive counter utility but if we just look at it from a usage perspective we can go through all the same characteristics let's uh go with the advanced on-screen diagnostics and you can see that the diagnostics here have for every probe it has two counters a reflexive counter and a re-render counter so if we in this state if we just do our apply changes you can see that the reflexive counter is being bumped up but the re-render counter is not and so if we go into the other solutions that we walk through the primitive normalization applying the change there the reflexive or the re-render doesn't update if we actually change a value let's say the extension on the phone number and apply change you can see that the phone number expression both reflects and updated the dom whereas the class only reflects it did not update the dom for the new classification if we change the phone number to be a long distance let's go ahead and reset these counters here and do the apply change you can see that both the classification and the phone number itself updated both in the reflexive and the re-render so that's pretty cool so what have we learned well we've learned that we can visualize felt's reactivity right in our app either through diagnostic logs or the reflective counter which is a new utility that you have for your utility belt and we've learned that there's a big distinction between primitives and objects when it comes to dependency management we've also learned that svelte's reflexivity is very efficient in that it's dom updates occur only when the content has actually changed and that we have learned that your app can fine-tune reactivity uh as needed okay then before we wrap it up i'd like to give a big shout out to rich harris and all the core contributors for making svelt such an awesome product you've truly changed the landscape of web development and we all appreciate your time and effort as an aside you guys should really consider recruiting big bird on your team i have it on good authority that he would be a most excellent contributor to the spell code base to find out why you'll need to read the corresponding article that spawned this whole presentation it's bitly responsive svelt how do you like that shameless plug well that's about all i have i hope you enjoyed this little journey and learned something as well if you have questions or comments i can be reached at the following email and my twitter account is also open for direct messages so thanks for watching and enjoy the rest of the upcoming sessions
Info
Channel: Svelte Society
Views: 1,627
Rating: undefined out of 5
Keywords: Svelte, Javascript, Web development
Id: fvY1TAKNPgY
Channel Id: undefined
Length: 29min 28sec (1768 seconds)
Published: Thu Nov 25 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.