React's Magic Compiler You Can't Use (Yet)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'll be honest I kind of forgot about react forget it's silly to say that but it kind of disappeared it was announced all the way back in 2021 as part of react comp and I've only heard about it once or twice since in fact the dev that was leading the project originally has since left meta this had me pretty scared that react forget might have truly been forgotten thankfully it hasn't been and some of the stuff I've seen recently has me really excited specifically this tweet from Sebastian that spotted it on Instagram yes the react team is actually using forget in production now this single fact makes me so excited about forget again because I don't have any inside info for once I'm actually going to do a little more speculation than usual and we're going to try to dig into how react forgets being used and what a future looks like where we don't have to memorize everything ourselves without further Ado let's see what we've discovered and what exists because all we have are a few conference talks let's dive in first I think it's important that we build some context from the original presentation once again this was in December of 2021 over 2 years ago but it's very important context I want to make sure we don't forget the original promise of react with without memo if you want to watch the whole video I'll make sure it's linked in the description we're just going to skim through the important [Music] bits looks reasonable Jean hopefully I'm pronouncing his name correctly phenomenal developer really sad that he's no longer working on react forget because he clearly knew what he was talking about with this project it does seem to be in good hands though so hey what's up folks I'm Shin I'm a software engineer at meta so today I want to talk about react and memorization here I have yet another to-do list you know as JavaScript developers we just really really love to-do list who here love to-do list I want to see some ones in chat who here has built a to-do list to demo something On's in chat if you built a to-do list to demo something before this everyone's goto yeah I feel like there for every developer there's at least two to-do list apps so we enjoy the simplicity of the react code here on two when we open up the daa tools and we realize weever we add it to do or tle it to do all the add to-do is actually getting rendered as well this is the thing most people complain about with react in case you're not already familiar because react aggressively renders things whenever a parent node changes anything you end up with rendering occurring on a lot of things so in this case when you add a new to-do all of the other to-dos are getting rendered and even when you toggle one they're all getting rendered they're not reappearing on the Dom it's not recreating the node on the Dom but the virtual Dom which binds things between the react World and the the real world in your browser that has to validate at every step hey did these things change and if you want to opt out of that that's a thing you have to do manually through processes like memoization I'm going to skip a little bit again I highly recommend watching this whole video if you haven't already it's incredible it's a great 12-minute watch what we see here is a more complex example where you also have have a Color Picker where you can pick a color in the same window and whenever you drag your mouse around this it causes everything to render if you don't want that to happen if you want those elements to stay static I'll play it a bit feels much more Snappy 200 times is in pick a color to theme the user interface if we try this code out it works but the app feels pretty laggy and slow when we're picking colors and the reason is that changing theme color will reender the Blazing to leas and to lease which will eventually call a get a fer function again and again if we pay attention to the zoomed in number here it's been executed about 200 times yeah so what you do instead is you throw get filtered into a memo so you don't have to recall the specific function over and over again just because something else changed so long as to-dos and visibility haven't changed your filtered elements are going to stay the same fix this we can wrap the getter call with so this is the user experience we won y it shows that this get filtered gets called way less but it still has to render all of these elements if we skim in a little bit further this is but where things start to get chaotic with react even with this relatively simple example the relationship between all of these things and I love how the arrows are used here to show it once you're doing all of this memorization the very like top to bottom readable nature of react code gets a little bit lost and I I feel like that sucks it's one of the things that makes react code painful and this is when you stop losing a lot of the value of react when you run into these crazy memorization cases there are ways to architect things where it's not as bad like memorizing at different levels and such but it does kind of suck and it makes the control flow of your react components way more complex' be really nice if you could write your react components in the simple linear way that the first example was written without having the performance issues that are inherent to that style of writing and this is the compromise that they're talking about here where if you don't use memo the developer experience is great but you're going to start running into lag that my face is covering the word ux in the corner there so if you we're curious the DX is great without memo but once you're optimizing all the time it gets a little more painful and then ux quickly can get slow if you're not optimizing but the user experience way better if you do turn that this economics versus performance issue it's just so intrinsic to the model of react and doesn't look like we can optimize maybe we should use template rather than jsx but we just really like the expressivity of jsx or maybe we should go back to class or start with mutating stuff so it's easier to track what we think is there something that has been missing here today I want to give you you a sneak peek of some research that we've been doing that we think could solve this problem for the future of react to talk about this we need to rethink How We Do memorization like he says for the future he me when he said for the future of react he me when he said for the future of react tier he meant it because this took over 2 years for us to even start seeing it in the wild much less have access to it and look at this code again without aut memorization hook oh it's so pretty why can't code always be this simple the end of the day the to-do list is just a function that takes inputs from props and states and generate outputs such as UI and effects and the need to create intermediate value such as fter and handle change to do that to help with understanding we can also visual visualiz the dependency graph this way of visualizing what variables affect what things in the chain of dependencies here is such a good visualization and ideally your code should be as simple as this but once you have complex back and forth things get a lot more complex skipping a little bit again watch the whole video if you want to better understand the depth of this stuff the core Point here that I want to focus in on is the use of these magic variables that get updated using this memo cache the goal here is to automatically via a compiler wrap any code that could take time to execute and only execute it when its dependencies update it's kind of like signals such as what we see in solid and recently in angular but it's happening at a compiler level so the code you write is still very simple and procedural but the output is really performant and well optimized and the magic piece here is this memo cache where every value where it's defined gets a key in your cache and falls back on that when none of the dependent values have changed this can get even more complex once you have sub elements in children that do or don't need to be rendered and this lets you avoid memoizing components entirely by breaking out those children and referencing them from the memo cache if things haven't changed and also updating the cache if they have this lets you skip a lot of steps in just return an existing result instead of having to instead of having to recreate that result every time something changes this is really exciting stuff but where has it gone since like why haven't we heard about this for 2 years well we just recently have this is from react Advance London awesome that our good friend Jack Harrington was the one who streamed this which is dope all right so I'm Joe I'm an engineer on the react team at meta and in this talk we'd like to share our vision for client side react development specifically I'm talking about react forget uh forget is a compiler that we've built at meta that automatically memorizes your components and hooks so if you were hoping for us to be open sourcing forget today I am sorry already to disappoint you uh but we've made a lot of progress and we're excited to share more about that with you today uh so I'm going to be talking about what our vision is what forget is and how it fits into that Vision uh and then mof is going to come up and talk about our progress shipping forget at meta so to understand our vision for react it helps to look at some code here I'm showing a simplified version of an internal component from meta this component takes a heading a list of video vide and a filter and then it renders The Heading and list of videos that match that filter you can imagine the real component is more complicated the you know the filters actually State Etc you know but it's kind of simplified version so personally I think there's a lot to like about this code it's a small clear concise component it uses plain JavaScript values arrays uh we use standard JavaScript syntax if else for conditionals a for Loop for iteration no if else we're a fan of that is just an if with an early return if else isn't great just standard if statements a plus right we don't need to learn something new this is just the JavaScript that we already know use the platform so in a lot of ways this is react at its best UI as a simple function of data there's really only one potential problem with this code if we were to ship this as is we might see that parts of our app uh rerender unnecessarily and that can affect performance slowing things down so let's see an example of how that can happen imagine that our component rerenders but only the heading has actually changed when the component rerenders it passes that new heading down to The Heading component which updates as we'd expect my cat is screaming so much that I'm like getting a headache from it so I know you guys can't hear him but it is stressing me out I will be back in less than 2 minutes I am so sorry I will let the video keep playing so you have something to watch while I am gone but that's all that that's not all that happens by default when our component rerenders the entire component reruns this entire function reruns that means we create a new filtered videos uh list and then we pass that to video list which then also rerenders all the way down the tree and this will happen all the way down the tree even though nothing meaningfully changed about the videos to address this we can use two react apis use memo and react. memo so here I've applied use memo to the logic for filtering the videos the array at the bottom here tells react to only recompute filtered videos if the videos or filter values have actually changed so now if only the heading changes we don't recompute the list of filtered videos great but that's not quite enough because even though we're passing the same filtered videos down to the the video list component by default react will still rerender a component even if its props Chang important to opt out of that we wrap the component with react. memo so now we get the expected performance with these two changes now when heading changes we won't have to update the video list component great and if you judiciously apply react uh use memo use callback which I is for kind of the the call back version of used memo uh and then react. memo if you use them consistently throughout your code base you can achieve really good performance with react and a lot of other presenters have talked about that earlier we found that generally when applications do have a performance problem it's because of this kind of missing memorization and it can be fixed by just you know adding add add adding this back but this memorization has made our original code a lot less concise and clear I probably should have called this out a few places by now but I I want to really emphasize this point there are not many projects asides of react that will just come out and say something this bold where they have a solution to the problem but it's not a good enough developer experience so they're going to put years of work into working around it this is a bold statement and I wish we saw more of this from developers I think spelt for example does a really good job of this too rich Harris has come out and said outright that the way they did state in spelt was not good enough for large applications in complex State Management and as such the rethought state from scratch is a more hybrid signals based approach in order to make scalable State Management in felt possible and I love when big projects are down to be this type of honest and say yeah our solution just wasn't good enough yet we're no longer simply describing what the UI should be showing we're having to tell react how to process our code that's kind of losing some of the original idea of react right to Clara of rendering but now we're having to go into the the how and then our code reviews become about whether we've memorized correctly whether we memorize too little too much we get blog posts arguing that you should memorize everything blog posts saying that you shouldn't memorize it all you don't need memorization and the thing is that both of them are kind of right because it all depends on the context this code the original code here might be fine in a lot of apps but for other apps they might run into a performance problem but really with this memorization our code gets cluttered up with extra logic we're not just focusing on the core product experience we're focused on again how to achieve it it makes our code harder to read and harder to change so in a sense use memo is a compromise we sacrifice some of the clean concise original logic in exchange for better performance but why do we need to make this compromise at all well let's go back to the code the reason we started down this whole path was that we needed to use use memo to tell react that the video list doesn't depend upon heading but we're all developers we know JavaScript right we've already hold react that video list doesn't depend upon the heading in fact we've used a very well specified format of instructions that computers already understand to tell react that information it's called JavaScript you already know it I love that I was wondering what he was going to say there because there's a lot of things that specify this but because video list isn't a child of Heading Video list is not dependent on heading like it's obvious to us but the compiler doesn't know that and as such when one changes it has to render both and that's like a a pretty obvious design flaw that has allowed us to WR react as efficiently as we have and made it such a simple Paradigm but it also causes these types of problems that react forgets hoping to solve so why do we have to tell react again why do we have to also add in our used memo to tell react oh this doesn't depend upon these values what if react could figure that out automatically and better yet what if react could figure this out at build time when you compile your app and didn't you didn't need to pay a runtime cost this is a recurring theme of notice with recent react and meta JavaScript tools both stylex and react forget have leaned heavily into this idea of build steps to prevent user experience regressions even server components and server actions some amount are using build steps to create better user experiences really cool stuff and I like the idea of using compilers and build steps to make better outputs for a while react avoided this because react is just JavaScript and while I do think it's important in the sense that the code you're writing is just JavaScript this also comes at a cost that cost is that these more complex behaviors and finding solutions to these performance issues is difficult and they're trying to find a balance here where it is still JavaScript and more importantly you can still import any existing JavaScript code or JavaScript library and it behaves as expected but react can compile a better path out of it it's a really interesting idea rather than do some fancy Dynamic tracking of values at run runtime we could just figure this out ahead of time and avoid the runtime overhead so that's the goal of react forget it's the code name for this compiler that we built at meta to automatically memorize react Hooks and components let's let's developers write code without needing to manually memorize while achieving the same performance as a well memorized uh app and in some cases even faster so to make that really concrete react forget lets you write the original code I started with with no memorization while getting performance at least as good as the manually memorized version here moving this so you can see again that manually version is exporting the default react. memo wrapper of video list so forget really helps in two ways it simplifies the developer experience because developers don't need to think about memoization and it helps ensure that we're achieving Optimal Performance by default so let's take a look let's see will the swiping actually work all right hey okay uh oh wait hang on I forgot I got to grab the code let's grab that code where was it it's here somewhere I'm exit out let me grab the code got to make sure we get the right code that actually grabbing the code from the slide that's great over here so what I'm showing you here is our uh internal compiler playground I got some example code in there I I'll swap that out for anyone who's really curious about forget you might want to look at that code but we we'll go we'll look at this code nope oh I messed up I might want to go back and dig into that in a bit live demos gotta love it all right there we go so this is our internal compiler playround this is meant for us to use when we're developing the compiler you don't need to understand you know this this is a tool for us not for the typical react developer I'm just showing it here just as a way to demonstrate the compiler so again I pasted in the original code we started with right um and so this on the this is the input and then the this JS panel over here is showing the output from the compiler so let me zoom in a little bit to make sure youall can read that all right I like the dollar sign is use memo cache I'm sure that's not going to have conflict in any code base the output from the compiler so let me zoom in a little bit to make sure you all can read that all right that's probably good enough all right okay let me scroll sorry I'm like it's hard for me to see exactly way you can see all right yeah all right okay cool so uh forget now remember there was no memorization here but forget has figured out that it should memorize filtered videos uh this block is equivalent to a used memo so highlight all this this section here is all about memorizing uh filtered videos so what does it do so first it checks to see if videos or filter have changed forget figured out the dependencies automatically for this for for this value and then it takes the code that we wrote and just moves it inside right it's not reformatting our code it's keeping the the same code that we wrote um with a for Loop and an if statement and just moving it inside this memorization we call it a memorization block um and you know we have Source maps to preserve you know the source locations for this so so that all works uh so then after Computing the new value forget saves what the inputs were so we can compare them next time and then it saves the output right it saves the videos so now imagine that we render and and only the heading has changed well we check have videos and filter changed no they haven't so we go to the else block and we grab the the previously computed value so the net result is just like use memo right it's it's the same exact Behavior just a slightly more efficient implementation um instead of having to create a function expression which allocates memory not great um we can avoid that and just do a regular if statement uh instead of allocating an array for the dependencies and dynamically iterating them we're using static JavaScript code which can be optimized by the JavaScript engine but forget is actually memorizing even more right this is this is more memorization than we thought to do uh so you can see a bunch of stuff here let me scroll down and pick just one example so here's uh the video list so forget is actually memorizing the jsx element itself as long as filter videos hasn't changed we don't recreate the element and what this allows react to do is basically the same thing as as a react. memo so as long as filtered vide doesn't change we'll we'll uh put this exact same jsx element into our output and re when react gets to it it sees oh the jsx element at this spot was exactly the same I can skip rendering obviously if there's a state change it has to re render but uh in general just like react. memo uh and so this is where forget can memoize even wait I I just had to notice T3 spotted I think it's fair to say that react forgets officially supporting T3 more than a developer would typically think to do so okay so let's go back over to the presentation pick up here presenter view I wanted to see more of the code those are my notes all right and I gotta find my where was I okay uh yeah yeah okay that's all the other stuff all right okay so so that's kind of looks pretty magical forget just figured out what to memorize how does it actually work so if you're not familiar with programming language Theory or compiler Design This may feel pretty magical um but it's not magic it's computer science uh forget is a low-level compiler for react it's really specifically designed for react um and by low level I'm referring to the fact that forget builds a detailed you know internal representation of your code it understands the rules of JavaScript and it understands the rules of react and it can use those to figure out what parts of your of your application to memorize uh and these type these optimizations are things that are typically done by you know traditional uh you know compilers for languages like C++ or rust um in addition to some novel analysis that we came up with so that kind of together with understanding the rules of JavaScript and react we can kind of carve out a safe space for us to apply these optim one of the main reasons react native is so much better than any other solution is that they poured an absolute shitload of effort into making it possible by building all necessary bindings for both Android and iOS and in the future building them for other platforms and working with other companies to do it they positioned react native so well that Alternatives built for other languages like the I forgot the name of the Vue one but there was a Vue react native equivalent it was literally just calling react native components under the hood because it was so powerful if they're doing what I think they're doing here and it comes out in a good enough State I would expect to see a lot of other people copying this homework so by earlier this year we'd established a solid foundation for the compiler Okay so so this is in 2023 so by the beginning of 2023 they had a solid idea of what the compiler would do but it took over a year for them to get to that point from the first presentation about it that's actually a really interesting detail to have just snagged and we began a series of production experiments we used forget on increasingly complex and high traffic surfaces to tell you more about that part of the story I'll hand things over to [Applause] mang hey everyone uh wow I'm M Zen I'm I will say the little bit of inside info I have on react forget everything I've heard is that m is incredible in an absolute Legend This is my first time hearing anything from her so I'm actually really excited engineer on reacts and I've been working on forget since last June it is so exciting to be here and finally be able to talk about this project this year we took the forget compiler from an ambitious proof of concept to something that is now running on two major meta products that's right one of which is Instagram by the way you can now find this project out in the wild I mean some folks in the audience may have already used forget compiled apps our work is not quite done but I'm so proud of how far we've come and I'd really like to share with you our journey so far so about eight months ago we felt that forget was finally complete enough to start tripping at meta we had painstakingly walked over every Edge we could find in JavaScript and you know there's a lot of them um our GitHub repo held over half a thousand tests and each test checked that we were correctly analyzing and memorizing every permutation of valid react functions we could think of we had really crafted this compiler with Care iterating on its design with a lot of code samples from complex meta products and we were finally ready for our next step understanding how this compiler performs on real apps written by real engineers and on real devices does fret actually do what it's set out to do make any react app it touches better introducing our first collaborator Quest Store the app store for Quest VR devices Quest store has a large code base written in react native our primary goal was to free its developers from needing to worry about menu memorization I don't know if it was public info that the quest store was in react native until this I'm actually not sure so that's a detail I've known for a little bit and thought I couldn't talk about but that's really cool that that's now out there there's a lot of stuff in the quest ecosystem and in VR from The Meta side that was written with react native and they've used it as a test bed for a ton of really cool and I had no idea they were using forget in that and that is dope that is so cool to hear shout out to all the people working on that there's some really cool people doing cool stuff there while we were hopeful we thought our chances of actually improving performance were low Quest store engineers said had already spent a lot of time profiling in hand optimizing this app with used memo and Ed callback needless to say we also had to move with a lot of caution when integrating foret here during roll out every single test would run twice once using forget compiled code once without forgetting the pipeline at all soone as is the quest store in VR yes the quest store is a VR app you use like in virtual reality but this is actually a really cool point that I had actually thought about this before in terms of the dog fooding of react forget meta's inherently going to have some of the best react developers in the world that's just obvious that they're the creators of react and they have the core react team there to ask any questions if anyone's going to be writing react in a performant way it is meta so seeing if their compiler cannot just beat out an average react Dev or a below average one like myself rather seeing if it can beat out these really talented devs working at meta that's really cool and I'm excited to see how this performs compared to their selfand optimized code we also partnered with QA testers and even data scientists to check that we weren't changing product Behavior this is the product Details page on Quest store it shows uh well all the details of our product on the store this page is pretty complex as you can see there's five or six sections um that you can scroll or click through each section like gallery or about has its own complex UI La logic forget has now been entirely rolled out on this page meaning meaning meaning that every uh react component and hook is compiled by the forget compiler after enabling compulation we thought that page interactions felt a bit more responsive I was skeptical about this I mean that sounds almost too good to be true so to understand if forget actually helped we use the react profiler to record the re-rendering work following a click on the left Naf bar like clicking from gallery to reviews so this is the work done by one react render following the click before we turn on forget for anyone not already familiar with the react profiler this entire diagram shows a react component tree with each individual box representing a react component green boxes show components that were invoked during this reender gray boxes represent components that were not called as you can see many boxes are green here which means that this particular render required a lot of work um but if you remember from earlier a lot of Engineers had already tried to optimize this app so the gray boxes and those sub trees that you see is what they were a the work that they were able to save react now let's take a look at the forget compiled version to see if anything changes as a hint um keep your eyes on the components outlined in red okay ready damn that's a lot less work you have to [Applause] do so half of those over half of those rendered components uh kind of disappeared this means that rendering now requires much less work when using compiler optimized react awesome but I mean what was the difference we compared existing memorization in the code base with forgets output and it turns out compilers can do memorization pretty well often even better than hand optimized code so let's take a look at some simplified code from this page to see how so actually I'm going to full sizee that screen I think it's flashing and I'm going to click through a lot of slides hopefully that's better so this is some logic from an extremely strict down version of the media preview um component on this page it looks like a lot of code still so let's walk through it together media preview receives a media object which it renders if the media object represents a video we return a video card um we also a use call back don't need to go too deep in specific examples forget it by the way our compiler don't need to worry about making mistakes like forgetting a use call back they can just forget it by the way our compiler then if benefit we saw major improvements in interaction responsiveness what in production let's see are these numbers interestingly we also measured loading metrics like visual completion to be faster it turns out that the initial load of this page requires multiple reenders to initialize things like video state by memorizing according to its fine Grand understanding of reactivity forget reduce the amount of done work done during R render with forget R renders completed faster so that means we got our answer right forget is done and we automatically make our react apps better all the time not quite forget success here helped us gain a lot of confidence in its memorization strategy but we know that fast R renders are just one piece of what makes a performant UI fine grain memorization is great for interactivity but if a compiler memorizes too much it may adversely affect other app metrics we had a lot of ideas for how we can improve the compound output but first we needed more data instagram.com is a react app built for the web and presents a different set of challenges from Quest store didn't know that this was actually publicly confirmed already cool wied code translates directly to an increase in bundle size which may in turn increase startup time we also wanted to know if caching value vales created during render negatively affects memory constrained devices like older Android models and of course we hope that forget could make developers lives easier if you have visited instagram.com in the past month you might have used forget that's right forget is on Instagram Pages like profile in production than she was expecting Applause here and this this is Applause worthy like building a new comp piler for something as big as Instagram is pretty dope as you can see here so we're already gaining an early understanding of how forget affects metrics other than rendering speed on the profile page we measured less than a 1% increase in compressed code size and similar changes in retained memory in production we have so far seen no increase in memory related crashes or start out time instead we again saw slight improvements in visual completion okay those numbers are nuts they saw a 1% bump in the size of the like JavaScript output that's being sent to the user and no meaningful change in memory usage or startup times that's huge just like our results from Quest store oh and there's something I forgot to mention about all of this we used forget to achieve these results without needing to make any changes to product code forget can handle almost all JavaScript syntax we actually seen in use it current that's n that no product code was changed they just ran it through the compiler and it worked godamn understands 95% of components on instagram.com and we're working to increase that even further so what's left the performance wins we have seen from forget have exceeded our initial expectations however on the react team we have a really high bar for releasing products forget is not an exception here our Milestones are to First build a minimal proof of concept then a version that has almost all the necessary features carefully roll out to a small number of products getting feedback and iterating on our design we're at this stage now by the way um we're working to understand forgets impact on a pretty set diverse set of real real world apps and we're really confident about major design decisions but might need to make further adjustments and optimizations depending on data our next step is to scale up until forget is used everywhere at meta refining on small details finally when we have stress tested and iterated enough we release while we still have some work ahead of us we strongly believe that forget will help react achieve its Vision an ergonomic developer experience paired with great performance thank you that was huge I'm hyped also that the transparency here like it's nice that they're coming out and saying this directly like we are going to do these steps we're going to make it work internally and then we will release it good to hear this officially let's dig in gotta love that nice low res interesting this is just testing with a hook okay use Fu Con X is an array X push Y is X Y push oh that's a fun Edge case those the same array instance you define X let inputs in on chain use cach value nothing too surprising there I was hoping for some more interesting how it behaves stuff there yeah that was an awesome talk huge shout out to the team both Joe and M you're killing it I'm really Happ the progress on react forget I know this has been quite the journey to get it to this point and I know a lot of y'all are skeptical if it'll ever happen but if they're running it on Instagram's reduction code it's closer than we think and while it has been 2 years I do think we're close in 2024 might be the last year we have to write memos ourselves and react this is a very very exciting change and I this is what do you guys think about react forget this is a bit of a chaotic video but there's some really cool stuff in it and I couldn't be more hyped I'll pin a video in the corner all about performant react code and why you shouldn't use memo if you don't need to and whatever is below it YouTube seems to think you're going to like appreciate youall as always I'll see you in the next one peace nerds
Info
Channel: Theo - t3․gg
Views: 63,904
Rating: undefined out of 5
Keywords: web development, full stack, typescript, javascript, react, programming, programmer, theo, t3 stack, t3, t3.gg, t3dotgg
Id: LL4V8CcEhIo
Channel Id: undefined
Length: 37min 16sec (2236 seconds)
Published: Fri Jan 12 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.