awarm.spacenewsletter | fast | slow

Why my website's built with react

Warning: this is a bit of a technical one. Nerdery about web frameworks lies ahead.

A couple days ago Tom MacWright1 published this article: Second-guessing the modern web.

He's digging into the current trend in web-development of rendering an entire site "client side" with React, and isn't entirely convinced it's the right way to do things.

What "client side" means is instead a server generating a bunch of HTML and sending it your browser, it sends you a bunch of code that generates that html in your browser itself.

React is a massively popular library that makes it significantly easier for developers to write code to do client-side rendering. In Tom's post it stand's in for the whole class of things like it. More on react in a bit.

I don't want to get into all the tradeoffs here so I'll just summarize Tom's point as: Client side rendering is just not worth it in many cases and developers are doing all sorts of hacks to get to a point that they would be at if they'd just not used it at all.

He also has this:

I can, for example, guarantee that this blog is faster than any Gatsby blog (and much love to the Gatsby team) because there is nothing that a React static site can do that will make it faster than a non-React static site.

Which hit's a little close to home. As you gathered from the subject line, my site built with React. 😬. And if I'm being honest, I could 100% make my site without it. The vast majority of pages I"m working with are simple mappings of data to HTML, without any kind of dynamic interactions (the thing React is actually good for).

So why use react?

The thing is, using React in these cases looks exactly like a direct mapping between data and HTML! I have functions which take in data and output trees. Everything is just javascript and I don't have to bother with funky HTML templates that approach a full-fledged programming language.

Take a look at the code for my blog page:

It's pretty tiny! Just some normal javascript function calls, arrays, and objects, that are nested exactly like the HTML they produce.

None of this is unique to React, I could do the same with a library like lit-html, but it is a testament to how good of an abstraction it is. It extends naturally from the simplest case to arbitrarily complex ones.

Defending react as an abstraction

But of course it's not about the simplest case. There's a lot of hate for react in the Hacker News' discussion of the blog post (though the OP itself is pretty even-handed), focusing on it's complexity. This I entirely disagree with. React at it's core is two things:

  1. Components defining HTML trees as pure functions
  2. An API for defining "side-effects"2 in those components

"React", as commentators are talking about it, really begins with 2 though. Things get a little messy as relatively recently in React's history the devs introduced something called Hooks, which radically simplifies how it's done, and IMO moves it closer to the ideal of react. Using just functions you can define (and compose!) all the "actions" your component has to do. It's a similar idea of composition as React Components themselves, and in my opinion is a definite improvement on old react and anything else I've seen.

Okay but why does a blog need this?

The core appeal of React is the ability to build things up from these simple abstractions, and to ignore them if you want to. I can, without changing anything about my stack, implement pretty much anything I dream up.

My site isn't just a place to store documents, it's a playground for me to experiment with different ways of thinking, doing, and communicating. I want to be able to have my writing yes, but to also do weird experiments when I want to, like making an interactive visualizer of the git history of my site, or having small widgets like Kyle Mitchell's approval and listmaking apps.

Having this flexibility comes with a tradeoff of course. React is not a "zero cost abstraction" 3. I have to include the entire react runtime on every page on the website, even when it's not used at all, or only for a tiny portion of the page. The simple static pages on my site still weigh 4 about ~100kb. For comparision, the blog post I linked at the start of this newsletter weighs 10kb.

There is however some hopeful developments here. Next.js, the framework I use, to build this site and others, recently added an experimental flag to entirely remove the react run time, on a page by page basis. This page-by-page thing is kinda next's whole shtick. It lets you decide granularly how you want your site to be rendered and function. And now it's letting you get even more specific and remove everything to get the base state performance Tom's talking about in his post.

Of course there are problems with React apps other than the page weight. Using any javascript framework means javascript is necessary to run your website. And this creates issues where, for example, the buttons on your site don't work until the javascript's loaded.

Is this the future??

One way to frame the tension here is as between servers and clients. React and other tools like it do most of their work in the client, close to where people are actually interacting with websites. The alternative is doing work on the server where you have much more powerful resources. Both clients and servers and their associated computing environments are getting more powerful all the time, and their trade-offs persist.

The future lies in building systems that let developers more easily navigate those trade-offs.

Right now, I think React lets you leverage the power of serverside computing much easier than server-rendering frameworks let you leverage the client. But I think there's a lot more room for better tooling and frameworks.

NextJS is exciting to me because it let's you make decisions on a page by page basis. What if you could get even more granular? What if you could decide between surgical handrolled javascript and the full React run-time on a percomponent basis? There's a lot left to explore.

  1. Tom's blog is awesome. I've particularly enjoyed his series digging into decentralized "hosting" systems and trying to use them to host his site. He's covered IPFS, DAT, arweave, and ipfs again. Also he has this very fun post on making a cocktail website

    2: side-effects are a programming term for actions, things like users pressing a button, or making a HTTP request to another website. Or fetching state.

  2. This is a term I first heard in the rust community but apparently stems from C++

    C++ implementations obey the zero-overhead principle: What you don't use, you don't pay for [Stroustrup, 1994]. And further: What you do use, you couldn't hand code any better.

  3. It's kinda wierd talking about how much pages weigh but I like it. More weight makes it slower for the site to reach you. More weight makes it more cumbersome to work with, requiring special tooling and workspaces.