Canvas-based Web Apps

In this episode, Surma talks about web apps that (partly) abandon the DOM and use canvas instead, to take rendering matters into their own hands. Figma is one popular app that uses this approach, while Flutter is an entire app platform that went with this technique to provide portability. Jake and Surma discuss the tradeoffs of building apps this way.

Resources:

Transcript
  1. Jake:I guess I should do an intro. Hello!
  2. Surma:That's a good one, I like this intro.
  3. Jake:Pfff! Shut up!
  4. Jake:Oh, God.
  5. Jake:So, I am actually a little hungover.
  6. Jake:Anyway!
  7. Surma:Oh, tell me that story!
  8. Jake:Oh, well,
  9. Jake:what happens? I drank too much.
  10. Jake:And that causes you to have a hangover.
  11. Surma:Oh, I thought that would be, like, you know, people in bars with cocaine or something.
  12. Jake:No! No, I wasn't...
  13. Jake:I wasn't on travels as usual.
  14. Jake:No, this was just at home,
  15. Jake:and we were like,
  16. Jake:what if we had a bottle of wine
  17. Surma:Was it a green curry?
  18. Jake:and then another bottle of wine and a curry,
  19. Jake:and see what happens the next day?
  20. Jake:And, uh...
  21. Jake:Curry was good, wine was good, morning was bad.
  22. Jake:It was not...
  23. Jake:It was an Indian curry. It was a
  24. Jake:chicken ra-ra,
  25. Jake:which is a thing.
  26. Surma:A bit of a rah-rah.
  27. Jake:It's a delicious thing.
  28. Jake:A ra-ra.
  29. Surma:In general, I feel incredibly awkward when Thai or Indian, and I love that they put the original names on the menu,
  30. Jake:That's why there's a benefit of
  31. Jake:ordering online. I didn't have to say that out loud
  32. Jake:to a person. Hello, can I get
  33. Jake:a chicken ra-ra?
  34. Surma:but then I feel like my entire order is just me butchering another language with my ignorance.
  35. Jake:Mmm, yes.
  36. Jake:Yeah.
  37. Jake:I tried to learn Italian once,
  38. Jake:and then, for a while,
  39. Surma:Oh yeah, please, can I have the Cacio e Pepe?
  40. Jake:I was that guy in the restaurant
  41. Jake:pronouncing things with an Italian
  42. Jake:accent, until I
  43. Jake:realized that I hate that guy.
  44. Jake:And then I stopped.
  45. Jake:Yeah, exactly.
  46. Jake:Woohoo!
  47. Jake:I was doing the Mario noises as well,
  48. Jake:because obviously he's the world's most famous Italian.
  49. Surma:And the most authentic one as well.
  50. Jake:Exactly.
  51. Jake:I've got a worry
  52. Surma:Oh boy.
  53. Jake:that I want to get off my chest.
  54. Jake:So, my other
  55. Jake:half snores. She's a snorer.
  56. Surma:Are you Snorra?
  57. Jake:I don't...
  58. Surma:I mean, yeah, you said in a previous episode that the boiler kept you up, so yes, that sounds like you're a light sleeper.
  59. Jake:Well, that's
  60. Jake:the question, you see. Because I hate
  61. Jake:the fact that
  62. Jake:my other half snores. Because I feel
  63. Jake:like I'm a light sleeper, or certainly light
  64. Jake:to get to sleep.
  65. Jake:And so the whole snoring thing...
  66. Jake:Yeah.
  67. Surma:First Italian, now snoring.
  68. Jake:Exactly.
  69. Jake:Now, recently,
  70. Jake:my other half has been telling me
  71. Jake:that I have been snoring.
  72. Jake:And it's...
  73. Jake:I'm becoming what I hate.
  74. Jake:You know? It's
  75. Jake:stressing me out. I don't...
  76. Jake:Yeah, exactly.
  77. Jake:And it's
  78. Jake:been worrying me, because I don't want
  79. Jake:to be keeping her awake.
  80. Jake:And obviously
  81. Jake:it feels like a thing that happens
  82. Jake:when you get older as well, so it's kind of reminding
  83. Surma:Yeah, what's next? Are you going to start being a Nigel Farage fanboy?
  84. Jake:me that I'm getting older.
  85. Jake:But, here's a thing that happened.
  86. Jake:I got up in the middle of the night
  87. Jake:for the toilet, because...
  88. Jake:Another reminder that I'm getting old.
  89. Jake:Yeah, exactly.
  90. Jake:Yeah, that's next on the list.
  91. Jake:We'll see how long that takes. But...
  92. Jake:Went to the toilet.
  93. Jake:Got back into bed.
  94. Jake:And my other half
  95. Jake:rolled over,
  96. Jake:went...
  97. Surma:Is that a common occurrence in your relationship?
  98. Jake:She made this really angry noise.
  99. Jake:And then punched me.
  100. Surma:I have never heard myself snore, or know of anyone who has perceived themselves snoring.
  101. Jake:Well, here's the thing.
  102. Jake:She snored,
  103. Jake:got annoyed about it,
  104. Jake:and punched me.
  105. Jake:So now I'm wondering,
  106. Jake:am I actually a snorer?
  107. Jake:Or is it...
  108. Jake:Is she just dreaming about me snoring?
  109. Jake:...
  110. Jake:...
  111. Jake:...
  112. Jake:...
  113. Surma:That's hilarious.
  114. Jake:Oh, no, I have. Oh, absolutely.
  115. Jake:Yeah, I... And so this is the thing.
  116. Jake:I do know that I occasionally snore
  117. Jake:because I wake myself up snoring.
  118. Jake:Yeah.
  119. Surma:Yeah, you stop yourself, so where's the punching coming from? Clearly you would interrupt yourself.
  120. Jake:Mmm. At least I'm waking
  121. Jake:myself up.
  122. Jake:Oh.
  123. Surma:Full Fight Club mode.
  124. Jake:Yeah.
  125. Jake:Yeah, like, I thought she was punching me
  126. Jake:through the night, but then she was away for a week
  127. Jake:and I woke up with a black eye, so, you know,
  128. Jake:just...
  129. Jake:beating myself up through the night.
  130. Jake:Oh. Yeah.
  131. Jake:...
  132. Jake:...
  133. Jake:...
  134. Jake:...
  135. Jake:Hello!
  136. Jake:And welcome to another episode of
  137. Jake:Off the Main Thread.
  138. Jake:I'm Jake.
  139. Surma:Wait, is that how we start? Do we do intros?
  140. Jake:I don't know, man.
  141. Jake:This is how we're starting this one.
  142. Surma:Are you the guy who designed Service Worker?
  143. Jake:I am, actually.
  144. Jake:Oh, do you know what?
  145. Jake:There's been some interesting
  146. Jake:stuff around Service Worker.
  147. Jake:They've added static
  148. Surma:Wait, that has happened?
  149. Jake:routes to...
  150. Jake:Yeah, there's landing ads in the latest
  151. Jake:Chrome. Yeah.
  152. Surma:Sure, go.
  153. Jake:We're now doing a topic in the middle of the intro,
  154. Jake:which I don't think...
  155. Jake:Like, who are you?
  156. Surma:I'm Surma.
  157. Jake:Hi, Surma.
  158. Jake:That's good.
  159. Jake:As usual, or when we remember to,
  160. Jake:I want to thank Shopify for
  161. Jake:paying for all of this
  162. Jake:and the hosting and letting us do it.
  163. Jake:They don't ask us to say that, but we do.
  164. Jake:We do like Shopify. We like Shopify enough
  165. Jake:to both work there.
  166. Surma:Yeah, just about enough.
  167. Jake:Just about enough.
  168. Surma:So straight off the main thread, tell me about these new static routes.
  169. Jake:Yeah, well, look.
  170. Jake:I wasn't planning to talk about this,
  171. Jake:so it's really
  172. Jake:thin on the ground in terms of what's in my head.
  173. Jake:The idea is, it's in the latest
  174. Jake:Chrome, which is Chrome,
  175. Jake:whatever the latest number is.
  176. Jake:Do you know what? Let's do some
  177. Jake:Googling.
  178. Surma:Oh, I thought we were going to say, so in Chrome release, insert Chrome release, and then we can do a nice AI voice insert.
  179. Jake:Oh, look. If we're going to go off the main thread,
  180. Jake:there is this...
  181. Jake:Someone posted it. You know how articles
  182. Jake:sometimes have a button
  183. Jake:on to read the article
  184. Surma:Yeah.
  185. Jake:out loud? Well,
  186. Jake:there is a...
  187. Jake:Someone posted one of these on X,
  188. Jake:formerly known as
  189. Jake:Twitter.
  190. Jake:The article
  191. Jake:has generated this. This is not another tool doing this,
  192. Jake:but the article contains
  193. Jake:the odds of something are one in
  194. Jake:1, 0, 0, 0, 0, 0, 0, 0.
  195. Jake:And then, like, a lot of 0s.
  196. Jake:A lot of 0s.
  197. Surma:Alright.
  198. Jake:And just nothing prepares you
  199. Jake:for how that is read out.
  200. Jake:Because the voice
  201. Jake:is pretty good, pretty human-like.
  202. Jake:And it's just, you know...
  203. Jake:And the chances of that are one
  204. Jake:in...
  205. Jake:It just...
  206. Jake:Look, I'll post a link to that, because that is...
  207. Surma:Yes.
  208. Jake:I'm not doing that justice,
  209. Jake:but it's making me laugh just thinking about it.
  210. Surma:I was really impressed with OpenAI's text-to-speech, which did English pretty well.
  211. Jake:Hmm...
  212. Surma:You just give it German, it just recognizes it's German, and it sounds pretty damn good.
  213. Surma:I really haven't used it that much at all, I just played around with it for like 10 minutes.
  214. Surma:But we've been using OpenAI for our transcriptions on the podcast, and they go off the rails sometimes.
  215. Jake:Hmm...
  216. Jake:It's a little hit and miss!
  217. Jake:Hmm...
  218. Surma:I'm kind of curious if the same would happen with text-to-speech. I kind of doubt it, because it's probably a lot more deterministic in that sense.
  219. Jake:Yeah.
  220. Surma:But yeah, if you look at our transcripts, I've tried to make sure they're all good, but apparently I miss it sometimes.
  221. Jake:Hmm...
  222. Surma:And then you get art, as Monika called it.
  223. Jake:One of us is having a breakdown,
  224. Jake:where it's just...
  225. Jake:One of us going, yes, yes, yes, yes,
  226. Jake:yes, yes!
  227. Jake:Which sounds great!
  228. Jake:It just looks like you're interrupting me
  229. Jake:every other word to say yes, which I like
  230. Jake:the enthusiasm. You should
  231. Surma:Yeah, I'm just, I like your topic. It's called active listening, okay?
  232. Jake:actually do it.
  233. Jake:Right. Let's get off
  234. Jake:this thread, back onto the
  235. Surma:Pop it off the stack.
  236. Jake:off thread. Pop that off
  237. Jake:the stack. Chrome 1, 2,
  238. Jake:3. That's why I did read
  239. Jake:1, 2, 3 earlier, but I was like, well, I can't be 1, 2, 3,
  240. Jake:because that's just numbers
  241. Jake:in order, isn't it?
  242. Jake:It's also a legitimate Chrome version.
  243. Jake:Yes, the ServiceWorker
  244. Jake:static routing API.
  245. Jake:This is where, in your install event,
  246. Jake:you say, hey,
  247. Jake:for requests that look like this, do this.
  248. Jake:And this is
  249. Jake:an
  250. Jake:API sketch that we made
  251. Jake:in
  252. Jake:the very early days of
  253. Jake:ServiceWorker, before it landed in any browser.
  254. Jake:We were like, we probably need this at some point.
  255. Jake:And finally, it's actually
  256. Jake:being done. The API shape
  257. Surma:And the motivation here is it allows the browser to skip creating the service worker JavaScript scope,
  258. Jake:isn't exactly the same, but it's so you can say,
  259. Jake:yeah, requests like this, just get it
  260. Jake:from the cache, or
  261. Jake:requests like this, just go to the network.
  262. Surma:as the service worker is sleeping, and just have that as a static loop.
  263. Surma:It's faster, right? Especially when you open a page after a long time.
  264. Surma:The service worker isn't alive, everything is like, the cache is on disk, not on memory and everything.
  265. Surma:So this just makes, I guess it makes a significant speed-up possible.
  266. Jake:Yes, it is.
  267. Jake:It's a significant speed-up.
  268. Jake:We did see a lot of
  269. Jake:companies try and use ServiceWorker as a performance
  270. Jake:primitive, but it
  271. Jake:never worked out, because
  272. Jake:it has to create a
  273. Jake:worker. It has to run
  274. Jake:JavaScript.
  275. Jake:And, yeah.
  276. Jake:We knew it was not going to work, because this is why
  277. Jake:we sketched this API out in the early
  278. Jake:days. We couldn't get
  279. Jake:implementers to agree to do it, but
  280. Surma:Is it on you to do progressive enhancement, as in like to re-implement the same roots in your service worker imperative code?
  281. Jake:that is happening now.
  282. Jake:So, yes, hopefully you'll see
  283. Jake:ServiceWorker as being faster
  284. Jake:in general, but it certainly
  285. Jake:brings the capabilities of the being.
  286. Jake:Yes, it would be.
  287. Surma:I was going to say, it seems like a little mini-library, you import into your service worker and you just load that.
  288. Jake:For the time being, until all
  289. Jake:browsers support this routing API,
  290. Jake:you would have
  291. Jake:to, you know, it seems
  292. Jake:like the kind of thing that tooling could do
  293. Jake:a pretty good job of.
  294. Surma:Okay, where do you declare those static roots? In your manifest? In a separate file? How does it work?
  295. Jake:No, it's
  296. Surma:Ah, in the events, okay.
  297. Jake:all in the install event.
  298. Jake:So, you are still using
  299. Jake:JavaScript. It's one of those things where
  300. Jake:the term declarative is
  301. Jake:such a, there's a lot of gray area in the term,
  302. Jake:because it's declarative,
  303. Jake:because you're saying it up front,
  304. Jake:but you are saying it up front
  305. Jake:with JavaScript. So you could,
  306. Jake:if you wanted, create your own system where you
  307. Jake:fetch a JSON
  308. Jake:file, and then turn that into
  309. Jake:these calls for adding routes,
  310. Jake:and also, like, you know, then
  311. Jake:put that data in
  312. Surma:I mean, the good thing is that if it's already basically in imperative code in your install event,
  313. Jake:index.db so you can then do the same thing
  314. Jake:in your fetch event, or whatever.
  315. Jake:Yeah.
  316. Surma:that means that dictionary, I guess, of root to cache entry is already in your JavaScript code.
  317. Jake:Yeah.
  318. Surma:So then reusing it in your actual fetch handler is almost trivial.
  319. Jake:Exactly.
  320. Surma:Like you already have to have it in that code scope anyway, but the browser can do the smarts if available.
  321. Surma:So that's, I think it's actually in this case, quite the right choice for the API design.
  322. Jake:Yeah, so
  323. Jake:the way you match URLs is using URL
  324. Jake:patterns, and
  325. Jake:URL patterns is still
  326. Jake:like a Chromium only thing, so
  327. Surma:Is it?
  328. Jake:whatever. Yeah, but there are
  329. Jake:polyfills for it, so yeah. Anyway.
  330. Surma:I mean, yeah, the polyfill is small. I know that Safari doesn't have it.
  331. Surma:I thought Firefox did, but, well, who knows if they still have engineering resources in Safari to actually implement this.
  332. Jake:No, unfortunately not.
  333. Jake:Oh, yeah.
  334. Jake:We should.
  335. Surma:Let's give it a month and see what happens.
  336. Jake:Look, I did my
  337. Jake:shitting on Safari episode
  338. Jake:last time,
  339. Jake:so I'm going to give it a
  340. Jake:break this time.
  341. Surma:And then we do part two, the EU strikes back or the Department of Justice strikes back.
  342. Jake:Yeah.
  343. Surma:Whoever strikes back, that's the one who strikes back.
  344. Surma:Alright, so should we, I mean, I was going to say, should we talk about the web, but you kind of talked about the web.
  345. Jake:Exactly. All right.
  346. Surma:But should we talk about the main thread web?
  347. Jake:This is the thing, like, we
  348. Jake:started, well, just before we started recording,
  349. Jake:I was like, well, you know, I took over the last
  350. Jake:episode completely, so it's your turn,
  351. Jake:and here we are, like, 15 minutes in,
  352. Jake:and it's just been me talking.
  353. Surma:Yeah.
  354. Surma:Yeah, you're just an attention whore.
  355. Jake:So, come on, mate.
  356. Jake:Yeah, yeah, just, like,
  357. Jake:let's, just give me a break
  358. Jake:some. I want to
  359. Surma:Yeah.
  360. Jake:listen to something. So, your
  361. Surma:Then shut up.
  362. Jake:turn. All right. Okay.
  363. Surma:And I thought.
  364. Surma:I was going to talk a bit about.
  365. Surma:I was trying to find a good title, but I think I'm going to go with canvas based web apps.
  366. Jake:Yeah.
  367. Surma:Right, because this kind of got started with because I was talking about Bevy and I'm playing around with Bevy still.
  368. Jake:Yeah.
  369. Surma:And the game engine for us and it has an ECS pattern and blah, blah, blah.
  370. Surma:We talked about all that.
  371. Surma:But one thing that's interesting is that it runs on, you know, Mac OS, Windows Linux.
  372. Surma:But it also runs on the web because it compiles to WebAssembly and hooks into WebGPU.
  373. Surma:And so basically it just creates a canvas, gets the WebGPU context, hooks into the browsers, input events like keyboard, mouse, pointer, gamepad, whatnot.
  374. Jake:Hmm.
  375. Surma:Pipes that all into your wasmified rust.
  376. Jake:Hmm.
  377. Surma:The game engine runs as per usual and then issues the WebGPU commands to draw to the canvas.
  378. Surma:And, you know, that's cool.
  379. Surma:And I think for games that makes sense because the games don't use the DOM.
  380. Surma:The DOM is not in the vast majority of cases, not the right abstraction to do games.
  381. Surma:You want to do pixels and triangles and shaders.
  382. Surma:And so they're usually canvas bound.
  383. Jake:You can do Flappy Bird
  384. Jake:with divs, for sure, but it's
  385. Jake:not the fastest way to do it.
  386. Surma:Yeah, and even there is the question, like, should you?
  387. Surma:Is it actually the ergonomic way or the flexible way if you want to, like, because games also, you know, they optimize heavy for iteration.
  388. Jake:Hmm.
  389. Surma:You do play testing and have to do, like, little tweaks and visual adjustments.
  390. Surma:And I think sometimes the assumptions of the DOM come from document land, right?
  391. Surma:Like they're made for documents.
  392. Surma:And I think for games that is often just not a very good fit.
  393. Surma:So I think in this case, going, you know, canvas for games makes sense.
  394. Jake:Hmm.
  395. Surma:I think in this case, even going via WebAssembly makes sense because you're in canvas land anyway.
  396. Surma:So even if you wrote in JavaScript, there is a lot of things you would have to, you know, write and reinvent because you're really just like controlling pixels.
  397. Surma:And so WebAssembly can offer you benefits there.
  398. Jake:The only
  399. Jake:counter I would give to that is that,
  400. Jake:you know, we had decades
  401. Jake:of Flash games,
  402. Jake:and Flash is
  403. Jake:a scene graph, right, like, which
  404. Jake:is, the closest thing we have
  405. Surma:Yeah, I mean, the flash parallel is interesting because I remember, you know, many of the flash games that I played.
  406. Jake:to that on the web is SVG.
  407. Jake:There were pixel-based
  408. Jake:things in Flash,
  409. Jake:and I guess some games were using them, but a lot
  410. Jake:of games were just moving, you know,
  411. Jake:sprites around in a way you would, like,
  412. Jake:you know, doing animations in
  413. Jake:SVG, but, yeah, I mean,
  414. Jake:that was also in the desktop era, so
  415. Jake:yeah, how that would perform on mobile,
  416. Jake:I don't know.
  417. Jake:Yeah.
  418. Surma:And I tried to look a little bit at flash.
  419. Surma:I mean, I never really got, never understood it at the time because I just didn't have the knowledge.
  420. Surma:But, you know, the first thing you would build is a loading bar because these flash games were sizable.
  421. Jake:Yeah, well, yeah.
  422. Surma:And this is the same here.
  423. Surma:Like the toy game I'm working on, the WASM binary is 35 megabytes.
  424. Surma:And WASM compresses well.
  425. Surma:It broadly is down to six megabytes.
  426. Surma:But that's still pretty heavy for people that are, you know, bundle size obsessed like the two of us.
  427. Surma:That's a lot.
  428. Jake:Yeah, oh, for sure.
  429. Surma:I guess like, you know, many websites spend six megabytes just on a GIF, but it's a lot.
  430. Surma:To be fair, like it's unoptimized, you know, like ECS as a pattern doesn't really lend itself to tree shaking.
  431. Surma:You load plugins and then these functions run systems and they can't really tell whether there is any entities in your game that use the components,
  432. Surma:these systems processing, so that's something where I could actually go in and probably rip out a lot of stuff and optimize a bit.
  433. Surma:Anyway, so this is, again, for games.
  434. Jake:Hmm.
  435. Surma:And I think games also get a bit of a, like a free pass.
  436. Surma:They're allowed to be a bit bigger.
  437. Surma:I mean, look at what AAA games are consuming on consoles.
  438. Surma:Not that you shouldn't care, but, you know, I guess downloading six megabytes for a good game is not outrageous, especially if you cache it well.
  439. Jake:Oh, I love that thing
  440. Jake:where I, you know,
  441. Jake:I don't tend to do it anymore because of this,
  442. Jake:but when you actually buy a game on
  443. Surma:Yep. Yep.
  444. Jake:CD, and you're like, well, this is
  445. Jake:good because one of the advantages is all
  446. Jake:the data is right in my hand,
  447. Jake:so I'll just put the disk in
  448. Jake:and install it, and then afterwards
  449. Jake:it's like, I'm just going to download a little
  450. Jake:tiny update of
  451. Jake:30 gigabytes. Yeah.
  452. Surma:That's great.
  453. Jake:Yeah, okay.
  454. Surma:Now, with games, sure, but it is also kind of tempting to start thinking about Bevy and similar things for apps.
  455. Surma:Like for not like interactive 60 frames a second shooter thingies, but like apps with buttons and layouts.
  456. Jake:Hmm.
  457. Surma:And after all, like Bevy uses CSS for layout.
  458. Surma:So like this, you know, flex and grid and all these things.
  459. Surma:And it's kind of like, oh, I could just build my app with this and you gain control at a level that in the browser you sometimes don't.
  460. Surma:I think.
  461. Surma:And, you know, for me, like my immediate intuition is that for an app, the benefit cost ratio is off.
  462. Jake:Hmm.
  463. Surma:But it's worth looking at because there is, you know, a couple of apps out there that kind of take this model.
  464. Jake:Hmm.
  465. Surma:This model can be successful.
  466. Surma:Like I guess most notably Figma works in this model where the big design area they have in the middle.
  467. Jake:Yes.
  468. Surma:That's a canvas and it's driven by WASM.
  469. Surma:I think it's interesting to point out that the UI around this big canvas where, you know, you see your elements and the different attributes that is done in DOM.
  470. Surma:So they kind of do a mix and match approach.
  471. Jake:Oh, interesting.
  472. Surma:And I think that is because if you did it all in WASM, you have to reinvent a lot of wheels.
  473. Jake:Hmm.
  474. Surma:Yeah, I think they said like the text rendering for big documents just wasn't working the way they needed to and couldn't control it enough.
  475. Jake:Oh, for sure. Like, lots
  476. Jake:of mouse interaction stuff, which I guess they are
  477. Jake:somewhat doing as well.
  478. Jake:I'm actually just clicking around Google Doc
  479. Jake:here because I feel like
  480. Jake:Google Docs
  481. Jake:is Canvas. It looks, again, it's a
  482. Jake:mix. It seems like big areas
  483. Jake:of text are just Canvas
  484. Jake:element.
  485. Jake:Yeah.
  486. Surma:So I guess the text area might be different, but I guess the UI outside is still DOM.
  487. Surma:I don't know.
  488. Surma:I vaguely remember something like that.
  489. Jake:It's weirdly
  490. Surma:But yeah, I.
  491. Jake:chunked little bits of Canvas. Sorry,
  492. Jake:I'm now, like, yes, all
  493. Jake:your toolbar buttons are DOM,
  494. Jake:whereas the main text is
  495. Jake:a kind of, yeah, chunks of Canvas.
  496. Jake:It's quite, yeah, all right. Well, that was fun.
  497. Jake:Sorry.
  498. Surma:Interesting, I guess.
  499. Surma:I guess you would want to like cache them, the pages, because, you know, most of them will be static.
  500. Jake:Hmm.
  501. Surma:Like, you know, yeah, I don't know.
  502. Surma:I don't know.
  503. Surma:I guess that would be an interesting deep dive to do at some point.
  504. Surma:But yeah, like I was playing out with Bevy and kind of realizing I get a lot of very interesting control and I can avoid things that are slow in CSS because I have very granular control over like which algorithms to use, which cost to pay.
  505. Surma:But it also means you lose access to a lot of things that the browser has already done for you.
  506. Jake:Hmm.
  507. Surma:Like, for example, you know, Bevy implements a scene graph with the whole concept of you can have children elements on a parent element.
  508. Surma:And if you move the parent element, all the children move as well.
  509. Jake:Hmm.
  510. Surma:The browser already has this logic in the DOM and CSS.
  511. Surma:It even has it for 3D.
  512. Surma:You can literally rotate a DOM element in 3D space and the children will rotate the same way in 3D space.
  513. Surma:It's already there.
  514. Jake:Yes.
  515. Surma:But if you go canvas, you have to reimplement all of that where you propagate a change to a parent down to the children and vice versa.
  516. Jake:Hmm.
  517. Surma:You know, if the user clicks the mouse, you have to do hit testing.
  518. Surma:You have to figure out which element is currently under my mouse cursor.
  519. Surma:The browser has that logic built in where, you know, the browser just gets here are the mouse coordinates on screen and the browser figures out, OK, that means this DOM element is the one that has been clicked.
  520. Jake:Yes. And there's lots of
  521. Surma:...
  522. Jake:subtlety there. Like, you know, was this
  523. Jake:a tap on an interactive
  524. Jake:element, or was this a
  525. Jake:drag to scroll?
  526. Jake:And, yeah, that is all
  527. Jake:just built into the browser for you.
  528. Surma:Yeah.
  529. Surma:...
  530. Jake:But if you're handling scrolling yourself,
  531. Jake:if you're handling interactivity yourself,
  532. Jake:that is code you are going to write again
  533. Surma:Exactly.
  534. Surma:...
  535. Jake:and probably get it slightly different
  536. Jake:to the platform because it's probably
  537. Jake:different between iOS and
  538. Jake:Windows and Mac and all of that.
  539. Surma:And that's one of the parts where I really realized that this rabbit hole is really deep because I was building a menu, you know, the opening menu of a game where you have play, settings, options and quit or something.
  540. Jake:Hmm.
  541. Jake:Hmm.
  542. Surma:And I realized, you know, I have to catch intercept the arrow, like I have to listen to the arrow keys and then keep the state where the focus currently is and figure out what is the next element.
  543. Surma:And I realized I'm kind of like reinventing spatial navigation.
  544. Jake:Yes.
  545. Surma:And I was saying, you know, if I were to, yeah, if I were to make like a drop down, you know, in browsers, when you have a drop down, you can start typing and it jumps to the value that starts with the same letters.
  546. Jake:Spatnav.
  547. Jake:Hmm.
  548. Surma:...
  549. Jake:It's very different between platforms
  550. Surma:Exactly.
  551. Jake:as well, but yes, yes.
  552. Surma:And so I was thinking, you know, that is something that people in their browsers are probably used to very specific behavior.
  553. Jake:Yeah.
  554. Surma:And now you are building probably new behavior doesn't match any of the browsers or at best one of the browsers.
  555. Surma:...
  556. Surma:So that's also something where you actually provide like this uncanny valley experience to your users if you go down this route.
  557. Jake:Hmm.
  558. Surma:...
  559. Jake:Hmm. Yeah.
  560. Jake:This is the tricky part with, like, customizable selects
  561. Jake:as well is, like,
  562. Jake:yeah, right now browsers are free
  563. Jake:to show a select element
  564. Jake:however they want, and you see that with
  565. Jake:the difference between mobile and
  566. Surma:Yeah.
  567. Jake:desktop.
  568. Surma:...
  569. Jake:Whereas, yeah, to create a customizable system,
  570. Jake:it's going to have to be somewhat the same.
  571. Surma:I guess the point I make is this is all code that is going to be shipped, like has to go down the wire in your WASM to run.
  572. Jake:Hmm.
  573. Surma:And that's, I think, where these 35 megabytes eventually come from, because there's all this code that is technically already in the browser.
  574. Jake:Hmm.
  575. Jake:Hmm.
  576. Surma:But you decide that you want full control and there's no way for you to reuse what the browser already has.
  577. Jake:Hmm.
  578. Jake:Hmm.
  579. Surma:You have to start from pretty much scratch.
  580. Jake:Hmm.
  581. Surma:And yet there is, I feel like there is a bit of like a trend, not a trend, but there are some people exploring this more and more.
  582. Jake:Hmm.
  583. Jake:Hmm.
  584. Jake:Hmm.
  585. Surma:Especially with WebAssembly becoming more capable, more integrated or integratable with browser APIs.
  586. Jake:Hmm.
  587. Jake:Hmm.
  588. Surma:And that you can just, you know, you can just use WebGPU from within WASM.
  589. Jake:Hmm.
  590. Surma:I say just, there's a bit of magic happening, but it's, you can do it.
  591. Surma:And it's not slow doing these back and forth calls between WASM land and browser land.
  592. Jake:Hmm.
  593. Surma:So it's becoming more viable.
  594. Surma:And one platform, I guess, that is trying to see this through to the end is Flutter, right?
  595. Jake:Hmm.
  596. Jake:Hmm.
  597. Surma:Like you, that's the whole, you write your code.
  598. Surma:It's kind of right once run everywhere again.
  599. Jake:Hmm.
  600. Surma:But you write your app, you write in Dart, and then you can build it to Android, iOS, web, and even desktop native kind of thing.
  601. Jake:This is where I'm getting
  602. Jake:excited about this topic because I remember
  603. Jake:looking at Flutter a while ago
  604. Jake:and not
  605. Surma:Yeah, so I should, you know, ask, like I did look at Flutter in preparation for this.
  606. Jake:liking what I saw, and I know you've
  607. Jake:well, because of
  608. Jake:how they reinvent
  609. Jake:the world, and I'm
  610. Jake:interested to know if they've changed
  611. Jake:their practices.
  612. Surma:And, you know, I look at some demos and I want to talk about those, but obviously I am not an expert.
  613. Surma:I'm not involved in the Flutter ecosystem at all.
  614. Surma:But I will say I was kind of impressed.
  615. Surma:There's also things I don't like, but like in terms of, there are clearly things that are not perfect.
  616. Jake:Hmm.
  617. Surma:There are things that are uncanny valley, but they have done a thorough job as far as they could take it.
  618. Jake:Hmm.
  619. Jake:Oh, okay.
  620. Surma:So, and the thing, what I always liked about Flutter or what I was always jealous of is that they just went with, you know what?
  621. Jake:Hmm.
  622. Surma:We are going to animate layout.
  623. Surma:Like the cardinal sin of web development, if you animate any CSS properties or layout like margin or position or anything like that,
  624. Jake:Hmm.
  625. Surma:like Paul Lewis will appear and slap you on the wrist because you are doing things slow.
  626. Jake:Hehehe.
  627. Surma:It's not on the compositor.
  628. Surma:And in Flutter, they're like, oh, we kind of just designed our layout system to handle doing layout on every frame.
  629. Jake:Okay.
  630. Surma:They can do it at 120 frames per second, which is kind of amazing when you think about,
  631. Surma:and this is something the demo that I found online shows, they have similar to media queries breakpoints where, you know,
  632. Surma:like on mobile, you have multiple sections underneath each other, but on a wider screen, they kind of shift next to each other.
  633. Jake:Hmm.
  634. Surma:If you resize your window, it doesn't just snap.
  635. Surma:These boxes are animated into their new position.
  636. Surma:And that's slick.
  637. Surma:It looks really cool.
  638. Jake:Nice.
  639. Surma:And so, yeah, it does work and you get that across the platforms, like no matter whether you're Android, iOS or web,
  640. Surma:like that will work because they are taking full control at the lowest level.
  641. Surma:One thing that I found was really like ironic as I was looking at the showcase section on the website,
  642. Surma:which has like a little animation of logos of the companies that are using Flutter.
  643. Surma:And it's a 1200 by 1600 GIF that weighs six megabytes and looks really jank because it's 30 frames per second.
  644. Jake:Hehehe.
  645. Surma:And I was like, if you have the system that can compile to web, why are you doing this?
  646. Jake:Amazing.
  647. Jake:Yeah.
  648. Jake:Oh, and I'm sure
  649. Jake:even then, any video format
  650. Jake:would have been better than that GIF, right?
  651. Surma:Probably, yeah, this should be, I don't know, not AVIF, but an AV1 or why not a Flutter app?
  652. Jake:Yeah.
  653. Surma:It could be, it would probably be smaller, definitely smaller than six megabytes.
  654. Jake:Yeah, absolutely.
  655. Surma:Anyway, so like I looked at, they have a couple of demos.
  656. Jake:Yeah.
  657. Surma:I looked at the showcase demo for Material 3 and I'll link to this in our description.
  658. Jake:Hmm.
  659. Surma:So that one is not WebAssembly.
  660. Surma:That's, they compile your Dart to JavaScript and add all their runtime stuff and then use CanvasKit to do the rendering.
  661. Surma:CanvasKit is kind of surprised me here because CanvasKit is Canvas compiled to WebAssembly.
  662. Surma:So like Skia, the engine that Chrome uses to render Canvas, if you compile that to WebAssembly, that's called CanvasKit.
  663. Jake:Hmm.
  664. Jake:Hmm.
  665. Surma:And I'm sure they have their reasons, but it's kind of weird to me that they're loading CanvasKit when you have the Canvas in the browser.
  666. Surma:I'm assuming that CanvasKit offers you more control than what the browser Canvas currently offers.
  667. Jake:Or it's a
  668. Jake:cross-platform thing, maybe.
  669. Surma:Oh yeah, maybe it's that, but you know, like it's basically what it adds up to this.
  670. Jake:You know.
  671. Surma:This demo adds up to 2.5 megabytes.
  672. Surma:So it's 1.5 for the WebAssembly CanvasKit and one megabyte.
  673. Jake:Hmm.
  674. Surma:So CanvasKit is Wasm, but your code doesn't compile to Wasm, your Dart code from your app.
  675. Jake:Hmm.
  676. Surma:So yeah, and the CanvasKit WebAssembly is 1.5 megabytes and your Dart compiled to JavaScript ends up being a megabyte.
  677. Surma:There is in their beta channel support for WebAssembly.
  678. Surma:It is currently, as far as I understand, Chrome only because they rely on Wasm GC.
  679. Jake:Oh, yeah.
  680. Surma:So it allows them to not having to re-implement a garbage collector.
  681. Surma:I don't know if it performs faster or slower.
  682. Jake:Hmm.
  683. Surma:I didn't benchmark it, but it is smaller a little bit.
  684. Surma:Rather than 2.5 megabytes, it's 2 megabytes where your app code is now 700 kilobytes rather than a megabyte.
  685. Jake:Hmm.
  686. Surma:And they use a new fork, I guess, of CanvasKit called SKWasm, which is quote unquote only 1.1 megabyte.
  687. Jake:Hmm.
  688. Surma:I'm assuming it's a bit more tailored to the use case and they're probably removing some stuff that they don't need.
  689. Jake:Hmm.
  690. Surma:Not quite sure, but that's just for fairness that they are working on a WebAssembly version.
  691. Jake:Okay.
  692. Surma:So I guess with these sizes, the first load is definitely just going to be a bit meh compared to a handcrafted DOM-based solution.
  693. Surma:But to their credit, even the default template, when you get started, immediately ships with a service worker
  694. Surma:and caches all these static runtime thingies so that the second load is pretty snappy.
  695. Jake:Okay.
  696. Surma:Gotta give it to them.
  697. Surma:Even though they are definitely transferring lots of data, they're doing their best to make that work.
  698. Jake:Okay.
  699. Surma:And so, yeah, I mean, what do you get for that kind of file size?
  700. Surma:You get that animated layout that works.
  701. Surma:You resize the window and the things move around.
  702. Surma:It's really cool.
  703. Surma:Tab works.
  704. Surma:They rebuilt that.
  705. Jake:Right.
  706. Surma:Not only that you can focus through with tab, but they even have a bunch of custom elements to integrate with the browser's ARIA roles and screen readability.
  707. Surma:It seems correct.
  708. Jake:No.
  709. Surma:It seems all right.
  710. Surma:I worry that it's not matching the browser's native tabbing behavior across browsers because I don't think tabbing behavior is standardized.
  711. Jake:No.
  712. Surma:I'm not a screen reader user, so I don't know what that feels like for a screen reader user who might be used to a specific tabbing behavior on a normal web page.
  713. Surma:And now this one may be feeling navigating it differently.
  714. Surma:I don't know if that will make screen reader users get lost or not.
  715. Jake:It's just so much code
  716. Surma:That's just a worry.
  717. Jake:to do what's already there, so
  718. Jake:it's making me sad still.
  719. Surma:It is, for sure.
  720. Surma:And that's the other side.
  721. Surma:What do you lose?
  722. Surma:One of the first things I noticed.
  723. Surma:You can't select text.
  724. Surma:There's all this.
  725. Jake:Oh, right!
  726. Surma:I think it's something you can build or maybe you can have a...
  727. Surma:I'm sure that's been solved where you can probably say this text should be selectable.
  728. Surma:But if you have a sidebar with menu entries, you can't select those texts.
  729. Surma:As far as I could tell, in input fields, you don't get autocomplete.
  730. Jake:Hmm.
  731. Surma:Extensions will not work if they usually have something, I don't know, sensors backwards or you have some custom color styling to, I don't know, maybe to address a site inhibition that you have.
  732. Jake:Hmm.
  733. Jake:Hmm.
  734. Surma:Or ARC's new zapping feature.
  735. Surma:Or not new, but ARC's zapping feature where you can remove certain DOM elements or restyle them.
  736. Jake:Hmm.
  737. Surma:All of this won't obviously work.
  738. Surma:And that makes me think, I'm guessing, does SEO even work with Flutter?
  739. Jake:Hmm.
  740. Surma:Because there's nothing in text in the HTML.
  741. Surma:There is some text in the ARIA tree, but I'm not sure that's respected or consumed by crawlers.
  742. Surma:Anyway, so this is not like me wanting to go Flutter is good or Flutter is bad.
  743. Jake:Hmm.
  744. Jake:Interesting.
  745. Surma:That's just like as a platform that is doing this with, I suspect, lots of funding and engineering power and engineering expertise behind it.
  746. Surma:And this seems like the best they can do.
  747. Surma:That's why I think it's an interesting signal of where we are at in this world.
  748. Jake:Hmm.
  749. Surma:And that kind of reminded me of somewhat abstract proposal by Hixie that he put out a while ago.
  750. Surma:So I guess some people may not know Hixie.
  751. Surma:He's like the original author of the ACID2 and ACID3 tests.
  752. Surma:He was a spec author on HTML and CSS and came up with PingBag.
  753. Surma:And then until recently, yeah.
  754. Jake:HTML5 was
  755. Jake:his, yeah.
  756. Surma:And until recently, he worked on Flutter.
  757. Surma:He left, I think, at the end of last year, but he worked on this.
  758. Jake:Hmm.
  759. Surma:So that puts a bit of context, I guess, where he came up with this.
  760. Jake:Hmm.
  761. Surma:Basically, what he was proposing, it's a public document, so I'll link to it in the description.
  762. Surma:He called it towards a modern web stack.
  763. Surma:I would call it a minimal web stack, but he was basically saying,
  764. Surma:what if we focused the platform standardization efforts towards four major API services?
  765. Jake:Hmm.
  766. Jake:Hmm.
  767. Surma:WebGPU, WebAssembly, ARIA, and HID.
  768. Surma:Which, if you think about Flutter, that makes sense.
  769. Jake:Right.
  770. Surma:So you want rendering.
  771. Surma:You want code execution.
  772. Surma:You want, I guess, ARIA for like, you know, SEO, but also accessibility,
  773. Surma:that kind of like reflection API, so that external systems can inspect
  774. Surma:what is kind of being shown on screen.
  775. Surma:A standardized way to represent what is on screen, semantically speaking.
  776. Jake:Hmm.
  777. Surma:And HID, human interface devices, to give the user inputs.
  778. Surma:I guess output isn't really in here.
  779. Surma:Like, there's no web audio, I just realized, or anything like that.
  780. Surma:I'm guessing that would also be part of it.
  781. Jake:Yeah, you'd want that.
  782. Jake:It is just like taking all of the lowest level
  783. Jake:things we have on the web.
  784. Surma:Yeah.
  785. Surma:Yeah.
  786. Jake:So I guess you'd have
  787. Jake:file system API there at some point.
  788. Jake:But it's kind of like, what is the lowest
  789. Jake:of low level?
  790. Jake:It'd be interesting to know what the proposal there was
  791. Jake:for storage and stuff like that.
  792. Jake:Do you want some kind of
  793. Jake:byte storage system? But maybe
  794. Jake:file system would give you that, I guess.
  795. Jake:I don't know.
  796. Surma:Like, origin file system access would probably be enough,
  797. Jake:Hmm.
  798. Surma:and then extra permission if you want actual file system or something.
  799. Surma:I feel like we have, like, a lot of the puzzle pieces are kind of there.
  800. Surma:I'm guessing the ARIA one is the one that's most lacking to actually integrate.
  801. Surma:And also, in my head, it's like, yes, those are the lowest level primitives,
  802. Surma:and they should be as powerful and flexible as they can be.
  803. Jake:Hmm.
  804. Surma:But what I think that should be, obviously, I think this is completely
  805. Surma:unrealistic at this point, also because of backwards compatibility.
  806. Surma:But I kind of feel like what would be cool is to work towards, like,
  807. Surma:a modular browser.
  808. Surma:Like, again, like, this is never going to happen at this point,
  809. Surma:but it feels kind of cool where, yes, you have these low-level primitives,
  810. Surma:like the ones that Higgs suggested, but on top of that,
  811. Surma:you have a whole battery of kind of, like, standardized modules.
  812. Surma:You have your CSS cascade module, your CSS layout module, your DOM module.
  813. Jake:Hmm.
  814. Surma:Basically, anything that's a web standard would be a module
  815. Surma:that the browser provides and loads by default.
  816. Surma:But you, as a developer, you could opt out of any individual module
  817. Surma:and just, like, not use it or maybe provide your own replacement.
  818. Surma:So if you don't want to pay the cost for multi-pass layout,
  819. Surma:you could provide your own CSS layout module as a WebAssembly module.
  820. Surma:You want to go back to, like, vBasic script tags?
  821. Jake:Oh, VBasic as in Visual Basic.
  822. Surma:Go for it.
  823. Surma:Just replace the JavaScript module with your vBasic module
  824. Surma:that is compiled to WebAssembly.
  825. Surma:Yeah.
  826. Jake:I thought you were sort of
  827. Surma:Is it basic? No, like, the visual.
  828. Jake:regressing into German there.
  829. Jake:VBasic?
  830. Surma:But the script tag.
  831. Surma:Well, it was script language vBasic, wasn't it?
  832. Surma:I never used it.
  833. Jake:Yeah, it was.
  834. Surma:I just remembered that was a thing where, you know, you could do that.
  835. Jake:VBScript.
  836. Jake:Yeah.
  837. Surma:Like, I don't think this is going to happen,
  838. Jake:Oof.
  839. Surma:and I'm not sure it is actually worth putting steam behind this.
  840. Surma:But there were some, you know, developments in this direction.
  841. Surma:Like, Houdini.
  842. Jake:Well, Houdini.
  843. Surma:Yeah, like, at least for CSS, it did try to, like,
  844. Jake:Right, there we go.
  845. Jake:Yeah.
  846. Surma:provide your own paint routine with CSS paint worklet,
  847. Surma:even though I think it was a bit cut off at the knees
  848. Surma:in terms of what it could do.
  849. Surma:But they had plans for, like, augment the parser,
  850. Jake:Yeah.
  851. Surma:provide your own CSS parser extension,
  852. Surma:or they had the layout worklet to provide your own layout
  853. Surma:where you could...
  854. Surma:I guess this would be interesting if it hasn't happened.
  855. Surma:It was never really fully specified.
  856. Jake:Hmm.
  857. Surma:I think it was like a prototype behind the flag.
  858. Surma:But I think, theoretically, it could have allowed you
  859. Surma:to just make layout so cheap or fast
  860. Surma:that you could end up in a world like Flutter
  861. Surma:where you can just run layout in every frame.
  862. Surma:If you don't do floats and don't do intrinsic sizing
  863. Surma:and it's always single pass top-down,
  864. Jake:Hmm.
  865. Surma:that could have worked.
  866. Surma:But sadly, I think Houdini has not really made any progress.
  867. Surma:It's kind of stagnated.
  868. Surma:I think the focus is currently somewheres...
  869. Jake:Yeah, it feels abandoned,
  870. Jake:doesn't it, at this point?
  871. Surma:Yeah, a little bit.
  872. Jake:It's a shame, isn't it? Because every
  873. Jake:runtime CSS polyfill
  874. Jake:sucks.
  875. Jake:It's rubbish.
  876. Surma:Yeah.
  877. Jake:They're good enough for playing
  878. Jake:around with. They are not good enough
  879. Jake:for production because they are slow
  880. Jake:and there's
  881. Jake:booby traps everywhere.
  882. Surma:Yeah.
  883. Jake:It's going to not behave like
  884. Jake:the real thing because just
  885. Jake:CSS is not extensible
  886. Surma:One of the last things I did when I was still at Google
  887. Jake:in that way.
  888. Surma:was writing a polyfill for container queries,
  889. Jake:Hmm.
  890. Surma:which I was quite proud of because it was very small
  891. Jake:Hmm.
  892. Surma:but did most of the things.
  893. Surma:And I put in a readme, like,
  894. Surma:this is very much intentionally a pragmatic approach.
  895. Surma:Like, I want to solve the 80% use case for container queries
  896. Surma:without having to implement a full CSS engine.
  897. Surma:I think it did it all right.
  898. Surma:You know, the kind of thing where it's not going to work
  899. Surma:with the cross-origin at import statements
  900. Surma:or anything like that.
  901. Jake:Right.
  902. Surma:But like I said, it would be mostly for playing around with
  903. Surma:not to actually high-fidelity polyfill the functionality
  904. Surma:because it's nigh impossible with almost all CSS features.
  905. Jake:Yeah.
  906. Jake:Yeah, a little peek behind the
  907. Jake:curtain for folks there is that
  908. Jake:we would make those kind of polyfills
  909. Jake:to get people excited about features, to get people
  910. Jake:playing with them and testing them and saying what they
  911. Surma:Yeah.
  912. Jake:liked and didn't like. The downside
  913. Jake:of it is we ended up with Chrome
  914. Jake:project managers
  915. Jake:going out and saying that this
  916. Jake:feature is now cross-browser because
  917. Jake:the polyfill exists
  918. Surma:Yeah.
  919. Jake:and that, like, we found
  920. Jake:incredibly frustrating and
  921. Jake:we felt it was a lie.
  922. Jake:It was really
  923. Jake:misleading.
  924. Jake:Before I left,
  925. Jake:we kind of wrote up
  926. Jake:what the rules
  927. Surma:Yeah.
  928. Jake:for saying something is cross-browser
  929. Jake:and part of that was to explicitly say
  930. Jake:polyfills don't count
  931. Jake:unless they count
  932. Jake:as gold standard polyfill
  933. Jake:and I wrote this definition which basically
  934. Jake:meant the only thing that would pass
  935. Jake:as gold standard really would be little
  936. Jake:JavaScript methods being added, like
  937. Jake:if they come up with a new array method
  938. Jake:because you can polyfill that 100%.
  939. Surma:Yeah.
  940. Jake:Yeah, so these are the polyfills which are
  941. Surma:Yeah.
  942. Jake:kind of doing it, but it's going to be too slow
  943. Jake:for production and it's going to be messy
  944. Jake:all around the place.
  945. Surma:Would transpilation count?
  946. Surma:Like, you can have now async iterators if you run Babel first.
  947. Jake:So,
  948. Jake:I wanted
  949. Jake:transpilation to count, but I think
  950. Jake:others didn't, so I don't think it does count.
  951. Surma:Hmm.
  952. Jake:But yeah, I think
  953. Jake:transpilation is sort of okay.
  954. Surma:I don't think I have, like, a big hitting summary to end on.
  955. Surma:I just thought I find a really interesting thought experiment
  956. Surma:to think about what if you could take more low-level control
  957. Surma:of how your apps are being consumed by the browser
  958. Surma:without having to reinvent all the wheels
  959. Surma:and ship down that code.
  960. Surma:It definitely, like, in certain specific contexts,
  961. Surma:I think it is the right choice.
  962. Surma:Like, did Figma make the right choice with going Canvas and Wasm?
  963. Jake:I think
  964. Surma:I mean, they're doing the mix-and-match approach,
  965. Surma:but I'm assuming they did it for good reason.
  966. Surma:I feel like they would.
  967. Surma:It is a heavy lift to build the thing that they built.
  968. Jake:if you were going to recreate Figma with
  969. Jake:let's say SVG,
  970. Jake:you're going to have
  971. Jake:to control tabbing
  972. Jake:anyway because
  973. Jake:the order, the layering of
  974. Jake:things, you
  975. Jake:would have to implement spatial navigation of sorts,
  976. Surma:Yeah.
  977. Jake:right, and
  978. Jake:trying to make sure the correct semantics are there
  979. Jake:for the text and things like arrows
  980. Jake:from one thing to another. I think
  981. Surma:Yeah.
  982. Jake:the web doesn't have a ton to offer them there
  983. Jake:for that kind of thing, so
  984. Jake:going for
  985. Jake:WASM canvas rather than SVG,
  986. Jake:it seems totally
  987. Jake:reasonable if they got a performance benefit
  988. Jake:from it. I don't think they're throwing away
  989. Jake:a lot of stuff
  990. Jake:that the browser gives them already, whereas I do
  991. Jake:feel that Flutter is.
  992. Jake:I worry I'm
  993. Jake:being too negative on Flutter
  994. Jake:because another peek behind the curtain,
  995. Jake:what would happen
  996. Jake:when we were at Chrome?
  997. Jake:The Chrome developers'
  998. Surma:Yeah.
  999. Jake:Twitter account,
  1000. Jake:we had the keys to that, but so
  1001. Jake:did various marketing teams
  1002. Jake:and we would
  1003. Jake:wake up sometimes to find
  1004. Jake:a tweet on
  1005. Jake:the Chrome account essentially saying
  1006. Jake:you want to build any kind of web app? You should use
  1007. Jake:Flutter and nothing else.
  1008. Jake:They'd be like, excuse me?
  1009. Surma:Yeah.
  1010. Surma:Yeah.
  1011. Jake:I'd just go in and delete it and then
  1012. Jake:there'd be a ton of fuss.
  1013. Jake:I'm going to delete that and then America will wake up
  1014. Jake:and then we can have a little chat about it.
  1015. Jake:I used to get frustrated at that
  1016. Surma:Ah.
  1017. Jake:especially because
  1018. Jake:the other thing that we were trying to
  1019. Jake:say is please
  1020. Jake:don't re-implement everything the browser already has
  1021. Jake:to end up shipping
  1022. Jake:two megabytes to display a heading.
  1023. Surma:No.
  1024. Jake:I maybe should be more open-minded about it.
  1025. Jake:I do agree.
  1026. Surma:No, like, I think it's, like, for normal apps,
  1027. Surma:they literally, in Bevy as well,
  1028. Surma:like, you literally ship an entire font rasterization engine.
  1029. Surma:Like, that's not trivial.
  1030. Surma:Like, on one hand, amazing that Bevy has an implementation of that,
  1031. Surma:but they read the font files and, like, rasterize all of that
  1032. Surma:with hints and subpixel rendering.
  1033. Surma:But at the same time, like, it's in the browser.
  1034. Jake:You can, right?
  1035. Surma:Wouldn't it be cooler if we could hook into that?
  1036. Jake:You can use a regular canvas element
  1037. Jake:and write text to it.
  1038. Jake:I imagine Devi's not doing it
  1039. Surma:Yeah.
  1040. Jake:for the same reason as Flutter.
  1041. Jake:It's to be cross-platform.
  1042. Jake:To be cross-platform, it's easier for them
  1043. Jake:to implement everything their way from scratch
  1044. Jake:because then it's the same.
  1045. Surma:I think for Bevy, it's actually more like it's an open-source,
  1046. Surma:unpaid project until recently,
  1047. Surma:where it's just, like, passionate people working,
  1048. Surma:and that is just the easier thing to do to, you know,
  1049. Jake:Oh, yeah, yeah.
  1050. Surma:load a rasterization.
  1051. Surma:What is it called? Is it called Harfbuzz?
  1052. Surma:They're pretty much the de facto standard for font rendering,
  1053. Surma:and they're having bindings to that.
  1054. Surma:But I was thinking, like, it would be cool if I could literally
  1055. Surma:generate the font atlas in JavaScript with Canvas
  1056. Surma:and just load the texture into my WASM,
  1057. Surma:and basically that would allow me to skip the entire font code
  1058. Surma:in my WASM bundle if I were to publish this to the website.
  1059. Surma:There's a couple of interesting things to explore at some point.
  1060. Jake:Yeah, it's definitely
  1061. Jake:the thing aside
  1062. Surma:But, again, that's a lot of work, and it's probably not trivial
  1063. Jake:where they want the consistency across platforms
  1064. Surma:to make this work reliably and unilaterally.
  1065. Jake:there is definitely a problem
  1066. Jake:with the web right now
  1067. Jake:in that you have to either
  1068. Jake:go
  1069. Jake:use the platform
  1070. Jake:or not.
  1071. Jake:It's that in-between thing
  1072. Jake:that hooking into CSS
  1073. Jake:and changing bits like that.
  1074. Jake:It's that in-between thing
  1075. Jake:that hooking into CSS
  1076. Jake:and changing bits like that.
  1077. Surma:Yeah.
  1078. Jake:Providing your own layout engine,
  1079. Jake:even providing your own font rendering,
  1080. Surma:No, not really.
  1081. Jake:that kind of stuff.
  1082. Jake:If you want any of that,
  1083. Jake:you have to throw the whole lot away
  1084. Jake:and start from scratch.
  1085. Jake:We talk about the extensible web a lot
  1086. Jake:on this show,
  1087. Jake:but that was the dream there,
  1088. Jake:and it just hasn't been realized.
  1089. Surma:But, yeah, that was thoughts,
  1090. Surma:random thoughts by Surma on Canvas-based web apps.
  1091. Surma:And we still made it to 50 minutes.
  1092. Jake:Yeah, it's still a long episode.
  1093. Surma:So, you know.
  1094. Jake:We keep trying to do them shorter,
  1095. Jake:but we're...
  1096. Surma:Nah, we're just too self-indulgent.
  1097. Jake:Yeah.
  1098. Surma:But maybe if we don't waste any time, we can just end the podcast here
  1099. Surma:and call it.
  1100. Jake:Oh, okay.
  1101. Jake:Yeah, and then we'll see each...
  1102. Surma:Did you have any parting words? Any wisdom?
  1103. Jake:Any final words?
  1104. Jake:Wow.
  1105. Surma:I did make, like, a chop gesture with my hand,
  1106. Jake:Oh, you said parting words.
  1107. Jake:Sorry, I thought it was a bit more
  1108. Jake:threatening than that.
  1109. Jake:No.
  1110. Surma:which you obviously can't see, but, like, you know.
  1111. Jake:Oh, okay.
  1112. Jake:And then, yes, we'll be back
  1113. Jake:with whatever cadence
  1114. Jake:we manage.
  1115. Jake:And talk a bit
  1116. Jake:about putting React
  1117. Jake:in the browser.
  1118. Surma:Oh.
  1119. Jake:We've not done throw-forwards before,
  1120. Surma:Oh, that's, yeah, I'm excited now.
  1121. Jake:but we'll give it a go.
  1122. Surma:I'm excited now. That sounds inflammatory.
  1123. Jake:And what will inevitably happen
  1124. Jake:is something more important we'll come up to talk about,
  1125. Jake:and we'll just never talk about the React thing again
  1126. Jake:because it'll be...
  1127. Jake:Apple will start trying
  1128. Jake:to delete the platform again,
  1129. Jake:or whatever.
  1130. Jake:And we'll have to do an episode about that.
  1131. Surma:Weirder things have happened.
  1132. Jake:All right, then.
  1133. Jake:Well, only
  1134. Jake:one thing left to say, I suppose.
  1135. Surma:Yeah.
  1136. Jake:Happy next time.
  1137. Surma:Happy next time.
  1138. Jake:Bye!
  1139. Jake:...
  1140. Jake:...
  1141. Jake:...
  1142. Jake:...
  1143. Jake:...
  1144. Jake:All right.
  1145. Jake:Oh, we're cutting? Oh, amazing.