Putting React In The Browser

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.


  1. Surma:Ladies and gentlemen, welcome to OTMT!
  2. Surma:Is that an...
  3. Jake:Oh, that's good! No, keep going! I'm enjoying that!
  4. Surma:In the left corner, the inventor of ServiceWorker and AnyApp with a checkered background,
  5. Surma:Jaaaaaaaaaaake Archibald!
  6. Jake:And in the right corner, the inventor of... Oh, what is it? You... I think you'll find
  7. Surma:Nothing notable!
  8. Jake:Structured Clone API. I mean, yeah. It's Surma “The Surma” Surma! Amazing, right? Well, okay.
  9. Surma:Ha
  10. Surma:Wooo!
  11. Surma:Wooo!
  12. Surma:The crowd goes wild!
  13. Surma:Ah...
  14. Surma:Pfft!
  15. Jake:This has lost all credibility. I don't know if I'll put this in the show or not. We'll
  16. Surma:Yeah...
  17. Surma:But the miniscule amounts that we had, maybe...
  18. Jake:see where it goes. Can I tell you about the stupidest thing I ever did in my life? You
  19. Surma:I...
  20. Surma:I mean, of course, I thought I would know this, but now I'm...
  21. Jake:might. You might. So I went drinking with an old school friend at London Bridge, and
  22. Surma:Well, tell me, tell me, Jake...
  23. Surma:Hm...
  24. Jake:then we... I'll keep this short. We went to get the train back home as we were walking
  25. Jake:towards the train. I don't know. He somehow, like, he caught the back of my foot as he
  26. Jake:was walking. I tripped up, and my shoe flew off my foot, and in a shot that I couldn't
  27. Surma:Erm...
  28. Jake:do deliberately if you gave me a million tries, my shoe flew through the air and went
  29. Jake:between the train and the platform, just straight onto the ground. Yeah. And I looked at my
  30. Surma:Please mind the gap between the train and the platform edge.
  31. Jake:shoeless foot, I looked at my friend who was laughing a lot, and then it's like, what happens
  32. Surma:You went into the gap?!
  33. Jake:now then? What do we do? And here's where it gets stupid. I looked at the train board
  34. Jake:and saw that that train was not leaving for 15 minutes, so I went down onto the tracks
  35. Jake:and got my shoe. Well, I suggested... So I said, like, well, I could just reach down
  36. Surma:And now you were under the train.
  37. Jake:and get it, but it was a little bit far, so I suggested that he holds my ankles. But he
  38. Jake:found this whole thing so funny, he just dropped me. And I was under the train.
  39. Surma:That does seem slightly terrifying.
  40. Jake:And then I emerged from under the train with my shoe.
  41. Jake:And at the time, this all seemed like a very sensible thing to do, but it is.
  42. Surma:And the electricity under there, as well?
  43. Jake:Maybe this is why it's stupid, isn't it? This is why it was a very stupid thing to do.
  44. Jake:And I just... It's one of those things of, like, I meet up... So I met up with
  45. Jake:Frances Berryman, who I worked with at the BBC and have known for a very long time.
  46. Jake:And whenever I meet up with her, at some point, she'll go, remember the time you went under a
  47. Surma:Yeah.
  48. Jake:train, you idiot? And it's like, oh, yeah, I think I'm actually quite lucky to be alive.
  49. Jake:And, you know, not in one of those Darwin Award entries.
  50. Surma:Considering that on an airplane, now they tell you if you drop your phone, please call
  51. Jake:That is the correct thing to... Oh, hello. I dropped my shoe under a train. Can I have it
  52. Surma:a member of staff and don't move your chair because you'll just break everything.
  53. Surma:So this seems like you really should have gone to, like, train people and tell them
  54. Surma:My shoe.
  55. Jake:back, please? And yeah, no, no, that is the right thing to do. I think I, like,
  56. Jake:weirdly was embarrassed about it and decided that risking my life would be the better thing to do,
  57. Jake:which it absolutely, absolutely wasn't. But rest assured, if I dropped my shoe out of a plane,
  58. Jake:I think I would just write it off. Well, I don't know, it could be a Boeing, right?
  59. Surma:I mean, if there was any cavity that allowed you to accidentally hit the catapult, eject
  60. Jake:I'm terrified now to press that button to recline the seat in case just, like,
  61. Surma:the seat.
  62. Surma:It's right next to the eject button.
  63. Jake:part of the plane just ejects, yeah.
  64. Jake:Should we talk about the web? Right, oh, I suppose I will say thank you to Shopify for
  65. Surma:Let's talk about the web, Jake.
  66. Jake:just letting this happen. Whether you think that's a good thing or not, that's for you to decide.
  67. Surma:The way you say it, it's like they're kind of like, ah, this must happen, but I will
  68. Surma:look away.
  69. Surma:I will not dignify this.
  70. Jake:That's pretty much how it goes, pretty much how it goes. Okay, so what I want to talk about is
  71. Jake:putting React in the browser. And it's, well, it starts with a tweet from Michael Jackson,
  72. Jake:who is on the Remix team. And yes, yes, just to clarify, the tweet is this.
  73. Jake:Yesterday at a company, this is not my Michael Jackson voice, I'm just doing a vaguely other
  74. Jake:person voice. Yesterday at a company offsite, I was in a conversation with your advice and
  75. Jake:Jaffa the Cake, where we discussed a potential, that's me, yeah, we discussed a potential element
  76. Surma:It's too smart, it'll do it smart.
  77. Jake:dot replace HTML API. And I can't stop thinking about it. Think efficient DOM updating that
  78. Jake:doesn't lose state, like focus, built right into the browser, could be super powerful,
  79. Jake:and something frameworks like React could leverage internally. All right, so this API is
  80. Jake:kind of like inner HTML, but it'll do diffing. So it will, yeah, it will change as little of the
  81. Surma:My gut reaction to this is, that is actually kind of cool, because it is kind of the primitive
  82. Jake:structure as possible in order to achieve the kind of markup pattern that you've given it.
  83. Surma:brand.
  84. Surma:Even if you were to write your app by hand with JavaScript, like that's something you
  85. Jake:Exactly. And there was a lot of positive sentiment in the replies about how it's going to,
  86. Surma:do.
  87. Surma:I'm just going to interject again.
  88. Jake:this will improve performance and it will reduce the size of React and,
  89. Jake:or, you know, you wouldn't need frameworks at all for some simple cases.
  90. Surma:This reminds me of like, because we had a similar, not a similar, but there was similarly
  91. Surma:an exploration before many years ago now about what is a low level primitive we could build
  92. Jake:Oh, boy, we are going to get onto that. Yeah, hang on, hang on to that for quite a while.
  93. Surma:into the browser that helps frameworks like React, but also others.
  94. Surma:And wasn't that like template tag instantiation with like, oh, cool, okay.
  95. Jake:Because I stormed into this, you know, Twitter thread, so I was tagged in it, but to kind of
  96. Jake:really just pour misery on the whole thing, as I do, but I didn't really have enough time,
  97. Jake:space, whatever, to kind of add detail why I didn't think that this API is a good idea.
  98. Jake:So, hey, I thought I'd do it on the podcast. So why are modern frameworks good? Or why is the DX,
  99. Jake:the developer experience, good? I think it comes down to like, yeah, the DOM is this big,
  100. Jake:big old bag of state. And if you're changing the DOM, you're running commands like,
  101. Jake:you know, remove this element, add it over here, change this attribute, add this event listener,
  102. Jake:remove this other one, you're manually going from state A to B within a series of steps.
  103. Jake:And there is a lot of room for error. Whereas modern frameworks via some kind of,
  104. Jake:you know, templating system like JSX in React, they let you describe state B
  105. Jake:and the framework goes and does the minimum it can figure out that makes the DOM into that shape.
  106. Jake:So why isn't replaceHtml that? Like, why isn't it ticking that box? And the problem here is HTML.
  107. Jake:HTML is the serialized form of the DOM, but boy, is it lossy. Like, yeah. What's it got?
  108. Jake:Tag names, attributes, text nodes, child nodes, string values. Attributes can only be strings
  109. Jake:because it's a serialized string format. But there is a lot of state in the DOM that isn't
  110. Jake:captured by that, like event listeners. Yes, exactly.
  111. Surma:HTML API that Michael Jackson was kind of suggesting there, would take a string of markup,
  112. Surma:right?
  113. Surma:Which is where this lossiness that a stringified HTML cannot represent full state of a DOM
  114. Jake:Yeah, you're not getting the listeners, you're not getting properties, you're not getting, like,
  115. Surma:tree entirely or fully.
  116. Jake:the pixels on a canvas, right? It's just not there in the markup. And that's why I don't
  117. Jake:think it works. So, like, if React tried to adopt this thing, like, they would have to add in an
  118. Jake:extra layer to handle... Well, let's just talk about event listeners first. So they would need
  119. Jake:some way of knowing that an element was replaced when they expect it to have the same listener as
  120. Jake:the previous version of that element so that they could go and re-add the listener or, like, remove
  121. Jake:it if it's not supposed to have that listener anymore. So you would need a bunch of metadata
  122. Jake:coming back out. And my gut feeling is it's not worth it at that point. You'd be adding so much
  123. Surma:Also, yeah, I guess React and I guess other frameworks as well, already have this DOM
  124. Jake:code to do that. Yeah.
  125. Surma:like data structure, like objects with children, which probably resemble for many intents and
  126. Jake:Exactly.
  127. Surma:purposes, the DOM tree.
  128. Surma:So then serializing it to strings so that the browser can reparse it, probably quite
  129. Surma:wasteful.
  130. Surma:I think the goal here, like let me give you a new DOM tree or representation of a DOM
  131. Surma:tree and you figure out what actually needs to change.
  132. Surma:I think that that goal is viable.
  133. Surma:I think it just string, HTML strings might just be the wrong vessel to transport the
  134. Jake:Oh, yeah.
  135. Jake:Yeah. Agreed. And Preact is doing all of this already in 3K. So, like...
  136. Surma:information.
  137. Surma:Got to have to weave that one in there.
  138. Jake:Yeah, I know React is bigger, sure, but we're not going to be shifting the needle
  139. Jake:much in terms of download size if we put all of this in the browser, you know?
  140. Surma:Yeah.
  141. Jake:On the performance side? I'm guessing. But I feel like... And I used to make this mistake a lot.
  142. Surma:Yeah.
  143. Jake:I used to think if you took something that was written in JavaScript and just put it in the
  144. Jake:browser, it would be, like, three times as fast or whatever. It would take an eighth of the time or
  145. Jake:a tenth of the time or something. And I just don't think that's true in most cases, especially stuff
  146. Jake:that's doing a lot of DOM stuff.
  147. Surma:Yeah.
  148. Surma:JavaScript engines are just phenomenally good at running JavaScript.
  149. Jake:Oh, absolutely.
  150. Surma:I did a blog post a while ago, which I'm totally going to link now, where I was, and it's not
  151. Surma:completely apples and apples because it's really hard to do, but I was implementing
  152. Surma:a algorithm or something in WebAssembly, like in AssemblyScript in C and in Rust and in
  153. Surma:JavaScript.
  154. Jake:Was this image rotating or something else? No, it's a different thing.
  155. Surma:No, this was a similar exploration with the rotation where we thought WebAssembly would
  156. Surma:solve it.
  157. Surma:Actually, most of the performance gains came from thinking about browser caches.
  158. Surma:No, this one, I'm now doing the live clicking.
  159. Surma:Where is it?
  160. Surma:Is WebAssembly magic performance pixie dust?
  161. Surma:I was blurring.
  162. Surma:So you have, you know, pixels of an image in an array and you want to run Gaussian blur
  163. Surma:on it to blur the image.
  164. Surma:And basically, in the end, it took some, by default, JavaScript was just beating all of
  165. Jake:Oh, very good.
  166. Surma:the WebAssembly, like naively written JavaScript beat all of the naively written compiled languages.
  167. Surma:In the end, with like getting really deep and doing handcrafted optimizations, I could
  168. Surma:get all of most of the compiled languages to be close to JavaScript.
  169. Surma:C++ actually beat it in the end after I got help from good C++ developers.
  170. Surma:But JavaScript just, you know, me shitting some JavaScript on the floor ran really, really
  171. Surma:fast.
  172. Surma:Of course, there's then also the file size to consider.
  173. Surma:So JavaScript was just like, in the end, a really good tradeoff.
  174. Surma:And I guess it makes sense because JavaScript is fairly high level, which means the engine
  175. Surma:gets a lot of high level type information while it's running it to the interpreter to
  176. Surma:collect how to compile it.
  177. Surma:While, you know, at WebAssembly, you lose all that information about like, is this a
  178. Jake:Yeah.
  179. Surma:float array?
  180. Surma:Is it an image?
  181. Surma:What are the access patterns?
  182. Surma:Like in that sense, JavaScript, the language can encode a lot more that the compiler can
  183. Surma:use than low level WebAssembly.
  184. Surma:But yeah, like JavaScript is just very, very well optimized.
  185. Jake:Exactly. Yeah, it can adapt at runtime, which is great for things that are running in a tight
  186. Jake:loop, which that kind of code is. Yeah, I agree. I don't think it would be improving performance
  187. Jake:much, if at all. Especially when you have to add the extra stuff on top to make listeners work,
  188. Jake:you're probably losing. And we haven't even considered things like component references,
  189. Jake:which, you know, all the frameworks have, and you can't represent in this, like,
  190. Surma:I mean, it just compiles down to an object notation, right?
  191. Jake:replace HTML world so easily. So why doesn't React have this problem? Like, why is this
  192. Jake:totally fine in Preact, React, Vue, Svelte, all of that sort of stuff? And it's because of this
  193. Jake:templating language they use. So in React, it's JSX. It looks like HTML, but it is not,
  194. Jake:because it's able to express event listeners. It's able to express property values.
  195. Jake:Yes, exactly. And in fact, I think most of these frameworks don't surface a difference between
  196. Surma:I don't think it's just...
  197. Jake:attributes and properties. They just sort of, you look like you're writing an attribute,
  198. Jake:but you're probably using a property in most cases, but it will decide internally which to use.
  199. Surma:Yeah.
  200. Jake:And I think it's produced a generation of web developers that do not know the difference
  201. Jake:between attributes and properties. But I don't know. I think that's fine, right? It's great that
  202. Surma:Yeah.
  203. Jake:people don't have to worry about that. But if you're thinking about putting React in the browser,
  204. Jake:you have to think about that, right? This is something we have to consider.
  205. Jake:So for people, like, if you're unsure of the difference, attributes, they're the things
  206. Jake:that appear on the element in the elements panel in DevTools and in the HTML source,
  207. Jake:like id equals foo or whatever. Whereas properties are the ones on the DOM instance,
  208. Jake:so like .textcontent or .innerHTML on the element. Those are properties, not attributes.
  209. Surma:Yeah.
  210. Jake:And since they're on an instance, they don't have to be strings. So you can have .classlist,
  211. Jake:which is an object with methods and stuff. You've got .offsetheight, which is a number.
  212. Jake:You've got .value as date, which is a date on date inputs. The reason I think people get
  213. Jake:confused is there's a lot of attributes that have equivalent properties. So .id is the same as the
  214. Jake:attribute. In fact, it is just reading from the attribute, reading from the attribute and writing
  215. Surma:Oh, ID is reflected?
  216. Jake:to it, which the spec calls reflection. Id is reflected. Yep, absolutely.
  217. Surma:I was trying to remember because that's something where I'm still...
  218. Surma:I think I looked it up once and kind of didn't really memorize it because I don't interact
  219. Surma:with this enough.
  220. Surma:But I remember that Rob Dodson at the time was trying to write a guide for custom elements.
  221. Surma:Where is your source of truth?
  222. Surma:Like, do you write getter setter properties that read from the attribute?
  223. Surma:Do you have an actual property that just reflects back to the attribute?
  224. Jake:Oh, let's talk about that. Yes. So, yeah, this is where it gets confusing, is we have cases where
  225. Surma:And then, you know, the web platform is also, I think, somewhat inconsistent.
  226. Surma:Like, for example, dot value on an input field does not get reflected to the attribute.
  227. Surma:And I think once you set the property, changing the attribute does nothing, maybe?
  228. Surma:Isn't there something weird like that as well?
  229. Jake:there is reflection, but the names are different. So you've got a class attribute,
  230. Jake:but a class name property, and it is just reflection between the two, but they've got
  231. Jake:different names. But yes, the maddest one is form fields and value. Okay. Because in React,
  232. Jake:you look like you're just setting the value attribute, like in JSX or whatever, but you are
  233. Surma:I mean, it gets already weird when you think about that there is an input field with type file.
  234. Jake:not. I'm trying to think of the best way to describe this. This is going to sound...
  235. Surma:Where, right?
  236. Surma:Like, what does it look like on an attribute?
  237. Jake:Yes. Yeah. Yeah. Oh, absolutely. Yes. So value is a property that doesn't have an equivalent
  238. Surma:It just doesn't.
  239. Surma:It doesn't happen.
  240. Jake:attribute. And you can confirm this because if you write to .value with JavaScript and look at
  241. Jake:DevTools, it hasn't updated any attribute. If you type into a text field, you won't see an attribute
  242. Jake:getting updated in DevTools. So that's proof of that. But here's the thing. There is a value
  243. Jake:attribute. The value attribute is linked to the default value property. So .default value
  244. Jake:reflects or reads from the value attribute in the same way like class name and class are linked.
  245. Jake:And that sets the default value of the property. So if you have the attribute value equals foo,
  246. Jake:or you do .default value equals foo, that's the default value for that field.
  247. Jake:And if you read .value, initially, that's what you'll get back. Even if you update default value,
  248. Surma:I don't know.
  249. Jake:your .value will return the default if it's in default mode. But then as soon as the value is
  250. Jake:set, either by doing .value equals whatever, or the user interacts with the field, it switches mode,
  251. Jake:and it's now no longer doing the default thing. It's doing the actual set value thing,
  252. Jake:like whatever the user's input. Yeah, look, no wonder people don't know the difference between
  253. Jake:this stuff. Yeah, that's it. I know, I know. So yeah, diffing works because React has this format
  254. Surma:That's madness.
  255. Surma:Absolute madness.
  256. Jake:which can represent listeners and properties and non-string values and all of this.
  257. Jake:There are still gaps, like it can't represent the pixels in the canvas element. So if you're
  258. Jake:using canvas in React, you have to be careful, because if you hit a diffing path where it,
  259. Surma:True.
  260. Jake:you know, it doesn't realize that you've moved that canvas somewhere, it will end up,
  261. Jake:you know, removing one canvas and recreating another, and you lose all the pixel data.
  262. Jake:But that's, yeah.
  263. Surma:I mean, in general, any web elements, be that custom elements or native ones,
  264. Surma:that have internal state outside of the react state,
  265. Jake:Hmm.
  266. Surma:they start messing up when they get recreated and stuff and not just updated.
  267. Jake:Exactly.
  268. Surma:Video players as well.
  269. Surma:That's the infamous one where a video starts replaying from the start
  270. Surma:because React did a re-render and for some reason recreated the DOM element
  271. Surma:rather than not touching it.
  272. Jake:Yeah, absolutely. Iframes as well. Yeah, exactly.
  273. Jake:So to do this properly, you would need this declarative format, right? You would need
  274. Jake:something like JSX that can represent all of this stuff. But this is something that
  275. Jake:frameworks don't agree on. So if we just put JSX in the browser, is Vue going to drop their
  276. Jake:current templating language and use JSX instead? Is Svelte going to drop their
  277. Surma:I mean, I guess for me the idea would have been that whatever this API takes
  278. Jake:templating language and use JSX instead? I don't know, but I suspect maybe not.
  279. Surma:is an intermediate format that each framework can target with their own templating shenanigans.
  280. Jake:Yes, I agree. And so, to get a feel for how that is actually successful, we can take a step back
  281. Surma:Yeah, put it in the browser.
  282. Jake:and, like, 20 years ago or so, like, developers were asking browser dev rels to just put jQuery
  283. Jake:in the browser. Right. Just put it in the browser. And that didn't happen, but some stuff did happen.
  284. Surma:Yeah.
  285. Jake:Like, like you say, some kind of intermediatory, lower-level stuff was put in to help jQuery do
  286. Jake:its job faster and better. So I'll get into the details. QuerySelectorRole. We got that.
  287. Jake:Because the selector engine was a heavy part of jQuery. It was even its own
  288. Jake:project in the end called Sizzle. You know, a whole new implementation of selector matching,
  289. Surma:Yeah.
  290. Jake:parsing and matching. But, you know, the browsers should have this feature built in because it
  291. Jake:already has most of it there for CSS. Like, it already has the selector parser. It already has
  292. Jake:the means to select elements based on a selector. So it just had to expose it via JavaScript. And
  293. Jake:it's kind of stupid that it took so long for that to happen. The name of it sucks. It's a
  294. Jake:thing we use all the time. It's long to write out. But, you know, we got there in the end.
  295. Surma:Hmm.
  296. Jake:We also got things like element.after, element.before, and element.replacewith, I think
  297. Jake:was another. Like, a few of these methods, which they were just added for convenience.
  298. Jake:Like, they didn't perform better than the jQuery equivalents, but they,
  299. Jake:you know, made the platform nicer to use. And then we got things like CSS animations,
  300. Jake:web animations, requestAnimationFrame, because, you know, jQuery had some animations built in.
  301. Surma:I was going to ask, like in jQuery providing request animation frame,
  302. Jake:And this was better for the browser to do because it has access to things like vsync.
  303. Surma:was that like the infamous setTimeout16?
  304. Jake:Yes, it was. Because they couldn't do anything better. Like, there's literally nothing. And so,
  305. Surma:Brilliant.
  306. Surma:Yeah, of course.
  307. Jake:as soon as requestAnimationFrame became a thing, they switched to that, although,
  308. Jake:you know, a series of compatibility issues because setTimeout would run when the web page wasn't
  309. Jake:shown, whereas requestAnimationFrame would pause. So it was a compact issue for them to adopt it,
  310. Surma:Yeah.
  311. Jake:but I think they eventually did anyway. But you also get, for the declarative animations,
  312. Jake:some of them can run on the compositor and, you know, be much faster. And that's
  313. Jake:not something jQuery could have just done. So what is the equivalent for React and the
  314. Jake:current generation of frameworks? It's this kind of lower-level thing that you alluded to.
  315. Jake:And it's something that browsers have been looking at for years, and one of which you
  316. Surma:Yeah.
  317. Jake:mentioned right at the start of the topic was HTML template instantiation,
  318. Jake:which was a joint idea between Apple and Google seven years ago.
  319. Surma:Seven years ago.
  320. Jake:I know, I know. I remember hearing about it at TPAC, which is the W3C meetup.
  321. Surma:That's where I heard about it as well.
  322. Surma:It must have been my first TPAC then.
  323. Jake:Yes, it was. Yes, you were there for that one as well. Yeah, I remember.
  324. Jake:But yeah, it didn't go anywhere really beyond the dock. But there is a more recent proposal,
  325. Jake:it's still four years ago, but there was some more exploration done last year. So it's kind of,
  326. Jake:it's not dead, it might be resting. It's being looked into, absolutely.
  327. Surma:It's being looked into.
  328. Jake:Okay, DOM parts, what are they?
  329. Jake:Now, this seems like a pretty neat idea. It's essentially placeholders.
  330. Jake:So there's an attribute one, a DOM node one, and a child list, you know, a set of nodes, I guess,
  331. Jake:one. You put one of these placeholders in the DOM, and then you can update its value via the
  332. Surma:Hmm.
  333. Jake:placeholder object. So instead of setting an attribute to a string, you set it to one of these
  334. Jake:placeholders. And now you've got that kind of, you know, way of updating it. And same for nodes
  335. Jake:and stuff as well. There's also a grouping primitive. So you can group a lot of these
  336. Jake:placeholders together and update their values together, which gives you DOM batching, which
  337. Jake:removes that, like, bouncing between the DOM and JavaScript. You can kind of, you know,
  338. Surma:Yeah.
  339. Jake:in JavaScript, say, I want this, this, this, and this to happen, and then, you know, stage it and
  340. Jake:commit it.
  341. Surma:So this sounds a bit like what at the time litHTML and similar projects were trying to do
  342. Surma:not just took your JSX or markup-ish looking thing and diffed it against the current DOM.
  343. Surma:They would rather figure out which parts of your markup are actually dynamic,
  344. Jake:Yes.
  345. Surma:like are bound to a variable and remember those places and just if the variable updates
  346. Surma:it would go straight to that point in the DOM and just update it
  347. Surma:and kind of avoid this whole diff approach as much as possible.
  348. Surma:And that's also kind of what I think Preact signals are now doing
  349. Jake:Exactly.
  350. Surma:where when you pass a signal into an attribute or into the DOM,
  351. Surma:it doesn't do a whole vDOM diff if it can avoid it.
  352. Jake:Yeah, it is. So with Preact Signals right now, like, it only does the fast path for attributes.
  353. Surma:It just goes straight to the thingy.
  354. Surma:So this seems like a platformization of that.
  355. Jake:It doesn't do the fast path for, oh, sorry, you are correct, and for text nodes. It doesn't do
  356. Surma:And for text nodes, right?
  357. Jake:it for changing trees. But this DOM parts system would let you do it for trees as well. Yeah,
  358. Surma:Yeah.
  359. Jake:Lit does do this as well. It does it with, I think, the placeholders they use, well, within
  360. Jake:the DOM tree is HTML comments. I think it's the nearest thing they can get to these little markers
  361. Surma:Yeah.
  362. Jake:that they can put in. And so if you use Lit, if you go into DevTools and look at your thing,
  363. Jake:you'll see these little HTML comments dotted around the place, which is its,
  364. Jake:yeah, its kind of placeholder system. There is another part to the proposal.
  365. Jake:It's the DOM part declarative template. So this is a template element, as already exists.
  366. Jake:But inside there, if you put, and this is going to be difficult to say with words,
  367. Jake:open curly, open curly, close curly, close curly, you can imagine what that looks like.
  368. Surma:Yeah.
  369. Jake:Like a sort of mustache. Yes, yes, but with nothing in it. So, and that marks it as a part,
  370. Surma:Look at this.
  371. Surma:Handlebars, right?
  372. Surma:Oh.
  373. Jake:like a, it's kind of putting one of those little placeholders in.
  374. Jake:And then other than that, the details are kind of like, it's not clear how you would,
  375. Jake:you know, instantiate this template, how you would then get the parts out of it in an order
  376. Jake:that's reliable. That kind of stuff is still unexplored, but.
  377. Surma:It feels like the obvious choice would be you put a name in between the handlebars
  378. Surma:and you can reference the different parts by name.
  379. Jake:Well, yeah, I'd have thought that. I'd have thought that. But that doesn't seem to be
  380. Jake:the current proposal, but I think it's, I think that's a sensible way to do it. Like,
  381. Jake:you can put some metadata in there that makes it, you know, you can then
  382. Jake:query part by name or something, get part by name or whatever.
  383. Surma:Or you just get like a .parts, which is a dictionary of name to part.
  384. Jake:Oh, exactly. Oh, that's even better. Yeah. You should do API design. I should stay away from it.
  385. Jake:But yeah, it's, other than that, details lie on the ground. It does feel like this is a,
  386. Jake:you know, a mid-layer that a lot of the frameworks could benefit from,
  387. Jake:especially the batched DOM updates, like if nothing else.
  388. Surma:Yeah.
  389. Jake:Another API that I think is interesting here is there's a discussion around an API to move DOM
  390. Jake:nodes. And it sounds like, well, can't we already move DOM nodes?
  391. Surma:I was going to say, we have append and if it's already somewhere else, it gets moved.
  392. Jake:But you already hit upon the problem of this, and you mentioned it earlier.
  393. Jake:What's the problem with that?
  394. Surma:It loses state maybe?
  395. Jake:It does. And the reason it loses state is because it's, when you append a node to somewhere else,
  396. Jake:it's actually removing the node, then inserting the node. It's not a kind of atomic move.
  397. Surma:Right.
  398. Surma:So like in custom elements speak, you will literally see a disconnected callback
  399. Surma:and a connected callback.
  400. Jake:Exactly. And that is, like, again, I'm going to struggle to remember which elements this
  401. Jake:affects and which ones it doesn't. Like, you can move a canvas around and it's fine.
  402. Jake:You cannot move an iframe around because the removal steps for an iframe is to unload the
  403. Jake:inner document. Exactly. You can use a canvas outside of the DOM. Video is the one I can't
  404. Surma:Yeah.
  405. Surma:I mean, Canvas actually, you literally can remove it from the DOM
  406. Surma:and you can wait a couple of frames and reinsert and it will have the same state.
  407. Surma:Like that's literally how the Canvas element works, I guess.
  408. Surma:Yeah.
  409. Surma:So video player, I guess.
  410. Jake:remember. I think, yeah, because a video won't make noise when it's not in the DOM,
  411. Jake:so I think that is another one of the ones that will lose state when you're just moving around.
  412. Surma:Maybe it even depends on the attributes.
  413. Surma:Maybe if it's autoplay, it resets.
  414. Surma:If it doesn't, it can maintain the state.
  415. Jake:Oh, I don't know. But anyway, this is the bit they're looking to fix as well. And this will
  416. Surma:Who knows?
  417. Surma:Yeah.
  418. Jake:help. I know this is something the frameworks have asked for, is that, because it will help
  419. Jake:the case where they are wanting to rearrange. And it's not a problem unique to frameworks,
  420. Jake:but I know they want to be able to take an iframe and move it into a React portal kind of thing,
  421. Jake:and for it to survive. We've had the... Anyone who's implemented a video site where you want
  422. Surma:Yeah.
  423. Jake:to take the video and pop it into a kind of picture-in-picture, kind of like in the corner
  424. Jake:of the page as you scroll down, you're in all kinds of trouble because it's... Yeah,
  425. Jake:the horrible things you have to do to your DOM when you actually just want to move that video
  426. Jake:element. It's... Well, there you go. That's why they're so successful.
  427. Surma:Well, they have some very interesting techniques.
  428. Surma:I don't know if it's still the case, but I remember at one time when they load the page
  429. Surma:or when the page loads, they would what they called bless the video tags.
  430. Surma:So they would have multiple video tags that are in the DOM, but not visible.
  431. Surma:And they would click play on them because it's in response to some form of user interaction,
  432. Surma:which is the only way you're allowed to programmatically call play,
  433. Jake:Oh, interesting. And also, I think they use all of the lower level video stuff, right? Because they...
  434. Surma:and it actually has an effect.
  435. Surma:And that's what they would use for the autoplay feature,
  436. Surma:where they would then switch to the next video, change the source,
  437. Surma:and the video would start playing automatically
  438. Surma:because it had been blessed by a user interaction click.
  439. Surma:Oh, yeah, the media MSE and all those shenanigans.
  440. Jake:Yes, the media source extension stuff. Yeah. I think that gets them out of trouble as well.
  441. Surma:Yeah.
  442. Jake:But doing it just plain with a video element is a pain. So yeah, that's it. That's kind
  443. Jake:of where we're at. And so that's why when people say, well, let's just put this in the browser
  444. Jake:and be done with it, it's like, I get grumpy and say, this is not as simple as you think it is.
  445. Surma:No.
  446. Surma:But you said the discussion was like this was started four years ago.
  447. Jake:There was some activity in 2023. So not dead, maybe resting. I guess what they need to do is
  448. Surma:Is there still activity?
  449. Surma:Are these all dead?
  450. Surma:Are some of these still alive?
  451. Surma:Like what is the...
  452. Jake:make sure that this is of benefit to frameworks. Does this benefit React? Does this benefit Vue?
  453. Surma:I feel like, yeah, the whole here is a primitive to kind of isolate slots
  454. Surma:from different DOM elements that you can grab directly.
  455. Jake:Yeah. Yeah, I think so. I guess it would come down to how much work is it for React to translate
  456. Surma:That seems quite good to me.
  457. Jake:its current model into that? And do they get a benefit that is worth it in the end?
  458. Surma:I'd be really curious to know, like, for example, the Svelte folks
  459. Surma:who are already having this compilation step
  460. Surma:and putting a lot of powerful stuff into that step,
  461. Jake:Yeah.
  462. Surma:if they would use it, if they could basically,
  463. Surma:because you have your markup in a separate file,
  464. Surma:you have all the variables that are already reactive
  465. Surma:slotted into children or attributes and properties and all that jazz,
  466. Surma:if that for them would be like, yeah, cool.
  467. Surma:That's just a compilation target.
  468. Surma:We can adopt this in no time.
  469. Surma:It would do exactly what we need.
  470. Surma:I'm guessing other frameworks would.
  471. Surma:I think it sounds useful.
  472. Surma:But yeah, I would be curious to get some people together
  473. Surma:from framework land and just weigh in on that.
  474. Jake:Yeah, it does feel on the outside, it looks much more close to the lit model than the React model,
  475. Jake:but maybe the differences are smaller than we think. But the moving elements around thing,
  476. Jake:that was pretty recent. I mean, it's been talked about for a long time,
  477. Jake:but the activity on that has been recent.
  478. Surma:I'm actually surprised that that is still not around,
  479. Surma:because like, yeah, resetting and being able to move an element around
  480. Surma:without resetting its internal state seems like such an obvious thing to have.
  481. Jake:Yeah, and you can hack it as well.
  482. Surma:Maybe it's much harder to implement than I think it is.
  483. Jake:Yeah.
  484. Surma:I don't know.
  485. Jake:I think there's just a lot of spec work to be done. So you can have an element in the DOM
  486. Jake:that is slotted in a shadow root, and you can move the slot around,
  487. Surma:Oh.
  488. Jake:and that results in the sort of de facto position of the iframe in the DOM changes,
  489. Jake:but the iframe itself hasn't been removed and reinserted.
  490. Surma:It's almost like a document fragment kind of thing.
  491. Jake:Yeah, so there are lots of cases where you can appear to move things around the DOM,
  492. Jake:while you are sort of moving them around the shadow DOM, but without causing a
  493. Jake:disconnect and reconnect. But yeah, sort of doing that in a general case,
  494. Jake:I think it's one of those things where you've got that big,
  495. Jake:you know, massive HTML doc that you have to go through and make sure,
  496. Jake:you know, dot all the i's and cross all the t's, and deal with all of the edge cases around it.
  497. Jake:Also, things like what happens with mutation observers, what happens with
  498. Surma:I mean, well, I'm about to start rabbit-holing.
  499. Jake:mutation events, you know, because unfortunately,
  500. Jake:although they're deprecated, we still have to say what happens in that case.
  501. Jake:Yeah, so I think it's just a lot of work, but it's definitely something we want on the platform.
  502. Jake:Yeah, yeah, yeah.
  503. Surma:But mutation observer seems quite obvious.
  504. Surma:If the element is observed directly, you keep going.
  505. Surma:If it was just indirectly observed by a child list,
  506. Surma:then you get a remove event.
  507. Surma:Move on. Seems obvious.
  508. Surma:But you're right. There's all these things need to be spec'd, right?
  509. Surma:Maybe it's a new observer event then.
  510. Jake:Well, but you're not, though, this is the bit where it's tricky, because you're literally,
  511. Jake:like a mutation observer would tell you this element is being removed,
  512. Jake:and then added somewhere else. But what we're talking about is something that is
  513. Jake:observably different to that. Like it's a move, rather than a remove and an insert.
  514. Jake:And so maybe you just say, okay,
  515. Surma:If it's a new type of DOM operation, it probably has to be.
  516. Jake:yeah, I think so. You either sort of slightly lie and say it's a remove and insert,
  517. Jake:or you say it's a remove and insert, but add an extra little property on it to say it's,
  518. Jake:but really, it's, it's an atomic. And I think that's the word they've
  519. Surma:It was in fact a move.
  520. Jake:been throwing around in the API. So there's a kind of atomic remove and insert.
  521. Jake:Yeah. But yeah, you're naming, naming is the last problem to solve.
  522. Surma:I mean, also, now that you say that, you know, adding a move
  523. Surma:could actually break certain custom elements,
  524. Surma:because if the assumption is so far...
  525. Surma:Like, let's say you...
  526. Jake:Exactly. Yes. So I, yeah, I use the, I use the connected callback to, to, to know that my
  527. Surma:I don't know. Well, you store a pointer to your parent.
  528. Surma:It's kind of stupid, because you have that anyway.
  529. Surma:But let's say you did. You memoized it, and you kind of went,
  530. Surma:okay, I only need to invalidate that memoized value on a disconnect,
  531. Surma:and now the move prevents that disconnect callback from being called.
  532. Surma:Ugh, web!
  533. Jake:parent chain has changed. So I imagine you'll end up with connect being past some kind of,
  534. Surma:Yeah.
  535. Surma:Or maybe connect without disconnect is the move pattern.
  536. Surma:Who knows?
  537. Jake:oh, and disconnect being past this kind of atomic Boolean or something. But anyway,
  538. Surma:Yeah, yeah, yeah.
  539. Jake:yeah. So that's, that's where all the complication comes from. That's why, again,
  540. Jake:it's, it's never as simple as you think, but it's worth solving.
  541. Surma:That's why you don't do standards, people.
  542. Jake:Yeah. So I don't do it anymore. It's too, too much, too much work.
  543. Surma:And it takes six years.
  544. Jake:It takes six years to get nowhere. Really?
  545. Surma:That's how long structured clone took.
  546. Surma:Well, not like actively working on it, obviously,
  547. Jake:Yeah.
  548. Surma:but from filing the issue to it being shipped in the first browser.
  549. Jake:Yeah.
  550. Surma:I think it was like four years of nothingness,
  551. Surma:because people were like, yeah, we're interested,
  552. Surma:but nobody wants to do the work, and it's not relevant enough.
  553. Surma:And then for some reason, a second wind came
  554. Jake:So I think custom CSS easings, like using the linear function was surprisingly fast,
  555. Surma:that now people want a structured clone again,
  556. Surma:and it got prioritized.
  557. Surma:And sometimes I think in this case,
  558. Surma:you just have to wait for the right time to come around,
  559. Surma:to quickly be ready, and then just push it through.
  560. Surma:Yeah, that was really quick.
  561. Jake:but it depends where you measure it from. Like, cause people were asking for custom easing years
  562. Jake:and years ago, but the idea of like, well, let's have a function where it linear interpolates
  563. Jake:between a series of points to writing the spec to implementations being in browsers.
  564. Jake:But even then it was still a couple of years, I think from start to finish, but
  565. Surma:Yeah. Standards are definitely on the order of years.
  566. Surma:It's really below that.
  567. Jake:yeah. Oh, well.
  568. Surma:Speaking of our release cadence.
  569. Jake:Yeah. Should we, should we, should we stop just cause we're just not nattering on about
  570. Jake:other stuff now, aren't we? Really? I mean, I know that's literally the kind of name of the
  571. Surma:Yeah.
  572. Surma:I mean, that is the tagline, but yeah.
  573. Jake:podcast. Yeah. Should we, yeah, should we, should we go, I should probably
  574. Jake:should do some actual work for Shopify, you know?
  575. Surma:Thank you, Shopify, for letting us call this work,
  576. Surma:kind of. But yeah, I should also.
  577. Jake:Yeah.
  578. Surma:Because we are both off to Toronto, so.
  579. Jake:Oh yeah. Yeah. To, to do essentially standards work, but internally.
  580. Surma:Yeah. So much for not doing standards anymore.
  581. Jake:Oh yeah. It's like chairing a working group.
  582. Surma:Damn it. Just can't let go.
  583. Jake:Yeah. Well then with that, all that's left to say is happy next time. Bye.
  584. Surma:Yeah.
  585. Surma:Happy next time.
  586. Surma:Let's go further. Not even tech of the main thread.
  587. Surma:I learned an amazing story about a Japanese marathon runner,
  588. Surma:which I just have to tell you.
  589. Surma:So this is, his name is Shizu Kanakuri.
  590. Jake:It sounded convincing.
  591. Surma:I hope I pronounce it halfway correctly.
  592. Surma:I'm sure Mariko will tell me.
  593. Surma:And he ran for Japan in the Olympics in 1912,
  594. Surma:which were hosted by Sweden in Stockholm.
  595. Jake:Okay. I'm enjoying this Wikipedia entry.
  596. Surma:And at the time, I will actually, in fact, link to the Wikipedia entry to this,
  597. Surma:because it is hilarious.
  598. Surma:A friend had sent this to me.
  599. Surma:So he came from Japan at the time.
  600. Surma:Apparently, it takes 18 days to go from Japan to Stockholm
  601. Surma:with like boats and trains and stuff.
  602. Surma:And he arrived in Stockholm and it was summer.
  603. Surma:It was hot. It was, in fact, midsummer.
  604. Surma:So when the white nights are happening, the sun doesn't really set.
  605. Surma:So he struggled to sleep.
  606. Surma:After this long trip, he didn't really like
  607. Surma:or was able to eat the local food very much.
  608. Surma:And now he was supposed to run a marathon during a heat wave.
  609. Surma:And in fact, this Olympic event has already gone down in history
  610. Jake:Oh, okay.
  611. Surma:because it's the first time an Olympic athlete died
  612. Surma:because a Portuguese runner just collapsed because of the heat wave.
  613. Jake:Oh, okay.
  614. Surma:And so Shizo, our friend, also noticed that he was struggling.
  615. Surma:And just before reaching the half point,
  616. Surma:he just said, I need to stop because he was delirious at this point
  617. Surma:and just stumbled into a random garden party
  618. Surma:that was apparently happening nearby
  619. Jake:Okay.
  620. Surma:and just drank orange juice for an hour,
  621. Surma:hanging out with a Swedish family.
  622. Surma:And he was so embarrassed
  623. Surma:that he clearly was not going to have any form of respectable time
  624. Surma:that he just decided to go home.
  625. Surma:And he didn't tell anyone.
  626. Surma:And the Olympic officials didn't know
  627. Surma:and they filed him as a missing person.
  628. Surma:And that was kind of the end of it.
  629. Surma:Oh, by the way, this marathon competition,
  630. Surma:I think there were 96 people who started
  631. Surma:and only, I think, 50 finished
  632. Jake:Amazing.
  633. Surma:because so many had to drop out because of the heat wave.
  634. Surma:Anyway, decades later, a Swedish reporter stumbled over Shizo in Japan,
  635. Surma:working as a geography teacher.
  636. Surma:And I presume after reporting back to Sweden
  637. Surma:that this guy is alive and, you know, just going about his life,
  638. Surma:Sweden offered him to finish his marathon.
  639. Surma:So he went back to Sweden.
  640. Jake:And the finishing time still has to be from when he started, of course, right?
  641. Surma:Yeah, so he went back and met the family whose garden party,
  642. Surma:the son of the man who was hosting the garden party.
  643. Surma:Apparently, the son told him like,
  644. Surma:yeah, you gave my dad the scroll with Japanese writing
  645. Surma:and it's kind of become like a treasured family heirloom
  646. Surma:because it's so beautiful and, you know,
  647. Surma:and he gave that to them as a gift,
  648. Surma:as a thank you for hosting them and giving him orange juice.
  649. Surma:And he looked at it and it was just a customs form.
  650. Surma:That he apparently gave to them.
  651. Surma:So, yeah, he then actually finished his marathon
  652. Surma:with an official time of 54 years, 8 months, 6 days, 5 hours,
  653. Surma:32 minutes, 20 seconds and 300 milliseconds,
  654. Surma:which to this day is the Guinness World Record
  655. Surma:for the longest marathon time.
  656. Surma:And I guess he's also the only marathon runner to,
  657. Surma:while he was finishing a marathon,
  658. Surma:got married, had 6 children and 10 grandchildren.
  659. Jake:But I love that.
  660. Surma:And I just think that's an absolutely amazing story.
  661. Jake:Oh, yes.
  662. Jake:Like, yes.
  663. Jake:Link to the Wikipedia page for that.
  664. Jake:I want to read all of the extra details.
  665. Jake:That's excellent.