Stop Writing JavaScript
Posted | Reading time: 9 minutes and 47 seconds.
The web has developed into a terrible place. First, it’s no longer as fun and colourful as it once was, despite my best efforts1. Secondly, all promises that one day we will have a nicely controlled way to quickly create highly performant websites have never been fulfilled. And it is getting worse.
Wait… What? Don’t we have highly sophisticated and fast frameworks? Like React?
Well, they are making it worse. Or, as Alex Russell put it in his magnificent blog post 2 that has heavily inspired this post and that you should absolutely read:
It’s not healing, and it won’t be enough to nurse the web back to health, but tossing the Vercels and the Facebooks out of polite conversation is, at least, a start. Alex Russell
Do you remember the promise of SPAs (Single Page Applications)? Our pages would become so much faster and more responsive in no time!
Yet, agilemanifesto.org has a slightly higher score than reactjs.org. The first page is from 2001, was built by a single person using html3.1, and is probably hosted on a virtual server somewhere, whereas reactjs.org was built in 2023 and uses all the latest and greatest, like server-side rendering, the latest version of react, CDN, you name it!
Shouldn’t a website from 2023 be significantly faster than its 20-year-old counterpart?
“Matthias, you can’t compare that! The one page is only static text, whereas the other…” yes, the other what? It’s also only text. No more. No less. It has more interactivity, but interactivity does not equal a better User Experience3, especially if it makes your website slow.4
Take the Linux kernel as a counterexample. In 2012, building the kernel on your computer took 1 to 2 hours on current hardware, whereas in 2023, we are down to 4 minutes5. And on the web? Buildpipelines for many teams take far longer than the Linux kernel. And after that, the websites aren’t even ready - only the code that will be downloaded to your computer to create the website. If the website needs 1 second to be rendered by your framework, and you have 4000 visitors, another computing hour is added only to display a website.
Note: Obviously there were some improvements; internet got faster, as did browsers. The Agile Manifesto is likely to load faster today on your computer than it did in 2001. This is, however, not thanks to new technologies in web development, only coincidental infrastructural bycatch.
Now that was something that became obvious to the grand framework creators, too. Or why do you think they try to push you to server-side rendering - because it’s simply not feasible to do all of this in the browser.
But let’s go back to the 2010s when all that ran its course. We were all terribly scarred by progressive enhancement and looked at the wisdom of the ancients6 7 (from 10 years before) to learn that we cannot separate presentation from content. Combine that with “a lot of applications need a lot of interaction, thus javascript, so let’s do all there”, and you’re almost at SPA. Oh, the promises. The simplicity of the idea that
view = component(state)(props)
A view
is a pure function with some properties and state… that was simply too alluring. THAT’s developer experience; it makes things so much more manageable! Thus, everybody started to do everything using that paradigm.
Well, developer experience is essential, but it should never come at the expense of user experience.
Should you put developer experience above user experience if this makes your website slower? And most of your web applications are still that: websites.
And even for your oh so dynamic web application, many parts of your website are still that: Text. Because most of us are not building a new Google spreadsheet, Figma or Miro. And even there, plenty of text does not have to be put through yet another render loop.
But the major frameworks are not built to allow other things next to them. So the header is in the application as well. And the footer. And the navigation. And especially the routing.
Why do we have to pull so many things into the javascript application, and thus onto the client side, which any cheap web server gives us for free? While adding a lot of complexity and even more scripts? Yes, there are libraries for all those things. But they don’t come for free. They add to the weight of your website and can’t possibly cover all use cases of your browser, so you’re back on the server to handle 404s8, only far more complicated than with a regular web application.
There’s another issue, which was highlighted by Stefan Tilkov 9 10 quite early - that your architecture does not get better with single-page applications, but actually worse. Because having the business logic on the server rather than on the client enables your application to allow immediate changes across all clients, not just your SPA. And one of the many things you might end up with is that you’re doing validation at least twice.
“But Matthias, Server Side Rendering is here to save us!” - Server side rendering makes things worse, people! Yes, it brings back great stuff like caching and even 404s. But at multiple costs. Let’s check what it actually does - In a server-side rendered single-page application, once the initial HTML and JavaScript code is loaded, subsequent interactions and content updates are typically handled by making requests to an API and dynamically updating the DOM using client-side JavaScript. Also, after the initial loading of the HTML page, the engines that are linking the server and client are usually trying to recreate their representation of the document, which is maybe fast but significantly harder than doing nothing, and then figuring out in what places updates have taken place to then trigger follow up updates.
Giving the client that much work just to open a page that was mostly simple enough to be a static HTML page is almost as bad as secretly installing Bitcoin miners on your visitor’s computers. You are wasting their CPU with nothing.
And what’s worse is that you basically achieve something very similar to classic MVC pages, only far more complicated and a nightmare to debug. Where would you even start when you figure there’s an issue in the performance of your website?
The other part is the simple fact that many of those frameworks lock you in. Once you’re using React, there’s little chance to escape or ask it nicely to play well with another framework. Yes, you can export react components as web components 11. It’s almost as easy as convincing a cat to take a bath. And in case you wonder, no, that idea doesn’t scale to your big monolithic ball of mud that you created, and that can be certified as unentangleable.
Once you enter their promise, you will be forced to rewrite everything in their framework, or you’ll end up with a very fragmented technology landscape with many things that cannot be shared easily. As a technology manager, on the other hand, it can be challenging to avoid big frameworks in your ecosystem, as they offer many pre-build solutions that will make development much faster initially. As your product becomes more complex and complicated, however, your team will be stuck firefighting performance problems, weird non-reproducible rendering bugs, and sophisticated ways of having reliable and predictable integration tests for the colossal web applications that we are creating today.
Yes, those problems will hit you. No matter how capable you or your peers are, given the complexity of the frameworks for single-page applications, and their SSR friends, you can’t understand all their implications. And thus, you will make minor errors in highly specialised cases that only the framework creators could have told you to avoid. And as all those little things pile up to ever slower applications, left behind are Product Owners that are disillusioned by their teams, and customers that wait for a second after clicking an entry in the top-level navigation.
Don’t get me wrong - I have been there too. I have used many big frameworks, from the Reacts and Angulars to the Backbones and Meteors. And they will always have a special place in my heart, right next to Adobe Flash12. But the promises of faster websites and ever-better user experiences were a lie, just like the cake. 13
Such a long rant. So, what do I propose?
I can tell you what I use for this website as a start. The blog is built with hugo, a static site generator. It pretty much does what site generators have done for centuries - it takes content, in Hugo’s case, markdown files, and creates static HTML. That static HTML you can then put on a server or just directly into a CDN.
But indeed, only some things on the page are static. But javascript is used economically. Let’s take code snippets like this one:
Those are web components that are used where they are needed. But they are embedded in between the static HTML, and their performance does not impact the rest of the page.
<p>Those are web components that are used where they are needed. But they are embedded in between the static HTML, and their performance does not impact the rest of the page.</p>
<highlight-code location="snippets/hello-world" show="preview,html">
Loading codebench...
</highlight-code>
<p>I don’t need to use javascript or sophisticated libraries like framer-motion<sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup> for things like animation, but all of that is done by CSS, as I had written in the previous blog post on my hidden relaunch<sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup>.</p>
I don’t need to use javascript or sophisticated libraries like framer-motion14 for things like animation, but all of that is done by CSS, as I had written in the previous blog post on my hidden relaunch15.
On top of that, it is essential to ensure that the correct metrics are visualized in order to gain meaningful insights. Unfortunately, many organizations overlook the importance of UX, instead focusing on developer experience and shipping speed or the first result on a lighthouse check which have a more tangible return on investment. So don’t just create dashboards that say “First Contentful Paint: 0.8 s” or “Performance: 100/100”. Create a visualization that you can trace back to your business KPIs, like “98% of bounces have slow Time to First Meaninful Paint”, “72% of non-recurring visitors encountered prolonged execution of JavaScript code” or 17% of visitors to the signup flow have performance that is below converting visitors average".
In modern web development, plenty of great tools can help you build fast and efficient websites without overloading them with JavaScript. Some of these tools, like Svelte and Lit, allow you to use JavaScript only as much as you need while still providing powerful features like reactive data binding and templating. Other tools, like Hugo and Eleventy, offer lightweight and flexible static site generators to help you create websites with minimal overhead. By choosing the right tool for the job, you can create both performant and easy-to-maintain websites without sacrificing functionality or design. And if you miss functional components, hey, I even wrote a library for you16.
Let’s return to the web’s roots and focus on simplicity, reusability and efficiency, and create a more inclusive and sustainable web for everyone. So that one day, we can come back to having super fast, static websites that even work on 2-year-old mobile phones, pipelines that are building as quick as the Linux kernel, and all we have to do is to agree to write a little less javascript.
-
Let’s bring back the old internet! - Matthias Kainer - linkedin.com ↩︎
-
Sutcliffe, Alistair & Hart, Jennefer. (2016). Analysing the Role of Interactivity in User Experience. International Journal of Human-Computer Interaction. 33. 10.1080/10447318.2016.1239797. - researchgate.net ↩︎
-
How long does it take to compile a kernel - askubuntu.com ↩︎
-
Separation Anxiety: The Myth of the Separation of Style from Content - Bob Stein - alistapart.com ↩︎
-
How to let react router respond with 404 status code? - Stackoverflow.com ↩︎
-
Why I hate your Single Page App - Stefan Tilkov - medium.com ↩︎
-
Wider die SPA-Fixierung - Stefan Tilkov - innoq.com (German only) ↩︎
-
Exporting a Web Component from a React Codebase using Webpack: A step-by-step guide - J Hinter - medium.com ↩︎
-
Adobe Flash - engaging and interactive content for the web - wikipedia.org ↩︎
-
“The cake is a lie” is a catchphrase from the 2007 video game Portal - wikipedia.org ↩︎
-
A Hidden Relaunch - Replacing a lot of jQuery code with some CSS - matthias-kainer.de ↩︎