Smashing Podcast Episode 21 With Chris Ferdinandi: Are Modern Best Practices Bad For The Web?
Smashing Podcast Episode 21 With Chris Ferdinandi: Are Modern Best Practices Bad For The Web?
Drew McLellan 2020-07-28T05:00:00+00:00
2020-07-28T12:34:00+00:00
Today, we’re asking if modern best practices are bad for the web? Are modern frameworks taking us down the wrong path? I speak to Lean Web expert Chris Ferdinandi to find out.
Show Notes
- Chris’ page with links and notes for the podcast
- The Lean Web book
- Chris Ferdinandi on the web
- Chris on Twitter
- The Vanilla JavaScript Podcast
Weekly Update
- “Translating Design Wireframes Into Accessible HTML/CSS”
by Harris Schneiderman - “Building Desktop Apps With Electron And Vue”
by Timi Omoyeni - “Modern CSS Techniques To Improve Legibility”
by Edoardo Cavazza - “How To Use Styled-Components In React”
by Adebiyi Adedotun Lukman - “How To Create A Porsche 911 With Sketch”
by Nikola Lazarević
Transcript
Drew McLellan: He’s the author of Vanilla JS Pocket Guide Series, creator of the Vanilla JS Academy Training Program, and host of the Vanilla JS Podcast. He’s developed a Tips newsletter, it’s read by nearly 10,000 developers each weekday. He’s taught developers at organizations like Chobani and The Boston Globe. And his JavaScript plugins have been used by organizations like Apple and Harvard Business School. Most of all, he loves to help people learn Vanilla JavaScript. So we know he’d rather pick Vanilla JavaScript over a framework, but did you know he was once picked out in a police lineup as being the person least likely to have committed the crime? My Smashing friends, please welcome Chris Ferdinandi. Hello, Chris. How are you?
Chris Ferdinandi: Oh, I’m smashing. Thanks for having me.
Drew: I wanted to talk to you today about this concept of a Lean Web, which something of a passion for you, isn’t it?
Chris: Yes, very much so.
Drew: Why don’t you set the scene for us? When we talk about a Lean Web, what is the problem we are trying to solve?
Chris: Yeah, great question. Just as a caveat for all the listeners, this episode might get a little old man yells at cloud. I’m going to try to avoid that. When I look at the way we build for the web today, it feels a little bit like a bloated over-engineered mess. I’ve come to believe that a lot of what we think of as best practices today might actually be making the web worse.
Chris: The Lean Web is an approach to web development that is focused on simplicity, on performance, and the developer experience over… I’m sorry, not the developer experience. The user experience rather, over the developer experience, and the ease of building things from a team perspective, which is what I think where we put a lot of focus today and as we’ll probably get into in our conversation.
Chris: I’ve actually come to find that a lot of these things we think of as improving the developer experience do so for a subset of developers, but not necessarily everybody who’s working on the thing you’re building. So there’s a whole bunch of issues with that too, that we can dig into. But really, the Lean Web is about focusing on simplicity and performance for the user and really prioritizing or putting the focus on the people who use the things we make rather than us, the people who are making it.
Drew: As the web matures as a development platform, there seems to be this ever increasing drive towards specialization.
Chris: Yes.
Drew: People who used to cover Full Stack, and then we split into front-end and back-end. And then that front-end split into people who do CSS or JavaScript development. And then increasingly within JavaScript, it becomes more specialized. Somebody might consider themselves and market themselves as a React developer or an Angular developer, and their entire identity and outlook is based around a particular framework that they are highly skilled in. Is this dependency on frameworks, the core of our work on the web, a bad thing?
Chris: It’s nuanced. I used to be very strongly in the yes, always camp. I think broadly, I still feel like yes, our obsession as an industry with frameworks and tools in general really, is potentially a little bit to our detriment. I don’t think frameworks are inherently bad. I think they’re useful for a very narrow subset of use cases. And we end up using them for almost everything, including lots of situations where they’re really not necessarily the best choice for you or for the project.
Chris: When I think about a lot of the issues that we have on the web today, the core of those issues really starts with our over-reliance on frameworks. Everything else that comes after that is in many ways, because we throw so much not just frameworks which is JavaScript in general, at the web. I say that as someone who professionally teaches people how to write and use JavaScript. That’s how I make my money. And I’m here saying that I think we use too much JavaScript, which is sometimes a little bit of an odd thing.
Drew: In the time before the big frameworks sprouted up, we used to build user interfaces and things with jQuery or whatever. And then frameworks came along and they gave us more of this concept of a state-based UI.
Chris: Yes.
Drew: Now, that’s a fairly complex bit of engineering that you’re required to get in place. Does working with less JavaScript exclude using something like that, or do you have to re-implement it yourself? Are you just creating a loaded boilerplate?
Chris: A lot of it depends on what you’re doing. If you have a non-changing interface, you can build a state-based UI with… I don’t know, maybe a dozen or so lines of code. If you have a non-changing interface, I would honestly probably say state-based UI. It’s not necessarily the right approach. There’s probably other things you can do instead. Think of static site generators, some pre-rendered markup, even an old-school WordPress or PHP driven site.
Chris: But where this starts to get interesting is when you get into more dynamic and interactive interfaces. Not just apps. I know people love to draw this line between websites and apps, and I think there’s this weird blend between the two of them and the line is not always as clear. When you start to get into more the user does stuff, something changes. State-based UI becomes a little bit more important. But you still don’t need tons of code to make that happen.
Chris: I look at something like React or Vue, which are absolutely amazing pieces of engineering. I don’t want to take away from the people who work on those. I ended up as a learning exercise, building my own mini-framework just to get a better sense for how these things work under the hood. It is really hard to account for all of the different moving pieces. So I have tremendous respect for the people who build and work on these tools. But React and Vue are both about 30 kilobytes after minifying and gzipping. So once you unpack them, they’re substantially bigger than that.
Chris: Not all of it, but a good chunk of that weight is devoted to this thing called the virtual DOM. There are alternatives that use similar APIs or approaches. For React, you have Preact, which is 2.5 kilobytes or about 3 kilobytes instead of 30. It’s a tenth of the size. For Vue, you have Alpine JS instead, which is about 7 kilobytes. Still, substantially smaller. The big difference between those and their big brother counterparts, is that they’ve shed the virtual DOM. They may drop a method or two. But generally, it’s the same approach and the same kind of API in the way of working with code, and they’re substantially smaller.
Chris: I think a lot of the tools we use are potentially overpowered for the things we’re trying to do. If you need a state-based UI and you need reactive data and these dynamic interfaces, that’s great. I think one of the big things I try and talk about today is not… never use tools. For me, Vanilla JS is not you’re handwriting every single line of code and every single project you do. That’s madness. I couldn’t do that, I don’t do that. But it’s being more selective about the tools we use. We always go for the multi-tool, the Swiss Army knife that has all these things in it. And sometimes, all you really need is a pair of scissors. You don’t need all the other stuff, but we have it anyways.
Chris: Which is a really long way to… I’m sorry, of answering your question. Which is sometimes it’s more code than you could or would want to write yourself, but it’s not nearly as much code as I think we think it requires. When I say you don’t need a framework, I get a lot of push-back around this idea that, “Well, if you don’t use a framework, you’re basically writing your own.” Then that comes with its own problems. I think there’s a place in between using React or Vue and writing your own framework, and it’s maybe picking something that’s a little bit smaller. There are sometimes reasons where writing your own framework might actually be the right call, depending on what you’re trying to do. It’s all very fluid and subjective.
Drew: It’s quite interesting that as a learning exercise, you implemented your own state-based framework. I remember in the past, I used to think that every time I reached for a library or something, I liked to think that I could implement it myself.
Chris: Sure, sure.
Drew: But reaching for the library saved me the hassle of doing that. I knew if I had to write this code myself, I knew what approach I’d take to do it. And that was true all the way up to using things like jQuery and things. These days, I think if I had to write my own version of Vue or React, I have almost no idea what’s happening now in that library, in all that code.
Drew: For those of us who are not familiar, when you say something like Preact drops the virtual DOM and makes everything a lot smaller, what’s that virtual DOM giving us?
Chris: To answer that question, I want to take just a slight step back. One of the nicest things that frameworks and other state-based libraries give you is DOM diffing. If you’re not really updating the UI that much, you could get by with saying, “Here’s a string of what the markup is supposed to look like. In HTML, I’ll just put all this markup in this element.” When you need to change something, you do it again. That is a little expensive for browsers, because it triggers a repaint.
Chris: But I think potentially more importantly than that, one of the issues with doing that is that you have any sort of interactive element in there, a form-field, a link that someone has focused on. That focus is lost because the element… even though you have a new thing that looks similar, it’s not the same literal element. So if focus is lost, it can create confusion for people using screen readers. There’s just a whole bunch of problems with that.
Chris: Any state-based UI thing worth its weight is going to implement some for of DOM diffing, where they say, “Here’s what the UI should look like. Here’s what it looks like right now in the DOM. What’s different?” And it’s going to go and change those things. It’s effectively doing the stuff you would do just manually updating the UI yourself, but it’s doing it for you under the hood. So you can just say, “Here’s what I want it to look like.” And then the library or framework figures it out.
Chris: The smaller things like Preact or Alpine, they’re actually doing that directly. They’re converting the string you provide them of what the UI should look like into HTML elements. And then they’re comparing each element to its corresponding piece in the literal DOM. As you end up with UIs that get bigger and bigger and bigger, that can have a performance implication because querying the DOM over and over again becomes expensive. If you want to get a sense for the type of interface where this becomes a problem, right-click and inspect element on the “Favorite” button on Twitter, or the “Like” button on Facebook. And take a look at the nesting of divs that gets you to that element. It’s very, very deep. It’s like a dozen or so divs, nested one inside the other just for that single tweet.
Chris: When you start going that many layers down, it starts to really impact performance. What the virtual DOM does is instead of checking the real DOM every time, it creates an object-based map of what the UI looks like in JavaScript. And then does the same thing for the UI you want to replace the existing one with, and it compares those two. That’s a lot more performance in theory, than doing that in the real DOM. Once it gets a list of the things it needs to change, it just runs off and makes those changes. But it only has to attack the DOM once. It’s not checking every single element, every single time. If you have interfaces like Twitters or Facebooks or QuickBooks or something like that, virtual DOM probably makes a lot of sense.
Chris: The challenge with it is… the difference between Preact and React is 27 kilobytes before you unpack the whole thing into its actual codewave. The raw download and unpacking and compiling time on that alone can add quite a bit of latency to the initial load on a UI. That becomes even more pronounced if your users are on not the latest devices from Apple. Even an Android device from a couple of years ago or a feature phone, or if you have people in developing countries, it’s just really… the time to get going is slower. And then on top of that, the actual interactive time is slower because of the extra abstraction.
Chris: So it’s not just you load it and they’re comparable in speed. Each micro interaction that someone makes and the changes that need to happen can also be slightly slower just because of all that extra code in there. If you have a really, really complex UI with lots of nested elements and lots of data, then the virtual DOM’s performance gains outweigh that extra code weight. But any typical UI for a typical app that most of what I see developers using React or Vue for, the benefit you get from the virtual DOM just isn’t there and they’d be better off. Even if you want to keep the same convenience of React, use Preact. It’s a fraction of the size, it’ll work exactly the same way, and it’ll more performing. This is the kind of thing that I tend to argue for.
Chris: We need to be better about picking the right tool for the job. If you go with an approach like that, if you get to a point where a virtual DOM actually makes sense, it’s much easier to port Preact into React than if you rolled your own. That’s the situation. If you’re really worried about that, you get some future-proofing built in too.
Drew: Some might say, they might make the argument that these frameworks, things like Vue, React are so highly optimized for performance that you get so much benefit there that surely just pairing that with a package manager in a bundler to make sure you’re only sending down the code that you want to. Surely, you are way ahead already just by doing that?
Chris: Yeah. I don’t agree. I don’t really have much more to elaborate on that other than… I guess maybe, but not really. Even with a bundler, you still need that React core. Even with the bundling, that’s still going to be bigger than using something like Preact.
Chris: Drew, I really appreciate you leading the question on this. Because one of the other things I do talk about in my book, The Lean Web, and my talk of the same name, is how these tools… You mentioned the bundling, for example. One of the things we do to get around the performance hit that we take from using all this JavaScript is we throw even more JavaScript at the front-end to account for it. One of the ways we do that is package managers and module bundlers.
Chris: As you alluded to… for those of you who don’t know, these are tools that will… they will compile all of your little individual JavaScript bits into one big file. The newer ones and the more… I don’t want to call them thoughtful. But the newer ones will use a feature called tree shaking, where they get rid of any code that isn’t actually needed. If that code has some dependencies that aren’t used for the thing you’ve actually done, they’ll drop some of that stuff out to make your packages as small as possible. It’s actually not a terrible idea, but it results in this thing I typically call dependency health where you have this really delicate house of cards of dependencies on top of dependencies on top of dependencies.
Chris: Getting your process set up takes time. And anybody who has ever run an NPM install and then discovered that a bunch of dependencies were out of date and had to spend an hour trying to figure out which ones needed to be fixed and oh, it’s actually a dependency in a dependency and you don’t have the ability to go fix it yourself. It’s a whole thing. Maybe it works for you, but I’d rather spend my time not messing around trying to get my dependencies together.
Chris: I’ve started collecting tweets from people where they complain about time wasted on their workflow. One of my favorites, Brad Frost a couple year ago, was talking about the depressing realization that the thing you’ve been slogging through in modern JS could have taken you 10 minutes in jQuery. I’m not really a jQuery fan, but I feel that pain when it comes to working with frameworks.
Chris: The other issue with a lot of these tools is they start to become gatekeepers. I don’t know how much you really want to dive into this or not, Drew. But one of my big push-backs against JS, all the things in a workflow. Especially when you start to then say, “Well, if we’re already using JS for the HTML, why not use it for CSS too?” You start to exclude a lot of really talented people from the development process. It’s just a really big loss for the project for the community as a whole.
Drew: Well, I certainly am… I started picking up React at the beginning of 2020, adding that to my skillset. I’ve been doing it now for nearly seven months. I’ve got to say one part I’m least confident in is setting up the tooling around getting a project started.
Drew: It seems like there’s an awful lot of work to get something to Hello World, and there’s even more that you’ve got to know to get it to be production ready. That has to make development more difficult to get started with if this is being put forward as what you should be doing in 2020 to learn to be a web developer. Somebody coming in new to it is going to have a real problem. It’s going to be a real barrier to entry, isn’t it?
Chris: Absolutely. The other piece here is that JavaScript developers aren’t always the only people working on a code base or contributing in a meaningful way to that code base. The more we make knowing JavaScript a requirement for working with a code base, the less likely those people are to be able to actually participate in the project.
Chris: An example of that, that I like to talk about is WordPress, who has been recently… I shouldn’t say recently at this point. It’s been a couple of years now. But they’ve been shifting their back-end stack more and more to JavaScript, away from PHP, which is not inherently a bad thing. Their new editor, Gutenburg, is built on React.
Chris: In 2018, WordPress’s lead accessibility consultant, Rian Rietveld, whose name I almost certainly butchered… she very publicly resigned from her positioned and documented why in a really detailed article. The core of the problem was that her and her team were tasked with auditing this editor to make sure that it was going to be accessible. WordPress comprises now 30% of the web. Their goal is to democratize publishing, so accessibility is a really important part of that. It should be an important part of any web project. But for them in particular, it is acutely important. Her team’s whole job is to make sure… her team’s whole job was to make sure that this editor would be accessible. But because neither she nor anyone on her team had React experience and because they couldn’t find volunteers in the accessibility community with that experience, it made it really difficult for her and her team to do their work.
Chris: Historically, they could identify errors and then go in and fix them. But with the new React based workflow, they were reduced to identifying bugs and then filing tickets. They got added to a backlog along with all the other feature development requests that the JavaScript developers were working on. A lot of stuff that could have been easily fixed didn’t make it into the first release.
Chris: In May of 2019, about a year after Rian resigned, there was a detailed accessibility audit done on Gutenburg. The full report was 329 pages. The executive summary alone was 34 pages. It documented 91 accessibility related bugs in quite a bit of detail. Many of these were really… I don’t want to call them simple low-hanging fruit, but a lot of them were basic things that Rian’s team could have fixed and it would have freed up the developers to focus on feature development. That’s ultimately what it seems like they ended up doing, was spending a lot of time on feature development and pushing this stuff off til later. But that team is super important to the project, and they suddenly got locked out of the process because of a technical choice.
Chris: Alex Russell is a developer on the Chrome team. He wrote this article a couple of years ago called The Developer Bait and Switch, where he talked about the straw man argument of frameworks. This idea that these tools let you move faster and because of that, you can iterate faster and deliver better experiences. It’s this idea that a better developer experience means a better user experience. I think this is a very clear example of how that argument doesn’t always play out the way people believe it does. It’s a better experience for maybe some people, not for everyone.
Chris: CSS developers, people working on design systems, their ability to create tools that others can use sometimes gets limited by these tool choices too. In my experience, I used to be better at CSS. It’s changed a lot in the last few years and I am nowhere near as good as I used to be. In my experience, the people who are really advanced CSS developers… and I do mean that in the truest sense. People who work on CSS are proper web developers working on a programming language. It’s a very special, or can be a very specialized thing. The people who are exceptionally good at it, in my experience, are not always also very good at JavaScript because you end up diving really deep into one thing and you slide a little bit on some other stuff. Their ability to work with these technologies gets hindered as well, which is too bad because it used to not be the case.
Chris: When the stack was simpler, it was easier for people from multiple disciplines to participate in the development process. I think that’s to the detriment of both the things we build and the community at large, when that’s no longer the case.
Drew: I found recently in a project researching ways to deal with some of the CSS problems, workflow problems, we’re having multiple working on the project and the bundle size increasing and the old CSS never getting removed. It was a React project, so we were looking at some of these CSS in JavaScript approaches to see what would be best for us to use to solve the problems that we had. What became very quickly apparent is there’s not only one solution to do this. There are dozens of different ways you could do this.
Drew: CSS in JS is a general approach, but you might go from one project to the next and it’s completely influenced in a completely different way. Even if you’re a CSS person and you learn a particular approach on a project, those skills may not be transferrable anyway. It’s very difficult to see how somebody should investment too much time in learning that if they’re not particularly comfortable with JavaScript.
Chris: Yeah. The other interesting thing that I think you just got out a little bit is when I talk about this, one of the biggest pieces of push-back I get is that frameworks enforce conventions. You’re going with Vanilla JavaScript, you’ve got this green field-blue sky, you can do anything you want kind of project. With React, there’s a React way to do things.
Chris: But one of the things I have found is that there are Reacty approaches, but there’s not a strict one right way to do things with React. It’s one of the things people love about it. It’s a little bit more flexible, you can do things a couple of different ways if you want. Same with Vue. You can use that HTML based thing where you’ve got your properties right in the HTML and Vue replaces them, but you can also use a more JSX-like templating kind of syntax if you’d prefer.
Chris: I’ve heard multiple folks complain about when they’re learning React, one of the big problems is you Google how to do X in React and you get a dozen articles telling you a dozen different ways that you could do that thing. That’s not to say they don’t put some guardrails on a project. I don’t think it’s as clearcut as, “I’ve chosen a framework. Now this is the way I build with it.” To be honest, I don’t know that that’s necessarily something I’d want either. I don’t think you’d want those tightly confined… some people do, maybe. But if you’re touting that as a benefit, I don’t think it’s quite as pronounced as people sometimes make it out to be.
Chris: You got into an interesting thing though just there, where you were mentioning the CSS that is no longer needed. I think that is one of the legitimately interesting things that something like CSS and JS… or tying your CSS to JavaScript components in some way can get you is if that component drops out, the CSS also in theory, goes away with it. A lot of this to me feels like throwing engineering at people problems. Invariably, you’re still dependent on people somewhere along the line. That’s not to say never use those approaches, but they’re certainly not the only way to get at this problem.
Chris: There are tools you can use to audit your HTML and pull out the styles that aren’t being used even without using CSS and JavaScript. You can write CSS “the old-fashioned way” and still do the linting of unused styles. There are authoring approaches to CSS that give you a CSS in JS-like output and keep your style sheet small without spitting out these gibberish human unreadable class names that you get with CSS and JS sometimes. Like X2354ABC, or just these nonsense words that get spit out.
Chris: This is where I start to get really into the old man yells at cloud kind of thing. I’m really showing my developer age here. But yeah, it’s not necessarily that these things are bad, and they’re built to solve legitimate problems. I sometimes feel like there’s a little bit of a… if it’s good enough for Facebook, it’s good enough for us kind of thing that happens with these. Well, Facebook uses this tool. If we’re a real engineering program… team, department, organization, we should too. I don’t necessarily think that’s the right way to think about it. It’s because Facebook deals with problems that you don’t, and vice-versa. The size and scale of what they work on is just different, and that’s okay.
Drew: Exactly. I see some of these things like CSS and JavaScript to be almost like a polyfill. We’ve got legitimate problems, we need a way to solve it. The technology isn’t providing us a way to solve it yet. Maybe whilst we wait for the web platform to evolve and to get around to addressing that problem, this thing that we do right now with JavaScript kind of will see us through and we’ll be okay. We know it’s bad. We know it’s not a great solution, but it helps us right now. And hopefully in the while we can pull it out and use the native solution.
Chris: It’s really funny you bring this up. Because literally last night, I was watching a talk from Jeremy Keith from last year about progressive web apps. But he was talking about how a couple of decades ago, he was trying to convince people to use JavaScript. Which seems ridiculous at the time, but JavaScript was this new thing. He showed people how you could do cool things like change the color of a link on hover with this new… It seems absurd that you would need JavaScript for that now, because that’s what CSS does for you. But things like the focus attribute or property just didn’t exist at the time.
Chris: One of the things he said in the talk that I think really resonated with me is that JavaScript in many ways, paves those cow paths. It’s this very flexible and open language that we can use to create or bolt in features that don’t exist yet. And then eventually, browsers catch up and implement these features in a more native way. But it takes time. I completely understand what you’re saying about this. It’s not the perfect solution, but it’s what we have right now.
Chris: I think for me, the biggest difference between polyfills and some of these solutions is polyfills are designed to be ripped out. If I have a feature I want to implement that the browser doesn’t support yet, but there’s some sort of specification for it and I write a polyfill… once browsers catch up, I can rip that polyfill out and I don’t have to change anything. But when you go down the path of using some of these tools, ripping them up out means rewriting your whole code base. That’s really expensive and problematic. That’s not to say never use them, but I feel really strongly that we should be giving thought to picking tools that can easily be pulled out later. If we no longer need them or the platform catches up, it doesn’t require a huge rewrite to pull them out.
Chris: So getting to that we have a whole bunch of styles we don’t use anymore thing, that’s why I would personally favor a build tool technology that audits your CSS against the rendered markup and pulls out the things you don’t need. Because down the road if a platform catches up, you can pull that piece of the build tool out without having to change everything. It’s just augmenting what you already have, whereas CSS and JS doesn’t give you that same kind of benefit. I’m just picking on that one, but I think about a lot of these technologies more broadly.
Chris: I do feel things like React or Vue are probably paving some cow paths that browsers will eventually catch up with and probably use similar approaches if not the same, so there may be less rewriting involved there. A lot of the ecosystem stuff that gets plugged in around that may be less so.
Drew: I think it’s right, isn’t it, that the web platform moves slowly and carefully. You think if five years ago, we were all putting JavaScript Carousels on our pages. They were everywhere. Everyone was implementing JavaScript Carousels. If the web platform had jumped and implemented a Carousel solution to satisfy that need, it would not be sat there with nobody using it because people aren’t doing that with Carousels anymore. Because it was just a fad, a design trend. To counteract that and stop the platform itself becoming bloated and becoming a problem that needs solving, it does have to move at a lot steadier pace. The upshot of that is HTML that I wrote in 1999 still works today because of that slow process.
Drew: One of the other areas where things seem to be bloating out on the web is… I guess it’s related to the framework conversation. But it’s the concept of a single-page app. I feel like that a lot of promises are made around single-page apps as to their performance, like you’re getting all this benefit because you’re not reloading the entire page framework. I feel like they don’t always make good on those performance promises. Would you agree with that?
Chris: Yes. Although I will confess, despite having a very lengthy chapter in my book on this and talking about that a lot in talks and conversations with people, I don’t think single-page apps are always a terrible thing. But I do think this idea that you need one for performance is overstated. You can oftentimes get that same level of performance with different approaches.
Chris: I think one of the bigger challenges with single-page apps is… For anybody who’s unfamiliar with those. When a single-page app, instead of having separate HTML files or if you’re using something like a database driven site like WordPress, even though you don’t have actual physical HTML files for each page in your WordPress site, WordPress is creating HTML files on the fly and sending them back to browsers when URLs are requested. For purposes of this conversation, instead of having separate HTML files for every view in your app, a single-page app has a single HTML file. That’s what makes it a single-page app. JavaScript handles everything. Rendering the content, routing to different URL paths, fetching new content if it needs to from an API or something like that.
Chris: One of the spoken benefits of these or stated benefits of these is that only the content on the page changes. You don’t have to re-download all the JS and the CSS. Oh, and you can do those fancy page transitions that designers sometimes love. In theory, this is more performant than having to reload the whole page.
Chris: The problem with this approach from my perspective is that it also breaks a bunch of stuff that the browser just gives you for free out-of-the-box, and then you need to recreate it with more JS. You have an app that’s slow because it has a lot of JS. So you throw even more JavaScript at it to improve that performance and in doing so, you break a bunch of browser features and then have to re-implement those with even more JS too.
Chris: For example, some things that the browser will do for free with a traditional website that you need to recreate with JavaScript when you go the single-page app. You need to intercept clicks on links and suppress them from actually firing, with your JavaScript. You then need to figure out what you actually need to show based on that URL, which is normally something that would get handled on the server or based on the file that goes with that URL path. You need to actually update the URL in the address bar without triggering a page reload. You need to listen for forward and back clicks on the browser and update content again, just like you would with clicks on links. You need to update the document title.
Chris: You also need to shift focus in a way that announces the change in page to people who are using screen readers and other devices so that they’re not confused about where they are or what’s going on. Because they can’t see the change that’s happening, they’re hearing it announced. If you don’t actually shift focus anywhere, that announcement doesn’t happen. These are all things that the browser would do for you that get broken with single-page apps.
Chris: On top of that, because you have all this extra JavaScript, this is complicated. So most people use frameworks and libraries to handle this sort of thing. Because of all this extra JavaScript to support this approach, you end up with potentially slower initial page load than you would have otherwise. Depending on the content you have, this approach I think sometimes can make sense. If you have an app that is driven by API data where you don’t necessarily know what those URL paths are going to look like ahead of time.
Chris: Just an example here. You have an animal rescue where you have some adoptable animals, and that data comes from Petfinder, the animal adoption website. You have a bunch of animals there. Petfinder manages that, but you want to display them on your site with the Petfinder API. When your website’s being built, it doesn’t always necessarily have visibility to what pets are available in this exact moment and what kind of URL paths you’re going to need. A single-page app can help you there because it can dynamically on the fly, create these nice URLs that map with each dog or cat.
Chris: Something like Instagram with lots of user created content, maybe that also makes sense. But for a lot of things, we do know where those URLs are going to be ahead of time. Creating an HTML file that has the content on it already is going to be just as fast as… sometimes even faster than the JavaScript based single-page app approach, especially if you use some other techniques to keep your overall CSS and JavaScript size down. I use this approach on a course portal that I have. The page loads feel instantaneous because HTML is so easy for browsers to render compared to other parts of the stack. It feels like a single-page app, but it’s not.
Drew: Especially when you consider hosting solutions like a Jamstack approach of putting HTML files out in a CDN so it’s being served somewhere physically close to the user.
Chris: Yep.
Drew: Loading those pages can just be so, so quick.
Chris: Yes. Absolutely. Absolutely. One of the other arguments I think people used to make in favor of single-page apps is offline access. If someone loads it and then their network goes down, the app is already up and all the routes are handled just with the file that’s already there. So there’s no reloading, they don’t lose any work. That was true for a long time. Now with service workers and progressive web apps, that is I think less of a compelling argument, especially since service workers can fetch full HTML files and cache them ahead of time if needed.
Chris: You can literally have your whole app available offline before someone has even visited those pages if you want. It just happens in the background without the user having to do anything. It’s again, one of those technologies that maybe made sense for certain use cases a few years ago a little less compelling now.
Drew: It reminds me slightly of when we used to build websites in Flash.
Chris: Yes.
Drew: And you’d have just a rectangle embedded in an HTML page which is your Flash Player, and you’d build your entire site in that. You had to reimplement absolutely everything. There was no back button. If you wanted a back button, you had to create a back button, and then you had to create what the concept of a page was. You were writing code upon code, upon code to reimplement just as you are saying things that the browser already does for you. Does all this JavaScript that we’re putting into our pages to create this functionality… is this going to cause fragility in our front-ends?
Chris: Yes. This is almost certainly from my mind, one of the biggest issues with our over-reliance on JavaScript. JavaScript is just by its nature, is a scripting language, the most fragile part of the front-end stack.
Chris: For example, if I write an HTML element that doesn’t exist, I spell article like arcitle instead of article and the browser runs across that, it’s going to be like, “Oh, I don’t know what this is. Whatever, I’ll just treat it like a div.” And it keeps going. If I mistype a CSS property… Let’s say I forget the B in bold, so I write old instead, font way old. The browser’s going to be, “I don’t know what this is. Whatever, we’ll just keep going.” Your thing won’t be bold, but it will still be there.
Chris: With JavaScript, if you mistype a variable name or you try to use a property, you try to call a variable that doesn’t exist or a myriad of other things happen… your minifier messes up and pulls one line of code to the one before it without a semicolon where it needs one, the whole app crashes. Everything from that line on stop working. Sometimes even stuff that happens before that doesn’t complete, depending on how your app is set up. You can very quickly end up with an app that in a different approach, one where you rely a lot more on HTML and CSS, it would work. It might not look exactly right, but it would still work… to one that doesn’t work at all.
Chris: There’s an argument to be made that in 2020, JavaScript is an integral and important part of the web and most people don’t disable it and most people are using devices that can actually handle modern JavaScript. That’s true, but that’s not the only reason why JavaScript doesn’t work right, even if you have a linter there for example and you catch bugs ahead of time and things. There’s plenty of reasons why JavaScript can go horribly awry on you. CDNs fail.
Chris: Back in July of last, a year ago this month… at least, when we’re recording this… a bad deploy took down Cloudflare. Interestingly as we’re recording this, I think a week or two ago, Cloudflare had another massive outage that broke a whole bunch of things, which is not a knock on Cloudflare. They’re an incredibly important service that powers a ton of the web. But CDNs do sometimes go down. They are a provider used by 10% of Fortune 1,000 companies. If your JS is served by that CDN and it breaks, the JavaScript file never loads. And if your content is dependent on that JS, your users get nothing instead of getting something just not styled the way you’d like.
Chris: Firewalls and ad blockers get overly aggressive with what they block. I used to work at a company that had a JavaScript white list because they were extremely security conscious, they worked with some government contract stuff. They had a list of allowed JavaScript, and if your site or if your URL wasn’t part of that, no JavaScript. You have these sites. I remember going to a site where it had one of the hamburger kind of style menus on every view whether it was desktop or mobile, and I could not access any page other than the homepage because no JavaScript, no hamburger, that was it.
Chris: Sometimes connections just timeout for reasons. Either the file takes a while or someone’s in a spotty or slow connection. Ian Feather, an engineer at BuzzFeed, shared that about 1% of requests for JavaScript on the site fail which is 13 million requests a month. Or it was last year, it’s probably even more now. That’s a lot of failed JavaScript. People commuting go through tunnels and lose the internet. There’s just all sorts of reasons why JavaScript can fail and when it does, it’s so catastrophic.
Chris: And so we built this web that should be faster than ever. It’s 2020, 5G is starting to become a thing. I thought 4G was amazing. 4G is about as fast as my home wifi network. 5G is even faster, which is just bonkers. Yet somehow, we have websites that are slower and less performant than they were 5 or 10 years ago, and that makes no sense to me. It doesn’t have to be that way.
Drew: How do we get out of this mess, Chris?
Chris: Great question. I want to be really clear. I know I’ve hammered on this a couple times. I’m not saying all the new stuff is bad, never use it. But what I do want to encourage is a little bit more thoughtfulness about how we build for the web.
Chris: I think the overlying theme here is that old doesn’t mean obsolete. It doesn’t mean never embrace new stuff, but don’t be so quick to just jump on all the shiny new stuff just because it’s there. I know it’s one of the things that keeps this industry really exciting and makes it fun to work in, there’s always something new to learn. But when you pick these new things, do it because it’s the right tool for the job and not just because it’s the shiny new thing.
Chris: One of the other things we didn’t get into as much as I would have liked, but I think is really important, is that the platform has caught up in a really big way in the last few years. Embracing that as much as possible is going to result in a web experience for people that is faster, that is less fragile, that is easier for you to build and maintain because it requires fewer dependencies such as using what the browser gives you out-of-the-box. We used to need jQuery to select things like classes. Now browsers have native ways to do that. People like JSX because it allows you to write HTML in JavaScript in a more seamless way. But we also have template literals in Vanilla JavaScript that give you that same level of ease without the additional dependency. HTML itself can now replace a lot of things that used to require JavaScript, which is absolutely amazing.
Chris: We talked a little bit about… this is a CSS thing, but hovers over links and how that used to require JavaScript. But using things like the details and summary elements, you can create disclosure, like expand and collapse or accordion elements natively with no scripting needed. You can do auto complete inputs using just a… I shouldn’t say just, I hate that word. But using a humble input element and then a data list element that gets associated with it, with some options. If you’re curious about how any of this stuff works over at vanillajstoolkit.com, I have a bunch of JavaScript stuff that the platform gives you. But I also have some used to require JavaScript and now doesn’t kind of things that might be interesting too if you want some code samples to go along with this.
Chris: On the CSS side of things, my most popular Vanilla JS plugin ever is this library that lets you animate scrolling down to anchor links. It is very big. It’s the hardest piece of code I’ve ever had to write. And it now is completely replaced with a single line of CSS, scroll behavior smooth. It’s more performant. It’s easier to write. It’s easier to modify its behavior. It’s just a better overall solution.
Chris: One of the other things that I wish we did more is leaning on multi-page apps. I feel a little bit vindicated here, because I recently saw an article from someone at Google that actually pushes for this approach now too. I thought that was pretty interesting, given this huge angular and then framework… all the things, boom, that Google started a few years back. Kind of cool to see them come back around to this. Using things like static site generators and awesome services like Netlify and CDN caching, you can create incredibly fast web experiences for people using individual HTML files for all of your different views. So kind of leaning on some of this out-of-the-box stuff.
Chris: In situations where that’s not realistic for you, where you do need more JavaScript, you do need some sort of library, maybe taking a look at the smaller and more modular approaches first instead of just going for the behemoths of the industry. Instead of React, would Preact work? Instead of angular… I mean, instead of Vue rather, would Alpine JS work? There’s also this really interesting pre-compiler out there now called Svelt, that gives you a framework-like experience and then compiles all your code into Vanilla JavaScript. So you get these really tiny bundles that have just what you need and nothing else. Instead of CSS and JavaScript, could you bolt in some third party CSS linter that will compare your HTML to your CSS and pull out the stuff that got left in there by accident? Would a different way of authoring your CSS, like object oriented CSS by Nicole Sullivan, work instead? We didn’t really get to talk about that, but it’s a really cool thing people should check out.
Chris: And then I think maybe the third and most important piece here, even though it’s less of a specific approach and more just a thing I wish more people kept in mind, is that the web is for everyone. A lot of the tools that we use today work for people who have good internet connections and powerful devices. But they don’t work for people who are on older devices, have spotty internet connections. This is not just people in developing areas. This is also people in the U.K., in certain parts of the U.S. where we have absolutely abysmal internet connections. The middle of our country has very slow internet. I know there’s places in part of London where they can’t wire a new broadband in for historical reasons, so you’re left with these old internet connections that are really bad. There’s places like that all over the world. Last time I was in Italy, same thing. The internet there was horrible. I don’t know if it’s changed since then.
Chris: The things we build today don’t always work for everyone, and that’s too bad. Because the vision of the web, the thing I love about it, is that it is a platform for absolutely everyone.
Drew: If listeners want to find out more about this approach, you’ve gone into loads of detail to it in your book, The Lean Web. And that’s available online. Is it a physical book or a digital book?
Chris: It’s a little bit of both. Well, no. It’s definitely not a physical book. You go to leanweb.dev. You can read the whole thing for free online. You can also if you want, there’s EPUB and PDF versions available for a really small amount of money, I forget how much now. I haven’t looked at it in a while. The whole thing is free online if you want it. You can also watch a talk on this topic where I go into more details if you want.
Chris: But I’ve also put together a special page just for listeners of Smashing Podcast at gomakethings.com/smashingpodcast, because I’m very creative with naming things. That includes a bunch of resources in addition to the book, around things that we talked about today. It links to a lot of the different techniques that we covered, other articles I’ve written that go deeper into some of these topics and expand on my thinking a little bit. If folks want to learn more, that would probably be the best place to start.
Drew: That’s terrific. Thank you. I’ve been learning all about the Lean Web. What have you been learning about lately, Chris?
Chris: Yeah, a couple of things. I alluded to this a little bit earlier with watching Jeremy’s video on progressive web apps. I have been putting off learning how to actually write my own progressive web app for a couple of years because I didn’t have a specific need on anything I was working with. I recently learned from one of my students who is in South Africa, that they have been dealing with rolling blackouts because of some stuff they have going on down there. As a result, she is not able to work on some of the projects we’ve been doing together regularly, because the power goes out and she can’t access the learning portal and follow along.
Chris: For me, now building an experience where it works even if someone doesn’t have internet has become a higher priority than… I realized that maybe it was before, so I just started digging into that and hope to get that put together in the next few weeks. We’ll see. Jeremy Keith’s resources on this have been an absolute lifesaver though. I’m glad they exist.
Chris: I know, Drew, you mentioned one of the reasons you like to ask this question is to show that people no matter how seasoned they are, are always learning. Just a little related anecdote. I have been a web developer for I think, about eight years now. I still have to Google the CSS property to use for making things italic, literally every single time I use it. For some reason, my brain defaults to text decoration even though that’s not the right one. I’ll try a couple of combinations of different things, and I always have one word wrong every time. I also sometimes write italics instead of italic. Yeah. If anybody ever there is ever feeling like, oh, I’m never going to learn this stuff… just know that no matter how seasoned you are, there’s always some really basic thing that you Google over and over again.
Drew: I’ve been a web developer for 22, 23 years, and I have to Google the different properties for Flexbox still, every time. Although I’ve been using that for 23 years. But yeah, some things just… there’s probably going to more of those as I get older.
Chris: Yeah. Honestly, I ended up building a whole website of stuff I Google over and over again, just to have an easier copy-paste reference because that was easier than Googling.
Drew: That’s not a bad idea.
Chris: That’s the kind of lazy I am. I’ll build a whole website to save myself like three seconds of Googling.
Drew: If you the listener would like to hear more from Chris, you can find his book on the web at leanweb.dev, and his developer Tips newsletter and more at gomakethings.com. Chris is on Twitter at Chris Ferdinandi. And you can check out his podcast at vanillajspodcast.com or wherever you usually get your podcasts. Thanks for joining us today, Chris. Do you have any parting words?
Chris: No. Thank you so much for having me, Drew. I had an absolutely smashing time. This was heaps of fun. I really appreciate the opportunity to come chat.
(il)
From our sponsors: Smashing Podcast Episode 21 With Chris Ferdinandi: Are Modern Best Practices Bad For The Web?