Skip to main content Accessibility Feedback
  • Episode 82

Responsible JS with Jeremy Wagner

In today’s episode, I chat with Jeremy Wagner about his amazing new book, Responsible JS.

Transcript

Hello, hello, hello. This is the Vanilla JavaScript podcast. I’m Chris Ferdinandi. Thanks so much for joining me. Today, I’m joined by my good internet friend, Jeremy Wagner, where we’re going to be talking about JavaScript, his new book, Responsible JavaScript, and maybe Wasps. Jeremy, for people who don’t know you, would you mind introducing yourself, just telling us a little bit about who you are and what you do? Yeah. Nice to be on your show, Chris. I’ve been meaning to get in touch with you for a while. We’ve been kind of bantering back and forth on the internet for a good minute, so it’s finally good to meet you. Yeah, same. So a little bit about me. I’m a web developer. At least I was in practice until very recently. A couple months ago, I took a technical writing gig, so I do that now, but I’ve been kind of doing this professionally, web development, for about 15 years and been kind of a hobbyist since I was like this little nerdy kid in middle school. So, you know, it’s just kind of one of the things I like is the web and play a little guitar on the side, you know, kind of screw around with other things and little DIY stuff, but mostly web developer guy. Nice. Awesome. So, yeah, so you wrote a book, and I was hooked on the title alone, Responsible JavaScript, because I just am constantly ranting about how irresponsible most of our JavaScript use on the web is these days. So do you mind maybe just giving folks, me even, actually a high level kind of what the book is about and why you wrote it? So yeah, the point behind Responsible JavaScript, and it actually kind of started as a series of posts for A List Apart. You know, every so often I look at HTTP archive data or I read the Almanac when it comes out every year, and the story always just seems to be, hey, we’re shipping more of this, and like a lot of things are getting worse, especially at, you know, percentiles experiences higher than the median. And I’ve always been kind of a performance guy anyway, like since I was younger and like saving images from my dorky little website, I was in, you know, being on dial-up, I was always kind of, you know, like eyeballing image sizes, like I’ve always kind of had an eye for this, even if I’m not like the best at what I do, but the problem of JavaScript and how it is contributing to worse user experiences when we misuse or overuse it, just kind of prompted me to like go off on a tear. So I wrote these three posts for A List Apart, eponymously titled, and I was supposed to write a fourth part to like wrap it all up, and then like I never did, and then a book apart said, hey, we’re looking for people to like, you know, propose books, and I was like, well, shit, I guess I’ll just do that, and then I put a proposal together, and then that’s sort of what happened. Now, I ramble a lot, as you can tell, so let me tell you what the book is about, because that’s what you asked. The book is about, it’s really like kind of a collection of observations and techniques, it’s sort of part manifesto, but also part like practical advice of like patterns you can use to improve both loading and runtime performance. Things like managing your tool chains, although that’s at a very high level, because things really change a lot in the industry, so I didn’t want to like peg myself to any one set of like build tools, like I didn’t want to like get too much into like webpack or anything like that. And then webpack version four comes out and ruins everything you wrote about in the book? Kind of, yeah, like we’re on version five now, and like every version that comes out, I’m like, okay, well, everything I knew was mostly wrong. But yeah, that’s the book at a high level, a little bit about third party JavaScript. I talk about what I call sustainable architectures, which is like, you know, kind of identifying what your app or your website does, and why it’s important to pick either a server heavy architecture, or maybe like rely on client side rendering when it’s appropriate. But discussing good defaults around that. But yeah, ramble finished. Sorry. No, that’s please, I want to learn more about this. I’ve had more students of mine than I can count now message me asking me if I’ve like heard about or seen your book yet. So I think there’s a lot of interest around this. And it’s really cool to hear you kind of talk about the performance angle of this, because that is why I got into vanilla JavaScript in the first place. I mean, also, because I felt like a fraud who didn’t know JavaScript, and wanted to learn like how it worked under the hood. But I had read a series of articles from Dave Rupert on how he dropped jQuery and saw massive performance boosts in his stuff. And like, that was it for me, I was just off to the races after that, because I was a big web performance wonk before that. And, and that just really kind of sent me down this path. So yeah, I absolutely love that. So there’s a whole bunch of stuff I want to ask you, like everything you just said got my brain spinning in a million different directions, as it tends to do. It’s a little bit like being a puppy in a lottery ball machine being in my head. I’d love to maybe dig into just a couple of specifics at some point. But the first thing I kind of wanted to ask you was, so what’s up with wasps? Because I know that’s kind of like the big lead in on the responsible js.dev website. So what do wasps have to do with JavaScript? So in this book, each chapter opens up with a metaphor about a specific wasp. So the the main metaphor that’s kind of out there in his public is about this digger wasp, which is part of the genus specs. And there’s behavior that’s been observed, although recently, this has been kind of not recently for a while, but recently, like awareness around this has kind of changed. But sort of classically, the big metaphor has been that these wasps have this behavior that appears thoughtful, right? Like they, they, they’re solitary. So they, you know, it’s just one female in a burrow that she lays eggs, and she provisions it with like a cricket, right? So when she gets this cricket, she brings it to the opening of the nest and like goes in to check it, comes back out, drags it back in, seems really thoughtful, right? But what some observers have found, and again, this isn’t consistent across all of them, but you know, in a group or like a cohort of these wasps, you can do this, which is you can take the cricket and move it while they’re in the burrow. When they come out, they move the cricket back to the entrance and then go back in again. And you can repeat this for some time. That gives a rise to this word coined called infectiousness, which describes that behavior, right? Like, oh, we’re appearing to do thoughtful things, but really, we’re kind of just going through the motions. And I kind of feel like that applies a little bit to what we do, right? Like we have these sort of patterns and like behaviors that we do. We’re like, oh, we’re going to install these set of packages, use this boilerplate, you know, like before, sometimes we do this before we like stop and think like, hey, is this really an appropriate setup for a project? And I bring this up and I know it’s kind of a long tail because Pew Research has done a lot of research about internet connectivity across the United States and a lot of polling around that. And so some relevant stats, I think, are in 2021, 24% of adults in the rural US state access to high speed internet is a problem, right? And I live in Minnesota. I’m from Iowa. And if you’ve been to Wisconsin, and I don’t know how you feel about Wisconsin, but if you’ve been there and it’s you’re in kind of like the sticks, it’s really a problem. Like quality internet access is a problem. Like my wife and I went up to two harbors, Minnesota, up on Lake Superior to get away for a while. This, you know, earlier in the year, and just using the internet up there on your mobile phone was just painful. Like it was really, really painful. Like you could see the HTML like actually kind of like stream in, it was so slow. And so our use of JavaScript, I think, in our infectious behaviors around it, I think have a real impact on people who are in situations like this. And I bring this up and I’m front loading a bunch of stuff here. We depend on the internet for more than just buying shit, right? Like we always talk about web performance, sort of these terms like, oh, we drove conversions this much. And like, you know, when we shaved a second of load time off, we made another million dollars for workers who won’t get it. You know, it’s, and it’s tempting to do that because that’s like those big top line numbers always feel like, like big accomplishments. But what we forget is that the internet is used for all kinds of shit. It’s used for, you know, applying for government assistance. It’s like for finding resources for crisis intervention. We shop for groceries on the internet. You know, there’s just a lot of things that we depend on it for and JavaScript can facilitate those things. And it often does, but it can also kind of be a hindrance. And yeah, so that’s my big ramble. No, and you know, the thing you touched on too, like I, whenever I mentioned the whole, like we build on, you know, most of us who are building things for the web or many of us were building things for the web often have really fast new devices. We have good internet connections. And, you know, I mentioned that the folks who use our things aren’t always like that. And one of the biggest pieces of pushback I get from a certain type of person is that, especially if you’re talking about like e-commerce or something like that, is that the, you know, well, the people who have money to spend on my product, they have fast internet, they have good devices. And that’s not always true. There are plenty of people who choose to live in more rural areas and find that the internet connection out there is absolute garbage. It’s not just people in like developing regions of the world or like outside the U S that have crap internet. In fact, a lot of places outside the world have better just general internet connectivity than we do here. And it’s, you know, it’s good to hear kind of an example from you of how like, you know, even just kind of like, you know, going on vacation somewhere, going to, you know, get away for a little bit. Like you found yourself in like a situation where, you know, you couldn’t do some of the things you wanted to do, or it was difficult because of just like modern infrastructure. And that’s not even accounting for the fact that like bad weather can really screw up internet in this country. You get a storm and you have to rely on your phone. Like that’s it. Yeah. And you know, just how famously great our infrastructure is. You know, it’s pristine. We’ve invested so much in it here. I know. Right. But like that sarcasm just for anybody outside the U S listing. We don’t invest in our infrastructure much. Yeah. We like the Texas thing, you know, kind of brings that up, right? Like that’s a really good thing. And I want to, I want to tag on what you just said here about the devices we can afford, right? Like I, you know, my, my daily driver is a Mac book and one air. And like, that’s like a $1,000 machine. And that’s like on the cheaper end of, of like Mac books, right? But that’s still a lot of money, right? Like a thousand bucks to like somebody who uh, is like hand to mouth in it, uh, with like two or three part-time jobs. It’s like, that’s a huge expense. And like, so of course you could expect people who might be the most likely to rely on the internet to apply for assistance or like really just like navigate through life who can’t afford these devices. Um, they’re going to pick a device that like might be a used device or it might be a cheaper sort of feature phone. Um, and this is where we see like increased mobile only browsing, right? Because a lot of times these folks don’t have like laptops or desktops. They have their phone and that’s their, their device. Right. And there are people who, who, you know, like students, uh, might be doing their schooling through either a provided iPad or whatever device that they just have, right? Like maybe their school district can’t afford to like get a fleet of these devices to like loan out. And so, and we have to think about like what that means for runtime performance. So like in the U S as of September, 2021, uh, and this was, uh, from stack counters. So, you know, I, I hold it up as a reasonably decent source of information, but it’s, it’s a source. Um, but in the U S, uh, it’s around 28% of people are on iOS and around 21% of people are on Android, but in the world, it’s like 16% of people are on iOS and 41% approximately are on Android. And I always like to tie this statistic, uh, into this article that Tim Cadlick wrote a while back that I thought was really had a great point. It was called the long tail of performance and it talks about how, and I think this is true, especially while it’s true for Android and not true for iOS so much because iOS is, you know, it’s monopolized device. You know, Apple makes all the devices that it’s on, whereas with Android, they contract that out to different manufacturers. And so there’s like a much wider variety of devices and capabilities. Um, not to mention the fact that Apple really has a lot of money to invest, uh, in creating these, these arm architectures that are frankly miraculous and how good they are, but going back to what Tim said, uh, when you focus on, uh, on just sort of like even the median or just averages, which averages are kind of a lie because it doesn’t really represent any one particular session. Uh, you, you can kind of forget, uh, people on that long tail who are on these slower devices, right? Um, and that’s, that’s a huge problem. And I, and I think it’s one that we, we have to do a better job of addressing. Yep. I agree. Um, so we could probably dig into why JavaScript is so crippling for performance, but I feel like I talk about that all the time and I’m happy to do it if you’re really excited about it. But I think the thing I’d love to hear more about if your game, um, is, um, some of the actual recommendations from, from the book. So, um, kind of thinking about all these considerations, um, you know, the performance angle, uh, you know, the fact that folks don’t always have new devices, that much of what we do, even though it’s not always life and death, it can be, um, you know, it’s critical infrastructure for people. What are some of the things that folks who are building for the web can do to be more responsible with the way that, that we build? Um, uh, I struggle with this a lot because a lot of my recommendations can sometimes come from a more, um, kind of like ivory tower, pure tentacle kind of approach to this. Um, and they don’t always acknowledge kind of the reality of working on teams and things like that. So I feel like you’ve probably done a much more thorough job, um, kind of researching this than I have, and I’d love to hear kind of your, your advice, Jeremy. Uh, yes. So the book kind of is the smattering of just, it’s, it’s kind of weird when I, when I wrote the proposal, it was like, I first did a mind map and then I just kind of bucketed all of these techniques into different sort of categories. Um, but I’ll, I’ll pick a few. Um, I don’t want to spoil the whole thing in the, in point of fact is, you know, some of this stuff has been written about before, for sure. It’s, it’s hardly, uh, hardly novel. It’s just kind of my presentation of it. But anyway, uh, a side to the side, uh, one of the things I’ve been, I’ve been kind of doing is, uh, making use of idle time, right? So there’s this API and in most browsers, I think there may be a couple of mainstream browsers that don’t implement this, but most browsers do. It’s called request idle callback, right? Um, and this API, what it does is it’s sort of like, um, it has sort of a similar shape, uh, to like using set timeout, right? So like it’s a function that you can use, uh, window.request idle callback. The first, uh, item is a callback function of something that you want to have done. Uh, and then the second parameter is optional, which is the deadline by which this work must be done. Uh, now it sounds like set timeout, but it is, um, what it does is the browser under the hood, uh, takes that callback, uh, and kind of holds onto it for a minute, uh, or for however long it needs to until it can find a bit of idle time on the main thread to execute that work. So think about, uh, think about stuff that isn’t user facing, isn’t critical or might be user facing, but doesn’t really require like instant feedback, right? Like you can wait, right? So I think things like, um, batching up analytics calls, um, maybe doing like, uh, DNS prefetching in the background or anything that just doesn’t have an immediate user facing benefit, uh, you could defer to, to this API to say, hey, um, this isn’t super important. Maybe wait until you have a second where the main thread is free because I don’t want to just like deadlock the main thread with this, this unnecessary, or at least lower priority work. So that’s one of the things I’ve been doing. Um, I, if you want to chew on that with me, I’m happy to do that. Uh, but I have like a whole list, so I don’t know how you want to work it. Well, so just before we move on, just for benefit of my audience has a lot of beginner folks in it. Um, and so, um, one of the things that, um, I think it’s not necessarily unique to JavaScript, but that makes performance kind of sometimes an interesting thing is the like single threaded nature of it. Um, so for folks who aren’t necessarily familiar with that, do you mind unpacking that for just a little bit? So like, what is, what is the benefit of, um, the request idle callback API or why is it so important in a runtime environment like JavaScript? So like you said, um, JavaScript, well, technically JavaScript isn’t single threaded, but unless you explicitly take advantage of things like web workers or like worklets for things like audio or like, um, image processing and that type of thing, everything you do is on the main thread and the main thread is the only thread, um, where, where the page does its work, uh, at least by default, um, leaving workers aside. Um, so the reason why a request style callback makes sense is because if you have a ton of work, uh, that’s occurring in the main thread, then the main thread becomes sort of like bogged down. Like if you’ve been scrolling like on your phone and like the scrolling seems like kind of jittery or jumpy or like you click on a button and like the button doesn’t do what the button says it’s going to do for like a second or maybe two, uh, you’re the victim of a clogged main thread, right? It’s all of this work that is occurring and no new work can get, can get done until that work has been cleared out, right? It’s sort of first in first out. So request idle callback is a way of managing, uh, managing non-critical work, uh, so that the more crucial stuff has more room to breathe. Um, and it is a tricky API to use. Uh, Phil Walton, um, he wrote this article and I cover this kind of with my own spin, uh, but he, he wrote a fantastic article called, uh, idle till urgent. And it’s this pattern where you can delegate something to request that will call back. Uh, but if a situation comes up where that callback needs to run immediately, you can cancel the idle callback and just run the callback immediately. Uh, there’s some pretty interesting ways of using those API that can, in my opinion, can really help, um, like seriously help with runtime performance if, if we use it correctly. And now beyond just the main thread piece, this is also, these performance issues also pop up because JavaScript is primarily a synchronous language, although we’re starting to see more and more kind of asynchronous stuff pop up, but that’s part of it too, right? In that once an action is run, other things can’t happen until that action completes, unless you use something like, um, the request idle callback API to tell it to behave differently. Is that the kind of the idea? Yeah. Uh, it, it kind of, I, I don’t, I want to, I don’t want to say this incorrectly, but it is a sort of synchronicity. Um, everything in the callback will, when it runs, we’ll occupy its time and run in the order that. Right. But you’re deferring, you’re saying don’t hold up this other stuff for this thing. Right. Is that the idea? Yeah, exactly. That’s, that’s the whole, you can tell I’m self-taught because I use really official language, like no, no thing and stuff. No, same thing. Right. So like, I don’t have, um, this might, this might surprise your listeners. I don’t have training in computer science. I’m a designer by training. I hadn’t turned out that that really wasn’t fun for me. Uh, so I just sort of ended up doing this because I was already kind of a hobbyist on it anyway. Uh, but yeah, that’s again, I’m getting on the sides of the sides, but yes, that’s kind of the point of the awesome. No, thank you. This is just me. Like I know one of the things I’ve found is like, um, I’ve been working on this so long, but there’s a lot of things that I just kind of take for granted now that I know a lot of times my, like my students, the people listen to my shows, um, don’t always like they, if they haven’t been exposed to it, I just want to make sure that kind of we lay that, that foundational, like here’s why this is a problem or why you need this thing. Um, so you mentioned you had a whole list of things. I’d love to hear about some more of them. So one of the things I’ve been trying to kind of work on, and I do talk about in the book and show an example, uh, is anticipating interactions, right? So we, we kind of know a little bit. I mean, I don’t want to assume anything about your, about your listeners. Um, but it’s part of code splitting and code splitting. A quick recap is this idea that if you have part of your application logic that doesn’t need to be loaded, uh, at startup, so you have like this big old, like one megabyte bundle of stuff, there’s probably a good chance that a lot of that is unused during startup and only gets queued up, um, or gets used when like, say somebody clicks on a button or some interaction that occurs well after startup, right? And so we use a thing called the dynamic import, uh, and bundlers recognize this and it will split that off of your main application logic and load it on demand. Great, right? So you’re improving startup performance, um, and sending less JavaScript during startup and that reduces like parsing and compilation and all that stuff that ties up the main thread. Cool. Problem is, uh, is that when you load JavaScript on demand, uh, kind of what happens is when say like you have a button, right? Like an add to cart button and some JavaScript runs when you click it to add the thing to the cart. Well, if you’ve, if you’ve used code splitting to split that interaction off and the user clicks and then the dynamic import occurs, uh, the network has to go out, get that chunk of JavaScript, parse, evaluate it, do all the stuff at runtime. So you’re kind of back in this situation again, where great, my, my perceivable runtime performance feels really bad because I clicked this button and I’ve had to wait for the network to download this 30, 40 kilobyte chunk of JavaScript or whatever it is and evaluate it before anything happens. So I’ve been trying to find ways where we can anticipate these reactions a little bit better for click interactions. It’s a little bit trickier, right? Like you can try things like hovering and like that works, but what if you don’t have like a device that has a, um, like a fine pointer, right? Like a mouse, right? You’re using a course pointer, like a touch input. That’s a little bit trickier, but there are opportunities where we can do this. So the example I use in the book is like contact form validation, or you could really apply this to any kind of validation. And I, and I feel like as purists, sometimes we, we say a lot of things like use HTML, just use HTML for this type of stuff. And it’s like, yeah, you, you should, right? Because that could provide a really good baseline interaction. Like if you have a required attribute, um, or like if you use type equals email, that type of thing, all that stuff is great. Problem is a lot of that stuff isn’t very styleable. Uh, and you are inevitably going, inevitably going to run into a situation, especially in a job where somebody’s going to want that to that validation and that messaging to match their branding, right? Like we need this to look a certain way. So the anticipated interaction I’ve used for the contact form example is yes, we have some, some JavaScript that validates this form before it’s submitted and like creates some pretty validation, um, that, you know, matches your aesthetic or what you want, but we still want to code split, right? So what we do is in this example is anytime any of the fields on the form are focused, a fetch is done or like a preload is done to grab that little chunk of JavaScript. Uh, so that by the time the submit handler fires, uh, and the user is done with the form, which will take a while, uh, by the time that submit handler fires that dynamic import will won’t have to go to the network. It will actually go to the disk cache and we’ll grab that thing that we already preloaded, uh, almost instantaneously. So we kind of get the best of both worlds. Um, but that said, it’s, it’s difficult and every situation kind of requires its own kind of bespoke way to like handle it, right? But that’s kind of one of the things, um, I’m still kind of exploring where else this pattern could be used, right? Like focus event handlers to feel like a good, a good place to do it. Um, especially in forms because there is that period of time, you know, it just takes time to fill out a form. Uh, and even on a slow network, let’s hope that that chunk of JavaScript was preloaded by the time somebody hits submit. Yeah, that’s, um, that’s a really interesting one though. I, um, I had never like kind of considered cause I’ve, I’ve, I’ve done some code splitting in the past. I often find it like, um, like for me, it’s a level of like complexity. I just hate dealing with. And so I just try to use as little JavaScript as possible, but, um, all right, the golden rule of JavaScript uses little as possible, but, um, I, uh, yeah, that’s a really clever kind of approach. I, um, I like that, especially for things where like, if it fails, you should theoretically have some like server side validation that’s happening anyways. So it’s not the end of the world. If it doesn’t necessarily, like for something, like the example you gave about form validation, like if that script doesn’t download in time and the form submits without it, you should still be validating that code on the back end anyways. Um, so, um, that totally goes without saying, I mean, I really should say it because nothing should go without saying when it comes to that, but that is like a golden rule is client side validation is great. And it really, it can kind of grease the wheels a little bit, but definitely always validate your inputs. So I, I think what I’m trying to say is this feels like a really nice, like it’s a great progressive enhancement. If for some reason, like that file doesn’t download, parse and like start running before the user hits submit, it’s maybe a slightly less awesome user experience, but it’s not, it shouldn’t be breaking anything because you still kind of have those fallbacks in place. Um, so it just really seems like a perfect use case. It feels good. Um, and on top of that kind of the fallback in the example I use doesn’t even go to the server. Um, so the, the HTML that ships from the server for the contact form has stuff on it, like required attributes. Um, so you’ve got like HTML validation built in, right. But then when that, when that form run, like when that contact validation, um, the form validation script runs, it strips those, those attributes off of those form elements so that it can do its custom validation. Uh, so the fallback is just whatever ships in HTML. So there’s like fallback, fallback, fallback, because then on top of that, you’re also like validating them server. It’s, it feels redundant, but that, that kind of resiliency is kind of what guarantees that you get some minimally viable like experience, I think. And that to me is what progressive enhancement is all about. For sure. For sure. Um, yeah. And just kind of the idea of building more, the, the, the phrase or the word resilient, like really resonates with me. I’m a big fan of building resilient experiences that continue to function even when like things go wrong, because things always go wrong. Um, um, yeah, I’d love to hear, we probably have time for maybe one or two more things off your list. Um, I’d love to, I’d love to hear about another kind of responsible JS technique. So this is one and it’s, it’s, uh, resiliency is the perfect lead in word for it because that’s what it’s all about. In fact, I think one of the subheadings in the book is resiliency. Thy name is service worker. Uh, and I love service worker. Um, I’m actually right now working on, um, working on documentation for workbox, which is a Google, um, it’s a Google open source project that abstracts service worker. Uh, and it’s, it’s really, really slick. Um, but in the book, I, I discuss how to do this without workbox. Uh, so it’s very like bare metal. Um, although workbox really makes this a lot easier without a lot of overhead. Um, so it’s this idea of streaming service workers. And last year, uh, no, earlier this year, I, I put out an article, uh, called now that’s what I call service worker that talks about this, uh, in depth. Um, so you can check that out there, but what it does, uh, is that you can take, uh, the common parts of a page, right? Like, um, like that, the navigation, right. And the footer, all of these things that like are, are consistent across pages, they’re consistent UI elements. You can kind of like shove them away into their own HTML files and then cache them or rather pre-cache them with a service worker. And then you can, you can request, uh, content from the network, but like only the part of the page, uh, that, um, is inconsistent, right? So like the content area. Uh, so like I did this for a client of mine in Wisconsin. They’re like a logging company and that’s what the article talks about. Um, and so like they have, it’s a pretty simple website. Uh, so it’s like an about page, a contact page. They got a page with like a gallery of images and that type of thing, but their header and their footer stays the same. So what this pattern does is it just, it uses HTTP headers to let the backend decide if it wants to send the full page with the header and the footer or just a content markup. So when the service worker is installed, uh, what happens is, is that when navigation requests happen and to let your users know what that is, a navigation request is any request for an HTML document. Uh, so when a navigation request happens, it just gets that content partial, but then it’s, it, um, stitches it together with these pre-cached, with this pre-cached header and footer markup. And what we found was, you know, and this was in our field data. So this wasn’t like just synthetic testing that revealed this. What we found is a significant, uh, decrease in both, um, first contentful paint and largest contentful paint. And it also has this effect of immediate loading. Like it almost has a single page application type performance improvement when we did this. Now that said there, this technique, uh, I would describe it as kind of aspirational, uh, because it’s hard to scale up. And the reason why is because that pre-cached header markup, for example, has a navigation menu in it. And so you’d have to do things like you’d have to put in some inline JavaScript to say like on this page, the title tag should say this and this navigation, uh, item should have an on state, right? Fine for a small website with like four or five pages where this works, it gets more difficult. Um, but I know that there are some people, some larger companies out there that are testing this approach and seeing if it’s, if it’s viable for them. I think with the right abstractions, it could really be a, a sustainable pattern, uh, that gets us that sort of single page application like performance, although it does have downsides. Uh, when I was in two harbors, uh, with my wife, uh, I wanted to test this while I was on my mobile phone. Um, what I found was, is that, yeah, perceptually that header was appearing instantly because it was in the pre-cache, right? Um, but then like that network content still took a while to stream. So like it kind of created the impression of, it created a, it was still slow, but in a different way, if that makes any sense. Right. Yeah. No, for sure. You’re at least getting the framework ahead of time, even if the core, core content isn’t, or the shell, I guess is what they used to call it. Um, yeah, the, the application shell is technically a single page application. Um, like kind of term, but yeah, but yeah, basically that’s the kind of same idea. Yeah. So I mean, service workers are just so amazing. I, um, I, I get single page app, like performance out of my, I hate the phrase multi-page app because it’s really just like a normal website, but, um, I get SPA like performance out of my MPAs on a regular basis, just with like aggressive service worker caching. And, um, yeah, it’s kind of, kind of bonkers what they can do. I have a, I have a confession to make and I have not played with edge workers yet. And I just, it’s there. And I know that that’s going to be like a great additive enhancement, like with the service worker, but like that’s still one of those things where I’m like, I got to get to that someday because it is relevant and it would be good. But like, I don’t know. I just feel like it’s, it’s good to just put out there. Like there’s a lot of shit I don’t know. Yeah. Well, I mean, the list of things to learn is, is endless. So you gotta, you gotta pick and choose. Um, you know, um, Jeremy, if there was one, one last thing that you would want to share or one last little like tip or trick or kind of thing, um, what would it be? Uh, um, you know, rather than get specific, I think I’d like to get more general. Um, and it might, it might border philosophical. Um, please, please, uh, evaluate your framework choices for runtime performance. Uh, you know, I, I often poke at reacts and the fact is, is I, I think react is introduced some conventions that are really awesome. Like I really like JSX as a templating language. Uh, I think it’s really expressive and powerful. Um, I, I really think, and like just in general reacts API has introduced a lot of conveniences and, and innovative ways to kind of do work on the web, but it’s runtime performance is really, really kind of onerous on slower devices for even simple interactions. And I think, you know, about this article, I wrote a year ago for CSS tricks where I, I compared, uh, and it was for a simple interaction. It was, um, like a mobile navigation menu toggle, right? But it was a simple interaction. I profiled, uh, using react, um, a native event listener, like just a regular, like click event listener with minimal code, uh, and preact, uh, which is if your readers aren’t familiar with preact, it’s sort of this, um, super duper optimized API compatible version of react. Um, and I pretty much use it exclusively over react. Um, and not just because it’s like three kilobytes over the wire or whatever it is. So ridiculous. It’s ridiculous, right? It’s hyper optimized, but it’s not just hyper optimized for size. It is for runtime performance too. In a lot of cases, it was beating out react in this simple interaction, um, a few times over, like by like an order of magnitude in some cases. And I got a little criticism for that article because it was like, well, you’re just, of course, like, you’re just profiling this really simple interaction. Uh, and of course, a native event listener is going to be faster. It’s like, yeah, you know, we have to accept a certain amount of overhead if we’re going to use an abstraction. But the point is, is that when, a number of these interactions start to pile up, um, your choice of framework can be what, you know, could be the difference between a usable experience and an unusable experience. So please like get in the performance panel, uh, get a shitty old Android phone, uh, and like connect it to Chrome dev tools and do some profiling, like kind of like build out some like examples of like basic interactions and see which one works for you. Uh, because that’s going to really make a big difference to your users in the long run. It’s, it’s difficult. It’s not a simple, easy answer, but it’s worth the work. And I would like to see more people do that. Yeah, for sure. Um, I love that article. I reference it constantly. Um, I actually saw the, um, I’m totally drawing a blank on, uh, the gentleman who built Preact, but, um, he had tweeted a few months back that he was, yes, thank you. And he had tweeted that he was working on a new rendering engine for the next version of Preact that was apparently even more optimized than what they have now. Um, and, uh, it exploits some like browser rendering quirks in such a way that it can potentially behave more performantly than vanilla JavaScript, not like in the absolute sense, because, you know, like abstractions always add a little bit of latency, but like basically to get that same level of performance, you’d have to write your just plain old browser native JavaScript in a way that like a real human typically wouldn’t because it would be unreadable and kind of a hot mess. Um, and so I haven’t seen any actual kind of like tests showing this yet, but I would be really interested to see what, um, you know, uh, what comes out of that. Um, yeah. Have you had a chance to play around with petite view at all, or have you heard of this? I haven’t used new, like small subset of, of view intended for, um, just progressive enhancement kind of stuff. Is this, I haven’t heard of this, uh, in particular, but is this sort of like a, a riff on the islands approach to like sort of interactivity? Um, so what, um, my understanding is Evan was inspired by Alpine, which is supposed to be like to view what pre act is to react, like same API, same kind of approach, smaller kind of footprint. Um, and, uh, Evan, you apparently decided he liked the idea enough that he, um, he was going to build something himself that did, did same kind of thing. And so his version is, I think 5.5 kilobytes, same kind of core API as view, but shed some of the niceties, um, and is really intended for more of like, uh, rather than building like a whole like, like massive single page app kind of thing. It’s really intended for like, um, progressively enhanced interactivity. So maybe you have like an e-commerce site with like, uh, like filter products by criteria or, um, you know, browse albums by, or, you know, whatever, whatever kind of thing. Um, I’m always intrigued by these lighter weight versions of, of bigger tools, um, and how they actually work. I think the thing that’s most intriguing for me about pre act is it’s not just smaller because you can build tools that are smaller, but not necessarily more performant in terms of render. And I know because I have, I have done that. Um, my, uh, I’d like, I built this thing called, called reef to kind of learn how state-based UI works under the hood. And, um, I really liked the experience of working with it, but it’s not, um, it’s not necessarily like the render performance isn’t as good as some other dom-diffing engines are. Um, and so I’m just kind of always curious about this sort of thing. Um, I like the idea of, of these sort of smaller API compatible alternatives because going back to Jason, I, he, he seems like a guy that like, would have really done extremely well in embedded systems computing, uh, where those constraints are like really like minimal and they’re like, he just knows how to navigate that really well. And then he brings that to the web and that’s really cool. And, and Evan is bringing that to the web and that’s, I am all for these frame. In fact, if more frameworks were like this, I think I would be less openly critical of some of the things that have resulted from kind of like the more behemoth frameworks, right? But it’s also important to remember that it’s not always the framework itself. Uh, that it’s, it’s a lot of the add-ons and the things that flow through the framework, you know, that, that can kind of like really make things a little bit, you know, less, less usable, I guess. Yeah. I mean, as a, just kind of as an anecdote, um, like the stop and shop online shopping experience works fine on my computer, but even on my, like my new iPhone 13, it crashes the browser. If I try and scroll too fast or do too much at once, like it literally just shuts down and I have to like reload Safari, um, which is on an iPhone 13 that like, that was like, we’re working at it, but you can try really hard to, to do that. I thought my eye was fast, but like it probably would choke on that website. So, um, yeah. So to, to kind of bring this full circle. Yes. I think being, being more mindful of your, um, your library choice is, is really good advice. I actually have a, I’m sorry, your, your advice actually kind of led me to a tangent question, which is, have you looked at all at any of kind of the emerging kind of compiler approaches where you’re still using kind of a, a JavaScript based approach to building, but you run a thing ahead of time that then compiles that to mostly HTML with a little bit of like old school dom manipulation, you kind of kind of JavaScript. So I’m thinking specifically of things like Svelte or more recently, um, Astro. I’ve not played with Astro. Um, I’ve played with Svelte. Um, I, I like it. Um, I think the semantics and this is purely, purely an opinion. This is not denigrating, you know, anybody who works on Svelte because anything that makes the web faster and like lead and leads to a better development experience, I think is positive. Um, personally for me, the syntax and the kind of semantics around it are not, it doesn’t work for me. Uh, it doesn’t lead to a high, but like a high quality developer experience for me personally, but like, I also don’t really like non-jucks that much and that type of thing. So like it, I’m picky, right? This isn’t, this isn’t eight Svelte problem. This is. Yeah, no. And I think at the end of the day, a lot of this is like different people prefer different things. Cause I know you mentioned, you really like like the react and preact kind of interface. And I very much prefer, like for me views approach to templating makes sense in my weird brain better than react and preact. And I know like a lot of people disagree with me and that’s kind of what makes the web so interesting and weird and wonderful. Um, so yeah, I totally, I totally get that. I think the reason that JSX has like worked for me is because it, it’s so much resembles PHP to me. Like at the end of the day, I am an old man in a lamp stack costume doing a young man’s job. And so I’m trying to keep up. Well, and to be fair, so much of modern tooling is just reinventing PHP over and over again. So, another round with that. Oh man. Well, um, Jeremy, it was an absolute pleasure having you on the show. This is great. Um, uh, I learned a ton. You brought up some really interesting kind of new techniques. And like, I had not heard of, for example, the request idle callback, um, method before. Um, so I’m going to link to all of, I was pulling up stuff as you were talking. So I’ll make sure I linked to all of this in the show notes, um, including, you know, kind of relevant articles. I have your CSS tricks article, Philip Walton’s idle until urgent article pulled up. I’ll, I’ll drop those in the show notes as well. Um, for anybody who wants to learn more about you, your book, where to get it, what it’s all about, um, where can they go? Where can they go? Oh, um, so they can go to a book apart.com. Um, if they want to pick up the book, it would be much obliged. Um, but if you just kind of want to stalk me on the internet and look at what I’m writing or I’m, I’m up to, you can go to Jeremy dot codes. Uh, although that is currently in the middle of a refresh. So there really hasn’t been much, you know, new content lately, but pretty soon there’s going to be a pretty big refresh. I want to like, kind of go big with it this time and have a, have a good time with it. But yeah, that’s where you can go. Oh, and you can find me on Twitter and get hub, uh, as malcada that’s spelled N a L C H a T a. Um, and yeah, that’s, that’s me. Awesome. I will make sure I link to all of that stuff in the notes for, uh, for this episode. And, um, Jeremy, thank you so much. This was awesome. I learned a ton. I, uh, I really enjoyed chatting and thank you so much.