Putting React In The Browser 2024-04-22 In this episode, Jake and Surma chat about the complexities of adding common framework patterns into the web platform, and work that has been done on that so far.
Resources:
Transcript Surma: Ladies and gentlemen, welcome to OTMT! Surma: Is that an... Jake: Oh, that's good! No, keep going! I'm enjoying that! Surma: In the left corner, the inventor of ServiceWorker and AnyApp with a checkered background, Surma: Jaaaaaaaaaaake Archibald! Jake: And in the right corner, the inventor of... Oh, what is it? You... I think you'll find Surma: Nothing notable! Jake: Structured Clone API. I mean, yeah. It's Surma “The Surma” Surma! Amazing, right? Well, okay. Surma: Ha Surma: Wooo! Surma: Wooo! Surma: The crowd goes wild! Surma: Ah... Surma: Pfft! Jake: This has lost all credibility. I don't know if I'll put this in the show or not. We'll Surma: Yeah... Surma: But the miniscule amounts that we had, maybe... Jake: see where it goes. Can I tell you about the stupidest thing I ever did in my life? You Surma: I... Surma: I mean, of course, I thought I would know this, but now I'm... Jake: might. You might. So I went drinking with an old school friend at London Bridge, and Surma: Well, tell me, tell me, Jake... Surma: Hm... Jake: then we... I'll keep this short. We went to get the train back home as we were walking Jake: towards the train. I don't know. He somehow, like, he caught the back of my foot as he Jake: was walking. I tripped up, and my shoe flew off my foot, and in a shot that I couldn't Surma: Erm... Jake: do deliberately if you gave me a million tries, my shoe flew through the air and went Jake: between the train and the platform, just straight onto the ground. Yeah. And I looked at my Surma: Please mind the gap between the train and the platform edge. Jake: shoeless foot, I looked at my friend who was laughing a lot, and then it's like, what happens Surma: You went into the gap?! Jake: now then? What do we do? And here's where it gets stupid. I looked at the train board Jake: and saw that that train was not leaving for 15 minutes, so I went down onto the tracks Jake: and got my shoe. Well, I suggested... So I said, like, well, I could just reach down Surma: And now you were under the train. Jake: and get it, but it was a little bit far, so I suggested that he holds my ankles. But he Jake: found this whole thing so funny, he just dropped me. And I was under the train. Surma: That does seem slightly terrifying. Jake: And then I emerged from under the train with my shoe. Jake: And at the time, this all seemed like a very sensible thing to do, but it is. Surma: And the electricity under there, as well? Jake: Maybe this is why it's stupid, isn't it? This is why it was a very stupid thing to do. Jake: And I just... It's one of those things of, like, I meet up... So I met up with Jake: Frances Berryman, who I worked with at the BBC and have known for a very long time. Jake: And whenever I meet up with her, at some point, she'll go, remember the time you went under a Surma: Yeah. Jake: train, you idiot? And it's like, oh, yeah, I think I'm actually quite lucky to be alive. Jake: And, you know, not in one of those Darwin Award entries. Surma: Considering that on an airplane, now they tell you if you drop your phone, please call Jake: That is the correct thing to... Oh, hello. I dropped my shoe under a train. Can I have it Surma: a member of staff and don't move your chair because you'll just break everything. Surma: So this seems like you really should have gone to, like, train people and tell them Surma: My shoe. Jake: back, please? And yeah, no, no, that is the right thing to do. I think I, like, Jake: weirdly was embarrassed about it and decided that risking my life would be the better thing to do, Jake: which it absolutely, absolutely wasn't. But rest assured, if I dropped my shoe out of a plane, Jake: I think I would just write it off. Well, I don't know, it could be a Boeing, right? Surma: I mean, if there was any cavity that allowed you to accidentally hit the catapult, eject Jake: I'm terrified now to press that button to recline the seat in case just, like, Surma: the seat. Surma: It's right next to the eject button. Jake: part of the plane just ejects, yeah. Jake: Should we talk about the web? Right, oh, I suppose I will say thank you to Shopify for Surma: Let's talk about the web, Jake. Jake: just letting this happen. Whether you think that's a good thing or not, that's for you to decide. Surma: The way you say it, it's like they're kind of like, ah, this must happen, but I will Surma: look away. Surma: I will not dignify this. Jake: That's pretty much how it goes, pretty much how it goes. Okay, so what I want to talk about is Jake: putting React in the browser. And it's, well, it starts with a tweet from Michael Jackson, Jake: who is on the Remix team. And yes, yes, just to clarify, the tweet is this. Jake: Yesterday at a company, this is not my Michael Jackson voice, I'm just doing a vaguely other Jake: person voice. Yesterday at a company offsite, I was in a conversation with your advice and Jake: Jaffa the Cake, where we discussed a potential, that's me, yeah, we discussed a potential element Surma: It's too smart, it'll do it smart. Jake: dot replace HTML API. And I can't stop thinking about it. Think efficient DOM updating that Jake: doesn't lose state, like focus, built right into the browser, could be super powerful, Jake: and something frameworks like React could leverage internally. All right, so this API is Jake: kind of like inner HTML, but it'll do diffing. So it will, yeah, it will change as little of the Surma: My gut reaction to this is, that is actually kind of cool, because it is kind of the primitive Jake: structure as possible in order to achieve the kind of markup pattern that you've given it. Surma: brand. Surma: Even if you were to write your app by hand with JavaScript, like that's something you Jake: Exactly. And there was a lot of positive sentiment in the replies about how it's going to, Surma: do. Surma: I'm just going to interject again. Jake: this will improve performance and it will reduce the size of React and, Jake: or, you know, you wouldn't need frameworks at all for some simple cases. Surma: This reminds me of like, because we had a similar, not a similar, but there was similarly Surma: an exploration before many years ago now about what is a low level primitive we could build Jake: Oh, boy, we are going to get onto that. Yeah, hang on, hang on to that for quite a while. Surma: into the browser that helps frameworks like React, but also others. Surma: And wasn't that like template tag instantiation with like, oh, cool, okay. Jake: Because I stormed into this, you know, Twitter thread, so I was tagged in it, but to kind of Jake: really just pour misery on the whole thing, as I do, but I didn't really have enough time, Jake: space, whatever, to kind of add detail why I didn't think that this API is a good idea. Jake: So, hey, I thought I'd do it on the podcast. So why are modern frameworks good? Or why is the DX, Jake: the developer experience, good? I think it comes down to like, yeah, the DOM is this big, Jake: big old bag of state. And if you're changing the DOM, you're running commands like, Jake: you know, remove this element, add it over here, change this attribute, add this event listener, Jake: remove this other one, you're manually going from state A to B within a series of steps. Jake: And there is a lot of room for error. Whereas modern frameworks via some kind of, Jake: you know, templating system like JSX in React, they let you describe state B Jake: and the framework goes and does the minimum it can figure out that makes the DOM into that shape. Jake: So why isn't replaceHtml that? Like, why isn't it ticking that box? And the problem here is HTML. Jake: HTML is the serialized form of the DOM, but boy, is it lossy. Like, yeah. What's it got? Jake: Tag names, attributes, text nodes, child nodes, string values. Attributes can only be strings Jake: because it's a serialized string format. But there is a lot of state in the DOM that isn't Jake: captured by that, like event listeners. Yes, exactly. Surma: HTML API that Michael Jackson was kind of suggesting there, would take a string of markup, Surma: right? Surma: Which is where this lossiness that a stringified HTML cannot represent full state of a DOM Jake: Yeah, you're not getting the listeners, you're not getting properties, you're not getting, like, Surma: tree entirely or fully. Jake: the pixels on a canvas, right? It's just not there in the markup. And that's why I don't Jake: think it works. So, like, if React tried to adopt this thing, like, they would have to add in an Jake: extra layer to handle... Well, let's just talk about event listeners first. So they would need Jake: some way of knowing that an element was replaced when they expect it to have the same listener as Jake: the previous version of that element so that they could go and re-add the listener or, like, remove Jake: it if it's not supposed to have that listener anymore. So you would need a bunch of metadata Jake: coming back out. And my gut feeling is it's not worth it at that point. You'd be adding so much Surma: Also, yeah, I guess React and I guess other frameworks as well, already have this DOM Jake: code to do that. Yeah. Surma: like data structure, like objects with children, which probably resemble for many intents and Jake: Exactly. Surma: purposes, the DOM tree. Surma: So then serializing it to strings so that the browser can reparse it, probably quite Surma: wasteful. Surma: I think the goal here, like let me give you a new DOM tree or representation of a DOM Surma: tree and you figure out what actually needs to change. Surma: I think that that goal is viable. Surma: I think it just string, HTML strings might just be the wrong vessel to transport the Jake: Oh, yeah. Jake: Yeah. Agreed. And Preact is doing all of this already in 3K. So, like... Surma: information. Surma: Got to have to weave that one in there. Jake: Yeah, I know React is bigger, sure, but we're not going to be shifting the needle Jake: much in terms of download size if we put all of this in the browser, you know? Surma: Yeah. Jake: On the performance side? I'm guessing. But I feel like... And I used to make this mistake a lot. Surma: Yeah. Jake: I used to think if you took something that was written in JavaScript and just put it in the Jake: browser, it would be, like, three times as fast or whatever. It would take an eighth of the time or Jake: a tenth of the time or something. And I just don't think that's true in most cases, especially stuff Jake: that's doing a lot of DOM stuff. Surma: Yeah. Surma: JavaScript engines are just phenomenally good at running JavaScript. Jake: Oh, absolutely. Surma: I did a blog post a while ago, which I'm totally going to link now, where I was, and it's not Surma: completely apples and apples because it's really hard to do, but I was implementing Surma: a algorithm or something in WebAssembly, like in AssemblyScript in C and in Rust and in Surma: JavaScript. Jake: Was this image rotating or something else? No, it's a different thing. Surma: No, this was a similar exploration with the rotation where we thought WebAssembly would Surma: solve it. Surma: Actually, most of the performance gains came from thinking about browser caches. Surma: No, this one, I'm now doing the live clicking. Surma: Where is it? Surma: Is WebAssembly magic performance pixie dust? Surma: I was blurring. Surma: So you have, you know, pixels of an image in an array and you want to run Gaussian blur Surma: on it to blur the image. Surma: And basically, in the end, it took some, by default, JavaScript was just beating all of Jake: Oh, very good. Surma: the WebAssembly, like naively written JavaScript beat all of the naively written compiled languages. Surma: In the end, with like getting really deep and doing handcrafted optimizations, I could Surma: get all of most of the compiled languages to be close to JavaScript. Surma: C++ actually beat it in the end after I got help from good C++ developers. Surma: But JavaScript just, you know, me shitting some JavaScript on the floor ran really, really Surma: fast. Surma: Of course, there's then also the file size to consider. Surma: So JavaScript was just like, in the end, a really good tradeoff. Surma: And I guess it makes sense because JavaScript is fairly high level, which means the engine Surma: gets a lot of high level type information while it's running it to the interpreter to Surma: collect how to compile it. Surma: While, you know, at WebAssembly, you lose all that information about like, is this a Jake: Yeah. Surma: float array? Surma: Is it an image? Surma: What are the access patterns? Surma: Like in that sense, JavaScript, the language can encode a lot more that the compiler can Surma: use than low level WebAssembly. Surma: But yeah, like JavaScript is just very, very well optimized. Jake: Exactly. Yeah, it can adapt at runtime, which is great for things that are running in a tight Jake: loop, which that kind of code is. Yeah, I agree. I don't think it would be improving performance Jake: much, if at all. Especially when you have to add the extra stuff on top to make listeners work, Jake: you're probably losing. And we haven't even considered things like component references, Jake: which, you know, all the frameworks have, and you can't represent in this, like, Surma: I mean, it just compiles down to an object notation, right? Jake: replace HTML world so easily. So why doesn't React have this problem? Like, why is this Jake: totally fine in Preact, React, Vue, Svelte, all of that sort of stuff? And it's because of this Jake: templating language they use. So in React, it's JSX. It looks like HTML, but it is not, Jake: because it's able to express event listeners. It's able to express property values. Jake: Yes, exactly. And in fact, I think most of these frameworks don't surface a difference between Surma: I don't think it's just... Jake: attributes and properties. They just sort of, you look like you're writing an attribute, Jake: but you're probably using a property in most cases, but it will decide internally which to use. Surma: Yeah. Jake: And I think it's produced a generation of web developers that do not know the difference Jake: between attributes and properties. But I don't know. I think that's fine, right? It's great that Surma: Yeah. Jake: people don't have to worry about that. But if you're thinking about putting React in the browser, Jake: you have to think about that, right? This is something we have to consider. Jake: So for people, like, if you're unsure of the difference, attributes, they're the things Jake: that appear on the element in the elements panel in DevTools and in the HTML source, Jake: like id equals foo or whatever. Whereas properties are the ones on the DOM instance, Jake: so like .textcontent or .innerHTML on the element. Those are properties, not attributes. Surma: Yeah. Jake: And since they're on an instance, they don't have to be strings. So you can have .classlist, Jake: which is an object with methods and stuff. You've got .offsetheight, which is a number. Jake: You've got .value as date, which is a date on date inputs. The reason I think people get Jake: confused is there's a lot of attributes that have equivalent properties. So .id is the same as the Jake: attribute. In fact, it is just reading from the attribute, reading from the attribute and writing Surma: Oh, ID is reflected? Jake: to it, which the spec calls reflection. Id is reflected. Yep, absolutely. Surma: I was trying to remember because that's something where I'm still... Surma: I think I looked it up once and kind of didn't really memorize it because I don't interact Surma: with this enough. Surma: But I remember that Rob Dodson at the time was trying to write a guide for custom elements. Surma: Where is your source of truth? Surma: Like, do you write getter setter properties that read from the attribute? Surma: Do you have an actual property that just reflects back to the attribute? Jake: Oh, let's talk about that. Yes. So, yeah, this is where it gets confusing, is we have cases where Surma: And then, you know, the web platform is also, I think, somewhat inconsistent. Surma: Like, for example, dot value on an input field does not get reflected to the attribute. Surma: And I think once you set the property, changing the attribute does nothing, maybe? Surma: Isn't there something weird like that as well? Jake: there is reflection, but the names are different. So you've got a class attribute, Jake: but a class name property, and it is just reflection between the two, but they've got Jake: different names. But yes, the maddest one is form fields and value. Okay. Because in React, Jake: you look like you're just setting the value attribute, like in JSX or whatever, but you are Surma: I mean, it gets already weird when you think about that there is an input field with type file. Jake: not. I'm trying to think of the best way to describe this. This is going to sound... Surma: Where, right? Surma: Like, what does it look like on an attribute? Jake: Yes. Yeah. Yeah. Oh, absolutely. Yes. So value is a property that doesn't have an equivalent Surma: It just doesn't. Surma: It doesn't happen. Jake: attribute. And you can confirm this because if you write to .value with JavaScript and look at Jake: DevTools, it hasn't updated any attribute. If you type into a text field, you won't see an attribute Jake: getting updated in DevTools. So that's proof of that. But here's the thing. There is a value Jake: attribute. The value attribute is linked to the default value property. So .default value Jake: reflects or reads from the value attribute in the same way like class name and class are linked. Jake: And that sets the default value of the property. So if you have the attribute value equals foo, Jake: or you do .default value equals foo, that's the default value for that field. Jake: And if you read .value, initially, that's what you'll get back. Even if you update default value, Surma: I don't know. Jake: your .value will return the default if it's in default mode. But then as soon as the value is Jake: set, either by doing .value equals whatever, or the user interacts with the field, it switches mode, Jake: and it's now no longer doing the default thing. It's doing the actual set value thing, Jake: like whatever the user's input. Yeah, look, no wonder people don't know the difference between Jake: this stuff. Yeah, that's it. I know, I know. So yeah, diffing works because React has this format Surma: That's madness. Surma: Absolute madness. Jake: which can represent listeners and properties and non-string values and all of this. Jake: There are still gaps, like it can't represent the pixels in the canvas element. So if you're Jake: using canvas in React, you have to be careful, because if you hit a diffing path where it, Surma: True. Jake: you know, it doesn't realize that you've moved that canvas somewhere, it will end up, Jake: you know, removing one canvas and recreating another, and you lose all the pixel data. Jake: But that's, yeah. Surma: I mean, in general, any web elements, be that custom elements or native ones, Surma: that have internal state outside of the react state, Jake: Hmm. Surma: they start messing up when they get recreated and stuff and not just updated. Jake: Exactly. Surma: Video players as well. Surma: That's the infamous one where a video starts replaying from the start Surma: because React did a re-render and for some reason recreated the DOM element Surma: rather than not touching it. Jake: Yeah, absolutely. Iframes as well. Yeah, exactly. Jake: So to do this properly, you would need this declarative format, right? You would need Jake: something like JSX that can represent all of this stuff. But this is something that Jake: frameworks don't agree on. So if we just put JSX in the browser, is Vue going to drop their Jake: current templating language and use JSX instead? Is Svelte going to drop their Surma: I mean, I guess for me the idea would have been that whatever this API takes Jake: templating language and use JSX instead? I don't know, but I suspect maybe not. Surma: is an intermediate format that each framework can target with their own templating shenanigans. Jake: Yes, I agree. And so, to get a feel for how that is actually successful, we can take a step back Surma: Yeah, put it in the browser. Jake: and, like, 20 years ago or so, like, developers were asking browser dev rels to just put jQuery Jake: in the browser. Right. Just put it in the browser. And that didn't happen, but some stuff did happen. Surma: Yeah. Jake: Like, like you say, some kind of intermediatory, lower-level stuff was put in to help jQuery do Jake: its job faster and better. So I'll get into the details. QuerySelectorRole. We got that. Jake: Because the selector engine was a heavy part of jQuery. It was even its own Jake: project in the end called Sizzle. You know, a whole new implementation of selector matching, Surma: Yeah. Jake: parsing and matching. But, you know, the browsers should have this feature built in because it Jake: already has most of it there for CSS. Like, it already has the selector parser. It already has Jake: the means to select elements based on a selector. So it just had to expose it via JavaScript. And Jake: it's kind of stupid that it took so long for that to happen. The name of it sucks. It's a Jake: thing we use all the time. It's long to write out. But, you know, we got there in the end. Surma: Hmm. Jake: We also got things like element.after, element.before, and element.replacewith, I think Jake: was another. Like, a few of these methods, which they were just added for convenience. Jake: Like, they didn't perform better than the jQuery equivalents, but they, Jake: you know, made the platform nicer to use. And then we got things like CSS animations, Jake: web animations, requestAnimationFrame, because, you know, jQuery had some animations built in. Surma: I was going to ask, like in jQuery providing request animation frame, Jake: And this was better for the browser to do because it has access to things like vsync. Surma: was that like the infamous setTimeout16? Jake: Yes, it was. Because they couldn't do anything better. Like, there's literally nothing. And so, Surma: Brilliant. Surma: Yeah, of course. Jake: as soon as requestAnimationFrame became a thing, they switched to that, although, Jake: you know, a series of compatibility issues because setTimeout would run when the web page wasn't Jake: shown, whereas requestAnimationFrame would pause. So it was a compact issue for them to adopt it, Surma: Yeah. Jake: but I think they eventually did anyway. But you also get, for the declarative animations, Jake: some of them can run on the compositor and, you know, be much faster. And that's Jake: not something jQuery could have just done. So what is the equivalent for React and the Jake: current generation of frameworks? It's this kind of lower-level thing that you alluded to. Jake: And it's something that browsers have been looking at for years, and one of which you Surma: Yeah. Jake: mentioned right at the start of the topic was HTML template instantiation, Jake: which was a joint idea between Apple and Google seven years ago. Surma: Seven years ago. Jake: I know, I know. I remember hearing about it at TPAC, which is the W3C meetup. Surma: That's where I heard about it as well. Surma: It must have been my first TPAC then. Jake: Yes, it was. Yes, you were there for that one as well. Yeah, I remember. Jake: But yeah, it didn't go anywhere really beyond the dock. But there is a more recent proposal, Jake: it's still four years ago, but there was some more exploration done last year. So it's kind of, Jake: it's not dead, it might be resting. It's being looked into, absolutely. Surma: It's being looked into. Jake: Okay, DOM parts, what are they? Jake: Now, this seems like a pretty neat idea. It's essentially placeholders. Jake: So there's an attribute one, a DOM node one, and a child list, you know, a set of nodes, I guess, Jake: one. You put one of these placeholders in the DOM, and then you can update its value via the Surma: Hmm. Jake: placeholder object. So instead of setting an attribute to a string, you set it to one of these Jake: placeholders. And now you've got that kind of, you know, way of updating it. And same for nodes Jake: and stuff as well. There's also a grouping primitive. So you can group a lot of these Jake: placeholders together and update their values together, which gives you DOM batching, which Jake: removes that, like, bouncing between the DOM and JavaScript. You can kind of, you know, Surma: Yeah. Jake: in JavaScript, say, I want this, this, this, and this to happen, and then, you know, stage it and Jake: commit it. Surma: So this sounds a bit like what at the time litHTML and similar projects were trying to do Surma: not just took your JSX or markup-ish looking thing and diffed it against the current DOM. Surma: They would rather figure out which parts of your markup are actually dynamic, Jake: Yes. Surma: like are bound to a variable and remember those places and just if the variable updates Surma: it would go straight to that point in the DOM and just update it Surma: and kind of avoid this whole diff approach as much as possible. Surma: And that's also kind of what I think Preact signals are now doing Jake: Exactly. Surma: where when you pass a signal into an attribute or into the DOM, Surma: it doesn't do a whole vDOM diff if it can avoid it. Jake: Yeah, it is. So with Preact Signals right now, like, it only does the fast path for attributes. Surma: It just goes straight to the thingy. Surma: So this seems like a platformization of that. Jake: It doesn't do the fast path for, oh, sorry, you are correct, and for text nodes. It doesn't do Surma: And for text nodes, right? Jake: it for changing trees. But this DOM parts system would let you do it for trees as well. Yeah, Surma: Yeah. Jake: Lit does do this as well. It does it with, I think, the placeholders they use, well, within Jake: the DOM tree is HTML comments. I think it's the nearest thing they can get to these little markers Surma: Yeah. Jake: that they can put in. And so if you use Lit, if you go into DevTools and look at your thing, Jake: you'll see these little HTML comments dotted around the place, which is its, Jake: yeah, its kind of placeholder system. There is another part to the proposal. Jake: It's the DOM part declarative template. So this is a template element, as already exists. Jake: But inside there, if you put, and this is going to be difficult to say with words, Jake: open curly, open curly, close curly, close curly, you can imagine what that looks like. Surma: Yeah. Jake: Like a sort of mustache. Yes, yes, but with nothing in it. So, and that marks it as a part, Surma: Look at this. Surma: Handlebars, right? Surma: Oh. Jake: like a, it's kind of putting one of those little placeholders in. Jake: And then other than that, the details are kind of like, it's not clear how you would, Jake: you know, instantiate this template, how you would then get the parts out of it in an order Jake: that's reliable. That kind of stuff is still unexplored, but. Surma: It feels like the obvious choice would be you put a name in between the handlebars Surma: and you can reference the different parts by name. Jake: Well, yeah, I'd have thought that. I'd have thought that. But that doesn't seem to be Jake: the current proposal, but I think it's, I think that's a sensible way to do it. Like, Jake: you can put some metadata in there that makes it, you know, you can then Jake: query part by name or something, get part by name or whatever. Surma: Or you just get like a .parts, which is a dictionary of name to part. Jake: Oh, exactly. Oh, that's even better. Yeah. You should do API design. I should stay away from it. Jake: But yeah, it's, other than that, details lie on the ground. It does feel like this is a, Jake: you know, a mid-layer that a lot of the frameworks could benefit from, Jake: especially the batched DOM updates, like if nothing else. Surma: Yeah. Jake: Another API that I think is interesting here is there's a discussion around an API to move DOM Jake: nodes. And it sounds like, well, can't we already move DOM nodes? Surma: I was going to say, we have append and if it's already somewhere else, it gets moved. Jake: But you already hit upon the problem of this, and you mentioned it earlier. Jake: What's the problem with that? Surma: It loses state maybe? Jake: It does. And the reason it loses state is because it's, when you append a node to somewhere else, Jake: it's actually removing the node, then inserting the node. It's not a kind of atomic move. Surma: Right. Surma: So like in custom elements speak, you will literally see a disconnected callback Surma: and a connected callback. Jake: Exactly. And that is, like, again, I'm going to struggle to remember which elements this Jake: affects and which ones it doesn't. Like, you can move a canvas around and it's fine. Jake: You cannot move an iframe around because the removal steps for an iframe is to unload the Jake: inner document. Exactly. You can use a canvas outside of the DOM. Video is the one I can't Surma: Yeah. Surma: I mean, Canvas actually, you literally can remove it from the DOM Surma: and you can wait a couple of frames and reinsert and it will have the same state. Surma: Like that's literally how the Canvas element works, I guess. Surma: Yeah. Surma: So video player, I guess. Jake: remember. I think, yeah, because a video won't make noise when it's not in the DOM, Jake: so I think that is another one of the ones that will lose state when you're just moving around. Surma: Maybe it even depends on the attributes. Surma: Maybe if it's autoplay, it resets. Surma: If it doesn't, it can maintain the state. Jake: Oh, I don't know. But anyway, this is the bit they're looking to fix as well. And this will Surma: Who knows? Surma: Yeah. Jake: help. I know this is something the frameworks have asked for, is that, because it will help Jake: the case where they are wanting to rearrange. And it's not a problem unique to frameworks, Jake: but I know they want to be able to take an iframe and move it into a React portal kind of thing, Jake: and for it to survive. We've had the... Anyone who's implemented a video site where you want Surma: Yeah. Jake: to take the video and pop it into a kind of picture-in-picture, kind of like in the corner Jake: of the page as you scroll down, you're in all kinds of trouble because it's... Yeah, Jake: the horrible things you have to do to your DOM when you actually just want to move that video Jake: element. It's... Well, there you go. That's why they're so successful. Surma: Well, they have some very interesting techniques. Surma: I don't know if it's still the case, but I remember at one time when they load the page Surma: or when the page loads, they would what they called bless the video tags. Surma: So they would have multiple video tags that are in the DOM, but not visible. Surma: And they would click play on them because it's in response to some form of user interaction, Surma: which is the only way you're allowed to programmatically call play, Jake: Oh, interesting. And also, I think they use all of the lower level video stuff, right? Because they... Surma: and it actually has an effect. Surma: And that's what they would use for the autoplay feature, Surma: where they would then switch to the next video, change the source, Surma: and the video would start playing automatically Surma: because it had been blessed by a user interaction click. Surma: Oh, yeah, the media MSE and all those shenanigans. Jake: Yes, the media source extension stuff. Yeah. I think that gets them out of trouble as well. Surma: Yeah. Jake: But doing it just plain with a video element is a pain. So yeah, that's it. That's kind Jake: of where we're at. And so that's why when people say, well, let's just put this in the browser Jake: and be done with it, it's like, I get grumpy and say, this is not as simple as you think it is. Surma: No. Surma: But you said the discussion was like this was started four years ago. Jake: There was some activity in 2023. So not dead, maybe resting. I guess what they need to do is Surma: Is there still activity? Surma: Are these all dead? Surma: Are some of these still alive? Surma: Like what is the... Jake: make sure that this is of benefit to frameworks. Does this benefit React? Does this benefit Vue? Surma: I feel like, yeah, the whole here is a primitive to kind of isolate slots Surma: from different DOM elements that you can grab directly. Jake: Yeah. Yeah, I think so. I guess it would come down to how much work is it for React to translate Surma: That seems quite good to me. Jake: its current model into that? And do they get a benefit that is worth it in the end? Surma: I'd be really curious to know, like, for example, the Svelte folks Surma: who are already having this compilation step Surma: and putting a lot of powerful stuff into that step, Jake: Yeah. Surma: if they would use it, if they could basically, Surma: because you have your markup in a separate file, Surma: you have all the variables that are already reactive Surma: slotted into children or attributes and properties and all that jazz, Surma: if that for them would be like, yeah, cool. Surma: That's just a compilation target. Surma: We can adopt this in no time. Surma: It would do exactly what we need. Surma: I'm guessing other frameworks would. Surma: I think it sounds useful. Surma: But yeah, I would be curious to get some people together Surma: from framework land and just weigh in on that. Jake: Yeah, it does feel on the outside, it looks much more close to the lit model than the React model, Jake: but maybe the differences are smaller than we think. But the moving elements around thing, Jake: that was pretty recent. I mean, it's been talked about for a long time, Jake: but the activity on that has been recent. Surma: I'm actually surprised that that is still not around, Surma: because like, yeah, resetting and being able to move an element around Surma: without resetting its internal state seems like such an obvious thing to have. Jake: Yeah, and you can hack it as well. Surma: Maybe it's much harder to implement than I think it is. Jake: Yeah. Surma: I don't know. Jake: I think there's just a lot of spec work to be done. So you can have an element in the DOM Jake: that is slotted in a shadow root, and you can move the slot around, Surma: Oh. Jake: and that results in the sort of de facto position of the iframe in the DOM changes, Jake: but the iframe itself hasn't been removed and reinserted. Surma: It's almost like a document fragment kind of thing. Jake: Yeah, so there are lots of cases where you can appear to move things around the DOM, Jake: while you are sort of moving them around the shadow DOM, but without causing a Jake: disconnect and reconnect. But yeah, sort of doing that in a general case, Jake: I think it's one of those things where you've got that big, Jake: you know, massive HTML doc that you have to go through and make sure, Jake: you know, dot all the i's and cross all the t's, and deal with all of the edge cases around it. Jake: Also, things like what happens with mutation observers, what happens with Surma: I mean, well, I'm about to start rabbit-holing. Jake: mutation events, you know, because unfortunately, Jake: although they're deprecated, we still have to say what happens in that case. Jake: Yeah, so I think it's just a lot of work, but it's definitely something we want on the platform. Jake: Yeah, yeah, yeah. Surma: But mutation observer seems quite obvious. Surma: If the element is observed directly, you keep going. Surma: If it was just indirectly observed by a child list, Surma: then you get a remove event. Surma: Move on. Seems obvious. Surma: But you're right. There's all these things need to be spec'd, right? Surma: Maybe it's a new observer event then. Jake: Well, but you're not, though, this is the bit where it's tricky, because you're literally, Jake: like a mutation observer would tell you this element is being removed, Jake: and then added somewhere else. But what we're talking about is something that is Jake: observably different to that. Like it's a move, rather than a remove and an insert. Jake: And so maybe you just say, okay, Surma: If it's a new type of DOM operation, it probably has to be. Jake: yeah, I think so. You either sort of slightly lie and say it's a remove and insert, Jake: or you say it's a remove and insert, but add an extra little property on it to say it's, Jake: but really, it's, it's an atomic. And I think that's the word they've Surma: It was in fact a move. Jake: been throwing around in the API. So there's a kind of atomic remove and insert. Jake: Yeah. But yeah, you're naming, naming is the last problem to solve. Surma: I mean, also, now that you say that, you know, adding a move Surma: could actually break certain custom elements, Surma: because if the assumption is so far... Surma: Like, let's say you... Jake: Exactly. Yes. So I, yeah, I use the, I use the connected callback to, to, to know that my Surma: I don't know. Well, you store a pointer to your parent. Surma: It's kind of stupid, because you have that anyway. Surma: But let's say you did. You memoized it, and you kind of went, Surma: okay, I only need to invalidate that memoized value on a disconnect, Surma: and now the move prevents that disconnect callback from being called. Surma: Ugh, web! Jake: parent chain has changed. So I imagine you'll end up with connect being past some kind of, Surma: Yeah. Surma: Or maybe connect without disconnect is the move pattern. Surma: Who knows? Jake: oh, and disconnect being past this kind of atomic Boolean or something. But anyway, Surma: Yeah, yeah, yeah. Jake: yeah. So that's, that's where all the complication comes from. That's why, again, Jake: it's, it's never as simple as you think, but it's worth solving. Surma: That's why you don't do standards, people. Jake: Yeah. So I don't do it anymore. It's too, too much, too much work. Surma: And it takes six years. Jake: It takes six years to get nowhere. Really? Surma: That's how long structured clone took. Surma: Well, not like actively working on it, obviously, Jake: Yeah. Surma: but from filing the issue to it being shipped in the first browser. Jake: Yeah. Surma: I think it was like four years of nothingness, Surma: because people were like, yeah, we're interested, Surma: but nobody wants to do the work, and it's not relevant enough. Surma: And then for some reason, a second wind came Jake: So I think custom CSS easings, like using the linear function was surprisingly fast, Surma: that now people want a structured clone again, Surma: and it got prioritized. Surma: And sometimes I think in this case, Surma: you just have to wait for the right time to come around, Surma: to quickly be ready, and then just push it through. Surma: Yeah, that was really quick. Jake: but it depends where you measure it from. Like, cause people were asking for custom easing years Jake: and years ago, but the idea of like, well, let's have a function where it linear interpolates Jake: between a series of points to writing the spec to implementations being in browsers. Jake: But even then it was still a couple of years, I think from start to finish, but Surma: Yeah. Standards are definitely on the order of years. Surma: It's really below that. Jake: yeah. Oh, well. Surma: Speaking of our release cadence. Jake: Yeah. Should we, should we, should we stop just cause we're just not nattering on about Jake: other stuff now, aren't we? Really? I mean, I know that's literally the kind of name of the Surma: Yeah. Surma: I mean, that is the tagline, but yeah. Jake: podcast. Yeah. Should we, yeah, should we, should we go, I should probably Jake: should do some actual work for Shopify, you know? Surma: Thank you, Shopify, for letting us call this work, Surma: kind of. But yeah, I should also. Jake: Yeah. Surma: Because we are both off to Toronto, so. Jake: Oh yeah. Yeah. To, to do essentially standards work, but internally. Surma: Yeah. So much for not doing standards anymore. Jake: Oh yeah. It's like chairing a working group. Surma: Damn it. Just can't let go. Jake: Yeah. Well then with that, all that's left to say is happy next time. Bye. Surma: Yeah. Surma: Happy next time. Surma: Let's go further. Not even tech of the main thread. Surma: I learned an amazing story about a Japanese marathon runner, Surma: which I just have to tell you. Surma: So this is, his name is Shizu Kanakuri. Jake: It sounded convincing. Surma: I hope I pronounce it halfway correctly. Surma: I'm sure Mariko will tell me. Surma: And he ran for Japan in the Olympics in 1912, Surma: which were hosted by Sweden in Stockholm. Jake: Okay. I'm enjoying this Wikipedia entry. Surma: And at the time, I will actually, in fact, link to the Wikipedia entry to this, Surma: because it is hilarious. Surma: A friend had sent this to me. Surma: So he came from Japan at the time. Surma: Apparently, it takes 18 days to go from Japan to Stockholm Surma: with like boats and trains and stuff. Surma: And he arrived in Stockholm and it was summer. Surma: It was hot. It was, in fact, midsummer. Surma: So when the white nights are happening, the sun doesn't really set. Surma: So he struggled to sleep. Surma: After this long trip, he didn't really like Surma: or was able to eat the local food very much. Surma: And now he was supposed to run a marathon during a heat wave. Surma: And in fact, this Olympic event has already gone down in history Jake: Oh, okay. Surma: because it's the first time an Olympic athlete died Surma: because a Portuguese runner just collapsed because of the heat wave. Jake: Oh, okay. Surma: And so Shizo, our friend, also noticed that he was struggling. Surma: And just before reaching the half point, Surma: he just said, I need to stop because he was delirious at this point Surma: and just stumbled into a random garden party Surma: that was apparently happening nearby Jake: Okay. Surma: and just drank orange juice for an hour, Surma: hanging out with a Swedish family. Surma: And he was so embarrassed Surma: that he clearly was not going to have any form of respectable time Surma: that he just decided to go home. Surma: And he didn't tell anyone. Surma: And the Olympic officials didn't know Surma: and they filed him as a missing person. Surma: And that was kind of the end of it. Surma: Oh, by the way, this marathon competition, Surma: I think there were 96 people who started Surma: and only, I think, 50 finished Jake: Amazing. Surma: because so many had to drop out because of the heat wave. Surma: Anyway, decades later, a Swedish reporter stumbled over Shizo in Japan, Surma: working as a geography teacher. Surma: And I presume after reporting back to Sweden Surma: that this guy is alive and, you know, just going about his life, Surma: Sweden offered him to finish his marathon. Surma: So he went back to Sweden. Jake: And the finishing time still has to be from when he started, of course, right? Surma: Yeah, so he went back and met the family whose garden party, Surma: the son of the man who was hosting the garden party. Surma: Apparently, the son told him like, Surma: yeah, you gave my dad the scroll with Japanese writing Surma: and it's kind of become like a treasured family heirloom Surma: because it's so beautiful and, you know, Surma: and he gave that to them as a gift, Surma: as a thank you for hosting them and giving him orange juice. Surma: And he looked at it and it was just a customs form. Surma: That he apparently gave to them. Surma: So, yeah, he then actually finished his marathon Surma: with an official time of 54 years, 8 months, 6 days, 5 hours, Surma: 32 minutes, 20 seconds and 300 milliseconds, Surma: which to this day is the Guinness World Record Surma: for the longest marathon time. Surma: And I guess he's also the only marathon runner to, Surma: while he was finishing a marathon, Surma: got married, had 6 children and 10 grandchildren. Jake: But I love that. Surma: And I just think that's an absolutely amazing story. Jake: Oh, yes. Jake: Like, yes. Jake: Link to the Wikipedia page for that. Jake: I want to read all of the extra details. Jake: That's excellent.