CHARLES MAX_WOOD: Hey everybody and welcome back to another episode of JavaScript Jabber. This week on our panel, we have Steve Edwards.
STEVE_EDWARDS: Hello from a very rainy Portland.
CHARLES MAX_WOOD: Dan Shapir.
DAN_SHAPPIR: Hi from a warm and sunny Tel Aviv where it's in the high seventies all the time.
STEVE_EDWARDS: Oh, I'm so jealous.
CHARLES MAX_WOOD: AJ O'Neill.
AJ_O’NEAL: Yo, yo, yo. Coming at you live from sad. That's seasonal affective disorder by the way.
CHARLES MAX_WOOD: Oh yeah. It's cold here. I'm Charles Max Wood from Top End Devs. And yeah, Dan, you scheduled this. I guess you got tired of us complaining about React.
DAN_SHAPPIR: Yeah, exactly. I kept hearing you guys talking about how React is kind of weird and strange and not understandable and really complicated and how you guys miss the browser DOM. And I thought that maybe it has to do with the fact that we're not doing it in the same with a certain lack of understanding of some of React's core principles. And in particular, how the core philosophy of React, you might say, and how it's enabled by virtual DOM, which is obviously different from the real DOM because it's virtual. So yeah, that's what I wanna talk about today.
Hey folks, this is Charles Max Wood from Top End Devs. And lately I've been working on actually building out Top End Devs. If you're interested, you can go to topendevs.com slash podcast a little bit more about my story about why I'm doing what I'm doing with Top End Devs, why I changed it from DevChat.TV to Top End Devs. But what I really want to get into is that I have decided that I'm going to build the platform that I always wished I had with DevChat.TV and I renamed it to Top End Devs because I want to give you the resources that are going to help you to build the career that you want. So whether you want to be an influencer in tech, whether you want to go and just max to go live a lifestyle with your family, your friends, or just traveling the world or whatever, I wanna give you the resources that are gonna help you do that. We're gonna have career and leadership resources in there, and we're gonna be giving you content on a regular basis to help you level up and max out your career. So go check it out at topendevs.com. If you sign up before my birthday, that's December 14th, if you sign up before my birthday, you can get 50% off the lifetime of your subscription. Once again, that's topendevs.com.
CHARLES MAX_WOOD: I just think that the front end frameworks are mostly overkill, but.
DAN_SHAPPIR: Oh yeah. For a lot of use cases that definitely are. I mean, if you're building a mostly static website, then all you really need is just HTML and CSS and have at it. But if you're building something that's more applicative, an actual web app, let's say, something that needs to be a single page application, which is a whole discussion in and of itself, I guess.
STEVE_EDWARDS: Yes, it is.
DAN_SHAPPIR: Then something like a, then a framework is really often the way to go because it just does a whole lot of heavy lifting for you.
AJ_O’NEAL: I do agree that if you don't use one, you'll build one yourself. And I do agree that most people don't document their code. So you'll be left with something that's worse than any alternative.
DAN_SHAPPIR: Oh yeah, for sure.
CHARLES MAX_WOOD: My take on it is mostly that if you're building like an interactive experience, then yeah, the frameworks make a lot of sense. If you're building an interface that's relatively simple, that yeah, is mostly static.
AJ_O’NEAL: A contact form, a static web page with marketing material and a contact form.
CHARLES MAX_WOOD: Right. For sure.
STEVE_EDWARDS: But I need the contact form to be dynamic in, in all that. So I really need a JavaScript framework for that.
AJ_O’NEAL: And so you have to convert the entire page that otherwise would render without JavaScript at all, because there's literally nothing JavaScript does into a react app that then takes for
CHARLES MAX_WOOD: anyway. But I'm, I'm, I am curious because, you know, I mean, I've talked to plenty of people about React. I've built some React native apps. There are definitely some things that I like about React. It's just that, yeah, when I'm reaching for, hey, I've got to build this out, typically I'm not building the kind of experience where I really need the kind of interactivity that React, Angular, and Vue tend to, I think, would push me to use one of those. But Dan, let's dive into this, because I really do want to talk about, okay, what is the React philosophy? I mean, what are we talking about here with how React works, how React thinks about the web and things like that, because a lot of people are using it. A lot of people like it. And though I disagree that they need to use it in every instance that they use it, there are reasons that people are using it. And so I think that's the value of diving into this. And I think there might be some pushback as far as, hey, that makes sense, but then it doesn't add up to using it here. But I think in other cases, it's going to also be I hadn't thought of that before, so maybe I would reach for it in this instance where I wouldn't have before. And so I'm kind of curious just to have the conversation and see where we wind up, right? Because I'm betting that, yeah, you're going to dive into some stuff that I wasn't aware of. I hope so.
DAN_SHAPPIR: Yeah, we talked about it before the show that a lot of people are probably using React because that's simply what they've been told in a boot camp or an online course that got them into web development. So that's effectively all they know. It's not that they chose React, it's that like React was chosen for them. And they don't even necessarily know or understand how the browser dom works and the event loop and stuff like that. And that's, that's really a shame because as you said, in a lot of cases, the, the built-in functionality in the browser is just good enough. In fact, it's, it's often better than good enough. It's exactly what you need. But there was a reason that React was built the way that it was. And the particular aspect of React that I wanted to dive into is the virtual DOM or the VDOM. And understanding the VDOM is fundamental to understanding the why and how of React. And in fact, the VDOM has been so successful that it has transcended React and has been adopted by other JavaScript frameworks. So for example, Vue uses virtual DOM. Mithril uses the VDOM and Preact, which is kind of an alternative react implementation, obviously uses the VDOM. And then on the other hand, you have other JavaScript frameworks that intentionally avoid using the VDOM. For example, Rich Harris, the creator of Svelte has called VDOM on record, pure overhead and effectively built Svelte in a way that it totally avoids using it. So there it cuts both ways. So I definitely think. It's worth a conversation.
AJ_O’NEAL: So with the, with the virtual DOM, my understanding is might be totally off base, but basically virtual DOM is a legacy of back from the jQuery days when the DOM wasn't efficient and we didn't have methods like insert adjacent HTML that were extremely performant and we didn't have request animation frame and we didn't have all of the performance tools baked into the DOM that now exist.
DAN_SHAPPIR: Well, I, that's not exactly the case in my opinion, at least. From my perspective, there are a couple of problems with direct DOM manipulation, and performance, past or present, is only one of them. So other issues with direct DOM manipulation, historically it has been browser compatibility. That one can be said to be effectively solved, especially now that everybody's dropping IE support. For example, I just learned that Lego announced that they're no longer supporting IE. Wix, by the way, treats...
AJ_O’NEAL: Lego, as in...
DAN_SHAPPIR: Yeah, the toy that you buy, Lego, they have a website, apparently a really cool one, and they used to support IE, and now they don't anymore. So hooray for them.
AJ_O’NEAL: I'm glad that they realized that people that work at banks and government facilities aren't their target customer.
STEVE_EDWARDS: When you said that Dan, I thought for a minute they weren't shipping it as part of their Lego toys the little computers
DAN_SHAPPIR: Yeah, and by the way wicks also we also treat Legos a legacy browser so if it kind of happens to work and great, but we actually put in a notification that we don't officially support it anymore
AJ_O’NEAL: Wait, Lego.
CHARLES MAX_WOOD: I think you just yeah, you just misspoke and said we don't support Oh, legacy browser, which is hilarious, but we all know what you meant.
DAN_SHAPPIR: Yeah. Yeah, I met I but historically, one reason for frameworks has been browser compatibility. And like I said, that one is gone. So what's left?
CHARLES MAX_WOOD: Well, that was initially the issue that jQuery was built to solve.
DAN_SHAPPIR: Oh yeah, for sure.
CHARLES MAX_WOOD: It was, well, we don't know if we call this, if it even exists, right? Cause Microsoft made their own APIs and then we're just going to wang it out there and hope that it works. And so jQuery made it consistent, which was so helpful.
DAN_SHAPPIR: And now the browser makers really do work hard in order to adhere to the standards and make sure that the standards are such that they can all adhere to them. Okay, so if not browser compatibility, what then? What are other problems with the browser DOM itself? So I think the key issue from my perspective with the browser DOM is that it's effectively mutable global state you essentially any part of the code can access any part of the DOM at any time. And you manipulate it using side effects. So, uh, you, you invoke a JavaScript function, that JavaScript function, I don't know, does a query selector, whatever finds the DOM node that it's looking for. And then manipulates it and then doesn't actually return anything from that function. It's all side effects. It's all globals. Any part of the code can access almost any part of the DOM. These days we have the shadow DOM and stuff like that, but effectively you can access any part of the DOM from anywhere. And if you can't do something, developers tend to do that thing. So you end up with code that really any part of the app might be doing anything with any part of the DOM at any time. There's no clear separation of concerns and this becomes especially problematic. If you start working with a synchronous code. So you start modifying some part of the DOM, then you await for some JSON to arrive via AJAX. And in the meantime, some other part of the application manipulates that same part of the DOM, and you end up in something that's totally inconsistent. So that's the key problem with the browser DOM. Now, obviously, if you're not doing very significant manipulations, or alternatively, if you're writing really clean code, then you can work around this imitation componentized, you want to have encode, you want to have encapsulation, you want to have separation of concerns, and generally avoid side effects.
CHARLES MAX_WOOD: Got you. Everyone but Steve will have this problem. Steve's code is perfect, but the rest of us.
DAN_SHAPPIR: Yeah, exactly. Also, the DOM tends to be complex. It's highly imperative. You end up with really verbose code to do some things that seem to be really simple. You create a DOM element and then you need to set the properties one by one and then append it.
AJ_O’NEAL: False information. Fake news. Fake news. You do not need to do that. That is how it's commonly done. But you do not need to do that because you can just construct a string and use insert adjacent. What is it? Insert adjacent HTML, insert adjacent element HTML. I forget what it is.
DAN_SHAPPIR: Yeah, I'll get to that in a bit. But yeah, that's, you know, kind of quote unquote cheating in that effectively you're treating an HTML string as a piece of code. It's a legitimate thing to do, but it also has its own risks and downsides.
AJ_O’NEAL: Wait, have you ever heard of React? I just want to point out the hypocrisy while we're here.
DAN_SHAPPIR: Okay. We'll get there. And another issue that I wanted to mention about direct DOM manipulation is that it's, it's really problematic to test, or at least it can be because you usually end up doing a whole lot of mocking in order to simulate the DOM so that you can modify that simulated DOM in order to, to test your code. And mocking is just not a lot of fun.
AJ_O’NEAL: Do you find, cause I just assume that the only way to test front end code in any...any way that brings real value is to use something like cyclists. I had, I had never considered that it would be desirable to try to test. Well, I mean, I, I don't really use react, but I'd never considered it to be desirable to try to test DOM manipulations without testing how the browser actually behaves because, well, because it's so likely to do something you didn't expect.
DAN_SHAPPIR: Well, again, if you do, if you properly break down your code into components and certain components are really small and you can actually implement it is something like pure functions that receive a state value and emit HTML in a way that you can check that HTML that the function provides as a return value, then why isn't that testable?
AJ_O’NEAL: Because as soon as you put that on the page, there's some other component that overlaps with it by a padding of 30 pixels and you can't click the X button or get rid of the ad or even subscribe to the news.
DAN_SHAPPIR: Yeah, that's the thing. I'm not, again, I'm not saying to avoid end-to-end tests. I'm just saying that those are extreme cases and you should definitely test for them. But in each and every component, there is a lot of value to unit tests, let's put it this way. And if you can actually unit test the front end, that's a huge benefit. Anyway, it's really up to you, but one of the problems with working with the browser DOM directly is that unit tests if you do want to implement them, become really difficult. Now, I have to point out that it actually used to be very simple because in the past, if we wanted just the HTML to be kind of not implemented as side effects of JavaScript functions, well, what we would do is just do it all server-side. And then you just make a function called quote unquote, which is an HTTP get or an HTTP post if you have parameters that you need to provide and you get the HTML back as a return value because it's the response. And that's it.
CHARLES MAX_WOOD: I still like that way of doing things, to be honest.
DAN_SHAPPIR: Well, that way is great. It's great when it works, but there are obviously some problems with it. I mean, if your network isn't great, or sometimes even if it's pretty good, it still can be relatively slow because of the network round trip. For some interactions, it's not a problem, but for other interactions, having that network round trip, you want to create some sort of interactive form that does things whenever you click or type something, for example, something like the Google smart search box. You won't do that by reloading the page on every button press. It just doesn't make sense. And another big issue with this approach is that you lose local state whenever you reload the entire page. So even if you load the page that looks exactly like the page that you left, all the forms would be cleared. You lose whatever state you had locally within the page when the new page loads. So there are reasons why in some cases an SPA is better than an MPA, at least in portions of the web application.
CHARLES MAX_WOOD: Did you just say MPA?
DAN_SHAPPIR: Multi-page application.
CHARLES MAX_WOOD: I know. I just thought it was funny. I've never heard it before.
DAN_SHAPPIR: Oh, yeah?
CHARLES MAX_WOOD: Well, I've never heard the term before. Yeah.
DAN_SHAPPIR: Interesting. Live and learn. So this is what React creators were looking to to achieve or solve how to get the benefits of an SBA on the one hand and Couple it with a simplicity of an MPA on the other hand and here I use it again that means create this sort of a mechanism where you get back the DOM that you need as function return value kind of now it turns out that if we do want to achieve that on the client side, there are actually several ways in which we can do it. So one way is that we can in fact, like AJ kind of suggested before, essentially just have that function return an HTML string. Just return a string containing HTML and then use anything, something maybe is even as simple as inner HTML or like the new append adjacent HTML. I forget the exact DOM API, but you can definitely use that and it definitely works. So like I said, you just create this JavaScript function, which gets this, whatever state you need to provide to it as, as parameters return HTML as a string, let's say you invoke that following some user interaction, and then you assign that HTML into some element in the existing DOM, and it's really easy to implement because now we also have JavaScript template strings. So it's really easy to insert your values into some sort of a string literal that you prepare in advance. And another advantage is that you can actually even break it down into sub-functions, and each one of those can return a partial string, and then you can just concatenate all those sub-strings into this one big string, and there you go. So you've got the benefits of the server-side mechanism. In fact, it works in a way that's really similar to it. You avoided the round trip. You also don't need to reload the entire page with all its resources and all the JavaScript, because you just set that string into a part of the page. And you don't even need to modify the entire page. You can just modify those parts that need to be modified so the state and the other parts is untouched. And the benefits are that it's pure functional, it's params in, string out, it's very declarative. It's easy to compose, like I said, you just concatenate the strings, and it's really easy to test as well because you just test the string that you get back. You don't need to apply it into an actual DOM or a mocked DOM in order to test it. But it also definitely has downsides. First of all, it's surprisingly fast because browsers are really, really good at parsing HTML strings, but it can still be too slow, especially if you're trying to set really large portions of the page. For example, I probably wouldn't want to do that if I'm trying to maintain a 60-frame-per-second frame rate. I wouldn't set the entire page over and over again using HTML strings. Those portions of the page that do contain local state, if you do an inner HTML, for example, into their parent, you do lose their local state. So even if you replace one text box with another text box, the content of that text box is gone. And obviously there are the limitations of using strings as code because you don't really have syntax checking, for example. So I know that there are some VS Code extensions these days that kind of address this, at least to an extent. But still, at the end of the day, when you put code inside the string, you lose a lot of the safety that goes with the validation of that code. So for example, if you generate wrong HTML the only thing that you'll notice really is that the page renders wrong. There won't be any syntax error or anything like that. So that's one possibility. Another possibility is to actually have a function that generates an entire DOM subtree, maybe something with a document fragment or maybe just some root element or something. You just use JavaScript code with direct DOM API, create element, set attributes, all the stuff. And then you return that DOM fragment as the return value. And you can use something like the new replace with DOM API to replace the existing DOM node with a new DOM node. And again, you can even break it down into sub-functions. You just append the results of the sub-functions inside the main function. So that's another approach that you can take, which doesn't require anything beyond what we already have built into the browser. But despite what AJ said, this can end up being really verbose. I mean, unless you're using the HTML shortcuts in which, string shortcuts in which case, we already spoke about that, then you end up with really verbose code. For example, you create an element, then you set the properties one by one, then you append to the parent. Lots of instructions in order to create each and every element. Again, if you replace an element, you lose the state of the previous element. And the funny thing is that it can even be slower than the original, the previous method of using an HTML string. I know that people might be surprised by that because they think, hey, you know, the browser doesn't need to parse a string. I just give it the exact DOM elements. But it turns out that performing a lot of DOM operations from JavaScript can actually be very expensive. So we've talked about this in the past.
AJ_O’NEAL: I'm not sure about this but I would assume that if you do the operation in a request animation frame, you would get some benefit because then the browser knows that you don't expect it to cut its other processes to try to repaint. Cause the reason that doing the manipulations has traditionally been so bad, my understanding is that because the browser, every time you manipulate a node, the browser will repaint. Whereas if you use the string, the browser doesn't repaint until it's completed the entire node all on its own.
DAN_SHAPPIR: No, that's not correct.
AJ_O’NEAL: OK.
DAN_SHAPPIR: Browser, first of all, if you create a DOM node, which is currently not attached to the document, you just create it and then modify it so it's present not yet attached to the document. Anything that you do with it doesn't cause any rendering whatsoever because the browser knows that it cannot impact the display. So it's actually in most cases beneficial if you do use direct DOM manipulation and I have the dog barking here. If you're using direct DOM manipulation in this way, it's actually beneficial to do as much of the DOM manipulations before you attach the DOM node to the document. So that's one thing. The other thing is that if you don't interleave operations, that is, you don't read, write, you just write, write, write, write, write, and then read, read, read, or vice versa, then you can also, the browser can actually batch the updates. But we'll get to that in a minute. Hopefully, we'll get to that a bit later on. So we spoke about two possible solutions. So let me propose a third one. And the third one is actually the virtual DOM. And here it goes. Let's say that instead of that I take the similar approach to the one that I just presented, but of creating DOM elements. But instead of creating actual DOM elements, I create JavaScript objects. And the JavaScript objects kind of mimic or stand-ins for actual DOM objects. So what I'm saying is that instead of constructing actual DOM elements, we'll simply construct lightweight, simple JavaScript elements. You can think about them like JSON effectively, where each of these elements represents a single DOM element, or each one of these objects actually represents a single DOM element. You might have a string field on that object that specifies the tag name. You'd have an array of attributes or a map of attributes, you know, key value pairs. And then you would have an array of children, which are also just more JavaScript objects. So effectively, it's just a JSON. And instead of returning a DOM element, we return the root objects of this tree of JavaScript objects that we just constructed. As we all know, if there's one thing that JavaScript is really good and fast at, it's creating and manipulating its own objects. So JavaScript can create objects really quickly, add properties on top of them really quickly. We can also provide the factory function, which makes this really easy, or we can create it as object literals, whichever way we prefer. Either way, it's all good. But you then might ask, well, it's really great that you created this JSON which represents the actual DOM but still needs to be converted into the actual DOM in order to actually do anything. And you know for the first time that's exactly what happens. The first time that you render it's up to whatever library that you're using, in this case React, to take this tree of objects and actually just convert it into an actual DOM that exactly matches in terms of content the tree of objects that you handed over to it. But after the real DOM is created, what React does, it actually holds onto that tree that you gave to it. It doesn't just discard it. And then the next time that you give it a new tree, what it does is it then compares these two trees and checks and identifies exactly what the differences are between these two. And it kind of creates a list of all the differences. And then only those differences are applied into the actual DOM. And then, of course, you take that new virtual DOM that you created and use it as the base for the next time and discard the previous one. And this process, by the way, is called reconciliation. It realigns the browser DOM with a new virtual DOM by making the least expensive changes in the actual browser DOM so that it matches the new virtual DOM. Is that clear so far? So effectively, you've got this, theoretically you would have this pure function, you give it a state, it builds this tree of JavaScript objects, hands them back, you take that, the root object of that tree, you hand it over to React, and React uses that to update the DOM by just changing those parts of the browser DOM that don't match this new tree. The benefits of this approach is that it's really fast because, like I said, building a tree of JavaScript objects is really cheap, and also you make a really small, usually, except for the first time, you would usually make a small number of changes in the actual browser DOM. It also preserves the DOM state because anything that hasn't been changed is just not touched in the browser DOM. And it's easy to use because building JSON is simple. So, you know, it's really easy to do. I do want to say a few words about this reconciliation, about how it works. So, like I said, it works by comparing two trees in order to discover the differences between them, or more precisely, the smallest number of operations required to get from the second tree to the first tree. For general purpose trees, such a comparison would actually be pretty expensive. I didn't research it myself, but the React documentation says that the generic tree comparison algorithm would be a big O of N to the power of three. So it's pretty expensive. So in order to avoid such expensive corporations, what React does, and the same goes for the other frameworks, is that they use shortcuts comparing generic trees, they are comparing trees of HTML elements. So they reduce the complexity because they can make certain assumptions about the trees that they are comparing. For example, if let's say they hit a certain element in the new tree, VDOM tree, and it's of type, let's say span. And in the previous tree, it was of a type div, then, you know, they know, hey, the the element type itself has been changed, well then it doesn't try to do a comparison of the subtree from that point on. It just assumes that, okay, everything here has changed, I'm just going to replace the old one with a new one. So it just has to recreate that entire DOM, browser DOM section, but it reduces the complexity of the comparison. There are also special handling for certain attributes like style because it actually has to look at the various parts of the style and not at the style in its totality as just a string value. And there are other tricks in there that maybe if we have time we'll get to later like using keys and stuff like that to help the algorithm do its matching of which object matches which. And that's the whole trick of the virtual DOM, really. The fact that thanks to this approach you can have a pure function that takes state, returns the DOM that you want the browser to have, but as a whole. But not as an actual DOM, but as JavaScript objects, which you can then hand over to React, which does the minimal amount of changes in order to get to that desired HTML state. That's also one of the reasons why you should generally avoid modifying the DOM behind React back. Because it assumes that the state of the DOM matches the previous virtual DOM that it has. If you then just went directly to the browser DOM and did all sorts of modifications, then obviously React wouldn't be aware of it and you would end up with potentially inconsistent states. But if you've ever read React code you probably say, but hey, Dan, you're talking about simple objects and it's JSON and whatnot. But if I look at how React code is written, I don't see JSON objects. I see something that looks like HTML, which is obviously JSX. And that's kind of React's second, let's call it idea, or you can decide whether it's smart or not yourself, which is to, they were basically saying that it would be very unnatural for people to write the, create the VDOM using something that kind of looked like JavaScript objects. That people generally prefer to build HTML as something that looks like HTML. And I guess they were looking at the templates that were available in other frameworks like Angular, for example. So their idea was to use something like that, but to effectively embed it within the JavaScript itself. And they do that. And they did that by implementing a transpiler, or you can call it a compiler, or maybe even just a preprocessor, whatever you prefer, which takes something which looks like HTML declarations, and then it converts them into JavaScript objects. Well, more accurately, it actually converts them into function calls that generates JavaScript objects. But essentially, it's the same idea. So you kind of ended up with something that's kind of like HTML embedded in the JavaScript itself. Or you can call it HTML and JS or something like that.
Hi, this is Charles Max Wood from Top End Devs. Lately, I've been coaching some people on starting some podcasts, and in some cases, just taking their career to the next level. Whether you're beginner going to intermediate, intermediate going to advanced, whether you're trying to get noticed in the community or go freelance, I've been helping these folks figure out how to get in front of people, how to build relationships, and how to build their careers and max out and just go to the next level. So if you're interested in talking to me and having me help you go to the next level, go to topendevs.com slash coaching. I will give you a one hour free session where we can figure out what you're trying to do, where you're trying to go, and figure out what the next steps are. And then from there, we can figure out how to get you to the place you wanna go. So once again, that's topendevs.com slash coaching.
DAN_SHAPPIR: or seems or seemed like sort of a perfect solution. You can write pure JavaScript functions that accepts state as parameters, return the VDOM, hand the VDOM back to React, and it efficiently reconciles it with the actual browser DOM, and job done. And whenever you need to update the browser state because the user did something that needs to impact the UI or some information arrived from the server, well, you just call that function again. So theoretically, if we went with a really simple solution, all you would need to have is your own function, which builds the virtual DOM, get that and take that virtual DOM and just pass it as a parameter to some React function and job done. But we all know that React is not that simple because there were several problems with this really simple approach. And this is where I like to say that this is when reality happens. You had this really, really cool and simple solution, and then you started running into all sorts of limitations with it. So as I mentioned, the initial state is still expensive because there's nothing before the initial state. So that one still needs to be created from scratch. But let's put this one aside. We'll get to that later, hopefully, if we have time. And the other problem is that even with reconciliation, this process can be slow and I'll explain why. And another issue is how to manage local state. Because the function that I described that takes state and returns the entire VDOM as a return value that you hand over to React, that state is a global state. But let's say I want to have some sort of local state. Let's say I have a form and I have this checkbox that controls whether you see the state or you don't see the state or something like that. I'm talking about states in the US in the case of the form. So you kind of modify how the form looks like based on the values of other fields. And that doesn't seem like something which should reside in a global state. That's something that seems like local information to a particular component in the user interface. So those are the problems. But so let's, so like I said, the initial state is expensive. Let's talk about that a bit later. Let's talk about why I'm saying that even with reconciliation, the updates can still be too slow. So I previously explained how the D-DOM is really cheap and reconciliation is really efficient and the React developers are really smart. So they use the really sophisticated algorithm. And if their algorithm isn't efficient enough, you can use Preact which is even more efficient. But what about your own applications logic? I mean, that function that takes the current state and maps that into the VDOM, that's still potentially a lot of work. If your UI is complex and there are enough elements in the page and you need to run the logic for each and one of those elements. And in some cases, it's simply a question of quantity. If you have a lot of components in the page, then running the logic for all of these components can be really expensive. I've seen blogs, for example, implemented where almost every line in the blog was a React component. So if you've got a long document that's just a ton of React components that you need to – elements in the VDOM that you need to generate one after the other. Just a lot of work or potentially, maybe there are not so many objects in the VDOM, but some of them really depend on complicated logic that takes a while to evaluate. And running all of them, all that logic, your own code on each and every update can be expensive, again, especially if you're trying to hit something like 60 FPS. So there are certain tricks that you might use to reduce this overhead. For example, one trick that React introduced relatively early on is, let's say that your function, or a function that's supposed to generate the VDOM for a certain section of the page, let's say that instead of just getting the current state, it also receives the previous state. And it can then compare these two states. And if it sees that they are equivalent, that they generate the same that they should generate the same VDOM, then it could simply cut off without generating the VDOM, without invoking all its children, it could just stop and maybe return some sort of a value, which indicates I've stayed the same, all good, nothing to do with me, it will also reduce the reconciliation time. So that sounds really great, but it's kind of difficult to implement as a simple function. I mean, what would you return if you want to say, and everything is good with me as a function return value. I don't know, maybe you'd think, hey, I just return null or undefined, but turns out that those are actually legitimate values to return that mean I don't have a VDOM. So I actually, they would actually need to return something else. So like I said, implementing something like this as a pure function, which just returns a single value is problematic. So maybe you return two values, but then you make the whole thing just more complicated. So that's one problem with it. Another problem is that sometimes comparing the state can be in itself complicated and expensive. And then you might be doing more harm than good because for every one of these components you're doing both the comparison and then if the comparison turns out to be false the actual generation. So now you're paying an even bigger price whenever you need to actually modify the virtual DOM. And you still need to go through all the parents' elements in all the ancestors in the tree to get to that point where you do the cutoff. So bottom line is, it's a cool technique. It can be really useful in some cases, but in a lot of other cases, it's just not enough. We need other mechanisms where we can control which portions of the virtual DOM we actually want to generate. But again, you see the problem here. Originally the concept was so simple because we said, hey, we were just going to recreate the entire virtual DOM on everything. And then the model was indeed really simple. And now I'm getting into the weeds because I'm coming up with ways in which I can generate just portions of the virtual DOM instead of the entirety of it. So, so yeah. Any thoughts or comments so far?
AJ_O’NEAL: I'm sold on the basic idea of the virtual DOM, more or less. I...I think a lot of times when people have complained about, okay, so with AG Grid, for example, they do weird stuff that cannot be accomplished with direct DOM manipulation. We had them on the show, they talked about it, that makes sense. It seems to me that, and this is kind of, this is definitely a tangent from the main conversation, but just the argument about the virtual DOM. I get it, but I also question if the need for the virtual DOM...doesn't suggest that something else in your process has gone really wrong. So for example, in Angular, if you wanted to fill a list dynamically with, say, as you type, you want an autocomplete to fill. The reason that this was ridiculously slow in Angular was that it would regenerate the entire list on every single keystroke, right? And in the naive implementations. And so if you just used a little bit of smarts to make sure that you were generating your list and then filtering it down, then you would get the advantages that you need and it wouldn't be ridiculously slow necessarily. And when I think about most web applications, typically you're just dropping in a component, something new. You're adding a pop-up. You're making one or two small changes to the page. You're not making hundreds or thousands of pages or changes unless you're doing something like a like a virtual Table and virtual scrolling and all of that in which case but again,
DAN_SHAPPIR: But again AJ you're looking at it from the perspective of performance And the perspective that i'm trying to take to is to take you to is a perspective of updating The ui as through pure functions State in dom out and think about it this way when you're working with Angular, one of the complaints about Angular back in the day was that something changed and it was really difficult to determine what actually in your code actually changed it. What was the cause of that change? And because things could be changed from all over and the state itself of the UI was mutable, you kept you taking the state and if you made a wrong decision somewhere along the way, then you would end up with an incorrect UI state and it's like ten steps down the line it would be really difficult to determine how you got there. Whereas with React you just take the current state generate the fresh UI as if you're like I said as if you're you went to the server and got the whole page back. You don't have to think or worry about what the previous page looked like. The only thing that React does with this virtual DOM is that it tries to make this actually doable by reducing the cost of replacing the previous DOM, updating the browser DOM from the previous situation to the new one. So you don't look at it as mutable. You just look at it as state in, DOM out, and React converts that into a series of mutations and because it's React and created by really great developers, you can assume that they wrote the code correctly. Okay, so that's the basic idea.
AJ_O’NEAL: I get that. I get that. So let me repeat what I think I'm understanding. So let's say that we have some terrible add widget on the page and it has a bad selector and it goes and edits something that it shouldn't edit. With React, once the user clicks a button again, it's going to re-render from its object of what the state is what the state should be. And so the fact that you had an ad widget or an analytics widget or whatever that screwed up your page in some way that you didn't expect and would be a nightmare to debug, that bug is only gonna persist for a short time and then it's gonna-
DAN_SHAPPIR: Again, actually not exactly true. Okay, not really. Like I said, yeah, because again, like I said, if you actually modify the browser DOM behind React's back, React is not aware of it. React just writes to the DOM. It doesn't read from the DOM, from the browser DOM. Unless you... So if you have a widget that went behind React's back and actually modified a part of the browser DOM that it shouldn't touch, that page could persist unless React happens to write to that same place as well.
AJ_O’NEAL: Well, that's what I'm saying, is that React is gonna rewrite that thing because you're gonna do something on the page and it's gonna rewrite the form or it's gonna rewrite the list or...So if something is buggy, it's less, if something outside of the React is acting on the page, outside of the code flow that you understand is acting on the page, then that is going to be less of a problem.
DAN_SHAPPIR: I prefer to think about it slightly differently. Think about the fact that your UI can be in a whole bunch of states and in the angular type of an approach or direct dom manipulation you can get from any state to any state directly. You just supposedly mutate your state to get from state A to state B. And then you mutate your state to get from state B to state C and so forth. And if you made any mistake along the way, then instead of going from A to B, you get to B prime, which is almost like B, but not exactly. And then when you move from B to C, because you're not from B, you're from B prime, you get to a state that's not exactly C either. And the errors kind of accumulate and pretty soon you're, you're seeing something really weird on the screen and it's really difficult to figure out that you got there. With React, whenever you, you, you don't go from A to B, you always get back to that virgin state and because you're giving, you're taking your existing current state and generating the entire VDOM from it, you know, at least in the naive approach. So you're always starting from fresh, as it were. Like I said, think about it sort of like what they were looking at is how the browsers used to work when they would hit the server and get back the HTML. Whatever you screwed up in the previous page, that was gone. And again, I'm not looking at some third party component that you don't have any control over. I'm talking about your own code.
AJ_O’NEAL: But wait if I wrote buggy code wouldn't it still be buggy though?
DAN_SHAPPIR: Yeah, but again, it's much easier to think about going from fresh to state instead of having to Think about and and measure and monitor all the possible states that might exist in your application It's you know every state transition that you implement is something that you potentially need to think about to test To to make sure that it works correctly if you have like 10 possible states and you can get from any state to any state, those are what? 10 to the power of 10, those are a hundred different types of transitions that you need to to figure out to implement.
AJ_O’NEAL: I think you made a quadrillion.
DAN_SHAPPIR: Well, well no, it's not 10 to the power of 10, it's 10 times 10 because you can get from any everyone to anyone, you're correct. But on the other hand with the React approach, there are only 10 possible transitions. You always go from the fresh state to one of those target states. So it would be 10 transitions. Now, obviously in a real application, there are not 10 possible states. There are, I don't know, 10,000 possible states. Now, obviously you can't get from every state to every state, so it's not 10,000 times 10,000, it's just 10,000 times, I don't know, times 100. So it's a million different state transitions that you would need to validate. Whereas with React, it's just those 10,000, because you always start from fresh. That's the key. So don't think about it from the perspective of performance. Because look, at the end of the day, anything that you can do with React, or with any framework for that matter, you can just do with the plain old DOM. Because at the end of the day, all these frameworks are just built on top of the DOM. So DOM manipulation can be done as efficiently, if not more efficiently than any framework. It's just the frameworks make it easier for you to potentially write you know, correct code.
AJ_O’NEAL: OK, so essentially it gives you a sandbox to operate in and the constraints define the art. Therefore, if you have certain constraints that you operated within, you only have a certain way that you can write the code and you limit yourself to ways of writing the code that are more functional and therefore easier to test and debug.
DAN_SHAPPIR: And to also reason about.
AJ_O’NEAL: Well, so this is where I have a hard.
DAN_SHAPPIR: State in HTMLO. I would argue that function that pure functional code is always easier to think about and understand then code that is based on mutating a global object a shared global object
AJ_O’NEAL: So if you're pitting against the extreme then yes
DAN_SHAPPIR: Well, obviously
AJ_O’NEAL: if you if you apply no constraints to your code style and say everything's fair game at the global level then yes, I agree that if you If you intentionally exercise no constraint or code style versus you exercise any constraint or code style, including the functional paradigm, then yes, I agree that it is easier to reason about. However, my primary gripe with React is that it is nearly impossible to reason about because one, it's not JavaScript. It isn't. It is not JavaScript literally in the textbook definition of what a language is react is not JavaScript and it doesn't use patterns that are familiar to JavaScript and this is is said very well in Abramov's talk reacts to the future where he
DAN_SHAPPIR: oh, yeah
AJ_O’NEAL: He says in essence the problem with react is JavaScript. We could only get so far away from Java JavaScript That's not exactly his wording but that was his message is that reacts great. The problem is JavaScript.
DAN_SHAPPIR: I wouldn't take it that far, but I totally agree with what you said. I kind of agree and disagree because on the other hand, as we all know, I really love JavaScript. I'm on a JavaScript podcast. I'm a JavaScript fan boy. I definitely don't want to get away from JavaScript and you're correct. And I haven't, I don't recall reading that post by, by Dana Brahmov. So I can't comment on it directly, but it's definitely true that JSX is not JavaScript. But on the other hand, it's in a lot of ways, React is JavaScript centric, because everything is done within JavaScript files. And the JSX is embedded within JavaScript functions. And definitely you're using different paradigms, but they're all implemented in JavaScript. Whereas other frameworks really walk away from JavaScript. If you look at like Angular or Vue, they have their own templates, and their own kind of templating language, which is totally not like JavaScript. So you're writing conditions and loops within your front-end application in a totally different programming language, while in JavaScript, if you do a loop, it's probably implemented using something like a map function or something like that. So it's kind of interesting that on one hand you're definitely correct that it's not really JavaScript anymore because of JSX. But on the other hand, it's still in a lot of ways really JavaScript centric. So, you know, take it any way you like. But the point is, the key point I was trying to make is that the VDOM was created to make things really simple in an ideal world. They would have been, but then you ran into these three problems that I mentioned. One is the initial state, which like I said, we'll get to later. The other one is that even with the VDOM, it can still be too expensive to do that entire generation of the VDOM and the whole reconciliation on each and every change. You need to have shortcuts. And the third one was that you do want to have some sort of a local state, whereas the model that I described so far, that function that generates the VDOM just takes the whole global state. So you keep everything in the global state, and that's obviously problematic. And I presented one way to reduce the effort of generating the VDOM, which was by having the ability to do some sort of maybe a cutoff, seeing that the state that you got when compared to the previous state that you had on the previous invocation would generate the exact same VDOM, so there is no point in continuing. It can be a great optimization, but as we saw, it's actually difficult to implement using pure functions. And indeed, when React implemented it, at least originally, they did it via classes. So you would implement a method on an object which would be invoked in order to do the comparison. And then it would invoke a different method. If the comparison returned that rendering still needed, it would invoke a different method in order to actually return the generated VDOM. But the other problem with it is that it can sometimes reduce the overhead, but in some cases it can actually introduce overhead because even the comparison itself can be fairly expensive. Let's put that issue aside for a minute and let's talk about the problem of the local state. Now where can I put the local state? Because one approach is to avoid local states. And some...
CHARLES MAX_WOOD: I'm going to...Interrupt you here for a second, Dan. We're already at an hour recording. I have a hard stop in 20 minutes. So how much longer are we going to go?
DAN_SHAPPIR: Yeah, probably another episode, I think.
CHARLES MAX_WOOD: Probably. All right. So we'll just kind of put a pin in this here. We'll schedule a follow-up episode, do a part two. And yeah, this is really fascinating. I mean, a lot of this stuff I'm aware of, but anyway, I really, really enjoy just kind of seeing where you're coming from on this, Dan. And yeah, some of the stuff makes sense. Some of the stuff, it's like, okay, again, I would use this in certain circumstances and not others, but I'm really enjoying it.
DAN_SHAPPIR: Oh yeah, for sure. If I only have really a small amount of DOM nodes that I need to actually, browser DOM nodes that I actually need to modify, then a solution like that is a total overkill. And I can just write simpler, simple vanilla JavaScript and browser DOM and be done with it. And like AJ said, if I'm really organized about the way that I write the code and kind of push the code that does the DOM manipulation via side effects to really specific functions and make sure that certain parts of the DOM are only modified by those functions, then again, I can write pretty clean code. It's just that in reality, my experience is that unfortunately, developers are not that organized. That if you have this global state that you can touch from everywhere, then the developers, they're under pressure, they create a technical debt. They take shortcuts. You know, I need to, I need to modify this part of the DOM and it would be really difficult for me to call this whole sequence of functions and modify stuff all over the place. So I'll just reach out to the dome and touch it from here and job done. And eventually you end up with a big mess.
AJ_O’NEAL: But tomato potato, because the React code that I've seen is a big mess where it's a bunch of people just use and I get the argument, well, you're not really coding React if you're using Redux or whatever. I get that, right? But people just throw in these extra state management tools, and then they throw the state everywhere, and then everything is entrapped with the drippings of the state, and I don't see how that's any better. Then you need to be a disciplined coder. React isn't going to solve that problem.
DAN_SHAPPIR: I totally agree. I agree with everything you said, AJ. And yeah, React is no silver bullet. And if you write the messy code, then you can definitely write messy code in React. And my issue...and the one exactly that I'm most trying to express in this, in our conversation is that if you understand the React approach, the React philosophy, and try to write your code accordingly, work with React, instead of just writing on top of React, then you would probably end up with much better and cleaner code.
AJ_O’NEAL: I agree with that. I think the same applies for the DOM. But I agree.
DAN_SHAPPIR: Fair enough. I
AJ_O’NEAL: I'd much rather people get good React training and write good React code then not get good React training and write bad DOM code.
DAN_SHAPPIR: Fair enough.
CHARLES MAX_WOOD: All right, well, I'm gonna push this into PIX just in the interest of time. And yeah, we'll definitely revisit this in a future episode.
Hey folks, if you love this podcast and would like to support the show, or if you wish you could listen without the sponsorship messages, then you're in luck. We're setting up new premium podcast feeds where you can get all of the episodes released after Christmas 2020 without the ads. Signing up will help us pay for editing and production, and you can go sign up at devchat.tv slash premium.
CHARLES MAX_WOOD: Steve, why don't you start us off with picks?
STEVE_EDWARDS: All righty then. So I came across a site that's right up my alley. It is a phrase generator, a catchy headline generator. And it says, the description says it generates random clickmate titles for your blog or magazine articles. And then it has different categories like academic quotes. It even has Bible quotes, which is sort of funny, financial advice, headlines, and there's just random button and you push and you get a new headline. So like five jaw-dropping secrets that make supervisors stronger. There's political rhetoric says, I refuse to support an America where corrupt labor unions and greedy insurance companies can undermine our big box retail stores or the Bible quotes is great. Uh, they that praise the Lord that God shall cast out less than vice. They shall vanish wickedness. You know, just quotes that you won't find anywhere, but it's, it can come up with some really funny ones. So it's at a phrase generator.com. And then for my highly anticipated jokes that I provide every episode. Question, what is the difference between a cat and a complex sentence? A cat has claws at the end of its paws and a complex sentence has a pause at the end of its claws. Thank you. Thank you very much.
AJ_O’NEAL: Been muted in time.
CHARLES MAX_WOOD: And then That was actually pretty good.
AJ_O’NEAL: Why do birds fly to warmer climates in the winter? Because it's easier than walking. And then finally last one. Went to my Doctor the other day, I wasn't feeling well. And I said, doctor, man, I got a bad case. I have a case of diarrhea. What should I do? He said, buy a new case. Thank you. So those are my picks for the day.
CHARLES MAX_WOOD: All right, AJ, what are your picks?
AJ_O’NEAL: So first I will pick the react to the future talk. I was wrong. It is not by Abramov. It is by Jordan Walk. Is that the person that actually created react?
CHARLES MAX_WOOD: Yes.
AJ_O’NEAL: Okay. So even better. Because this is the person who actually created React, says the problem with React is JavaScript. And it's a talk on reason. It's a clickbait talk, because you think that it's gonna be about React, and then it's, React sucks because JavaScript, reason is gonna be the solution. Well, not React sucks, but React is crippled because of JavaScript, reason is the solution. It's kind of what the talk's about. I honestly, I only made it about halfway through, then I got too angry. But, but, that there for people to listen to it if they want to hear the words of the person who created React. I'm also going to pick a couple of books. I'm going to pick three, actually. I'm going to pick, well, I guess one's not a book, but Tribal Leadership is perhaps one of the most beneficial books that I have listened to in a long time, and I think it's one of those ones where I am not advanced enough as a human being to be able to digest it in one go but it's essentially about the way that humans work together. It's not a framework. Many of the business books out there present a framework for how to work together, such as doing the sprint, being an example that programmers are familiar with, or different methodologies. And tribal leadership is not really about a framework. It's about this is what people actually do. And these are how we give, it's those researchers, it's the words that they give to describe what they've observed about how people work together and what works best and what doesn't. And they describe it in stages, stage one through five, where stage one is life sucks, stage two is my life sucks, stage three is I'm awesome, stage four is we're awesome, stage five is life is awesome. And those don't sound like descriptions of people working together, but if you get into the book, it does. And basically, everybody's at different stages and might be at different stages within different tribes about how they feel. And this is just identifying how teams that work well together work well together and give some suggestions about how to move either your whole team or a subgroup of your team from one stage to the next stage. And so I think that it's quite valuable, perhaps one of the most valuable books that I've ever read, if I'm able to internalize it and kind of tease out those practices, because working with people is what makes life awesome or terrible. The next one that I'm going to pick is Innovator Solution, which would have been probably the... if maybe tribal leadership takes my new number one position, then Innovator Solution may be dropping to number two and Innovator Solution is just a book about, well, business. So if you're not interested in business and innovating, then maybe it's not for you. But there's another book of a similar name. there's actually three other books of a similar name. But Innovator Solution is the most important one. It's not the one that's most famous, but it's the one obviously by its name, Innovator Solution. This one is the one that has the answers, whereas some of the other books are more a different approach, which I won't say their names just so that. You get one thing stuck in your head, which is solution. And you don't get confused by two things. Other than that, oh, oh yeah. And then if you've got insomnia, I found this meditation. I don't necessarily like listening to it, but it has been incredibly useful for me to actually fall to sleep. It's called a Meditation for Healthful Sleep, Guided Imagery to Reduce Insomnia and Improve Quality and Quantity of Restful Sleep by Belarus Naprstech. So I'm gonna give a link to that because I always listen to it and think, oh, how am I going to fall asleep to this? This is not that good. Why do I like this so much? And then I always fall asleep. So it works. And then other than that normal stuff, creeds of craftsmanship.com at cool age 86 for following live streams at underscore beyond code for following the, the, the more high value material that I produce from time to time.
CHARLES MAX_WOOD: All right, Dan, what are your picks?
DAN_SHAPPIR: I only have just the one pick so one of my colleagues at Wix is this awesome guy called Galsch-Lezinger. He's into a lot of really cool stuff into WebAssembly and Rust. I really need to get him to come on the show sometime. One of the things he likes to play with is TypeScript and he takes TypeScript to the extreme. Because you know, when you're throwing generics and stuff like that into the type system, the type system itself becomes its own programming language. And so he wrote this post called typing the technical interview in TypeScript in which he uses TypeScript's own type system to implement the old FizzBuzz problem. So he implements a solution for FizzBuzz using just the TypeScript type system. Really interesting. Really amusing article. Highly enjoyable. At least I found it so. And like I said, I definitely need to get him on our show and this would be my one and only pick for today.
CHARLES MAX_WOOD: Awesome. I'm going to go out with a couple of picks here. So the first pick I have, I have this infection in my foot. It was bad. I'm going to pick antibiotics. The infection's gone. The pain's gone. Life is good. The other pick that I have, usually I listen to books while I work out and I haven't been working out because running, biking, infected foot. Anyway, so I don't have a book pick right now, but I, I am going to be putting out some more content about this and you can go find that at topendevs.com slash podcast. But what I'm working on lately is a system to help people level up. And I feel like there's kind of a multi-pronged approach that people can take for this. And so if you're interested in creating content for developers, I'm looking at three different kinds of series. One is going to be kind of the longer form course that everybody's kind of used to. But when I was learning how to program a lot of the videos that were really helpful for me were the half hour to one hour, Hey, here's how you do this thing. And so I'm going to be putting a lot of that stuff together as well. And then the other ones that were really helpful for me were the ones like rails, rails casts back in the day. And they were like 15 minute videos where it was, Hey, here's how you do this thing real quick. And then you'd get another one. Eventually he was doing two a week because one was paid and one was free. And so I'm looking at doing something very similar to that model. It's all at topendevs.com. I'm running a special through the end of November for Black Friday. And I realized that this may go out right after that, but you can sign up for 50% off at topendevs.com and start getting access to that. I'm going to be doing master classes up through the end of the year that you can join in on or watch the replays on for various things related to your career and leveling up and learning and and things like that. And there might be some widely applicable things that I put in there like Docker or some of the other tools out there that the developers can use. You know, maybe we'll do a once through master class on VS code, for example. But anyway, and then January, I intend to launch my first longer course. February, the same thing. March, the same thing. And the whole list will be up on topendevs.com. And then finally, yeah, I'm going to be putting out series on leadership career growth, and then I may pick a technology that I know well enough to do the ongoing series on, or I may just start at the beginning and say, here's the basic weekly stuff, but put those videos out as well. We're also adding a Slack channel where you can get help. There's going to be a way for you to connect with other people who are part of the community. And anyway, tons of great stuff coming. So if you want to be involved, go to topendevs.com and just sign up. If you want to author one of these, right? So it's like, hey, I want to be doing the series on React or Angular or whatever. I think I'm gonna beg Dan to do one, but anyway, I'm also gonna beg AJ to do one and Steve to do one now that I'm thinking about it. But anyway, so yeah, so if we can get these series going and you wanna author, basically my plan is, there's gonna be a certain percentage of incoming revenue. We'll split it up according to how many minutes of your videos people watch. Right. So if you're doing the ongoing stuff, I think you're probably getting more minutes than people who do the shorter videos. Who knows, right? It may be a hot topic that people just need to learn in an hour. But anyway, so if you're interested in being a part of that, go to, uh, top end devs.com slash author, you can just fill in the form. I'll get an email. I'll get back to you and we'll figure it out. But yeah, I'd love to get some of this stuff rolling so that when we launch at the beginning of January, there's plenty of content in there and the community is moving along in a way that will help you level up because my mission, my goal is to get you on the path to becoming top 5% developer in your field, whatever that is, React, Ruby, JavaScript, whatever, right? Wherever you want to be and then get you the outcomes that you want from your career. And that could be salary, it could be lifestyle, it could be I want to be home for my kids at a certain time of the day. I mean, whatever but let's get you there and you know, it's not so hard that you have to go and be this a meta genius across all these ideas. So anyway, topendevs.com, that's where it's all going to live. The podcasts are moving over there right now. In fact, they're mostly moved over so you can just go over there and click on any of the podcasts that we have. Um, and then if you have other ideas for other technologies that we're not covering right now, um, yeah, feel free to let me know as well. Um, the Slack channel will be free so you can get in that for free. There's just gonna be some premium channels that people can get into if they're paid members. Anyway, that's what I've got. I'm super excited. The thing that I implemented yesterday, so I'll pick them as well because I'm super happy with them, is Auth0. So I'm using them for the authentication on this. It was way faster and easier to pull them in and then hook up like the Google and GitHub and whatever sign in than it was for me to go build it out in Rails. So I'm pretty happy with them. And we'll see how that all shakes out. But yeah, those are my picks.
AJ_O’NEAL: Wait a second. Even even better than using forget the name of it.
CHARLES MAX_WOOD: What's device.
AJ_O’NEAL: Yeah. Device.
CHARLES MAX_WOOD: So device is easy. The problem is, is getting all those other types of sign ins. I want, I want people to be able to sign in with whatever they want.
AJ_O’NEAL: Oh, device doesn't have plugins for the other sign-ins.
CHARLES MAX_WOOD:It does, but you have to go and maintain that stuff. I'd rather just let off zero do that. So anyway, that's pretty much it. I'm looking forward to hearing from you. Also, if you want just direct coaching on any of that stuff, topendevs.com slash coaching. And yeah, we'll wrap it up here. Thanks for coming. This was terrific, Dan.
DAN_SHAPPIR: Thank you very much. I enjoyed it myself. And I get the pleasure of having a follow-up. So, you know, double win. Ha ha ha.
CHARLES MAX_WOOD: Right? All right, folks, till next time. Max out.
DAN_SHAPPIR: Bye.
STEVE_EDWARDS: Adios.
Bandwidth for this segment is provided by Cashfly, the world's fastest CDN. Deliver your content fast with Cashfly. Visit c-a-c-h-e-f-l-y dot com to learn more.