I wrote a post last week, “10 things I learned making the fastest site in the world”. All was going well, I had the usual wonderfully constructive comments on medium and snarky ones on reddit. But then I came across this friendly but rage-inducing comment:

I was not happy (Jan). I had let my readers down. I had let myself down. And most of all, I had let the foxes down.

I decided that I wouldn’t rest until I was faster than motherfuckingwebsite.com.

Then I had a little rest.

Then I got to work on the last piece of my web app I thought I could make faster — replacing React with VanillaJS.

You’ll find the site here (it’s a work in progress) and the source is on github, feedback is the aim of the game so don’t be shy.

What is React?

You know what React is, why are you even asking?

But now that you have, I will point out that I’m using “React” as an umbrella term in this post, to refer to concepts shared by React and Preact and friends, and sometimes to concepts from flux/redux.

What is VanillaJS?

VanillaJS is a framework written many years ago by a dude called Brendan that is rarely used anymore. It has quite a few interesting features that I thought would be useful in my project, so I dusted off the spider webs — or whatever you call the webs of spiders in your weird country — and reacquainted myself with the framework of frameworks.

This must be confusing for those of you new to web development. Allow me to speak plainly for a moment: [serious voice] When I say VanillaJS I am simply referring to JavaScript and the DOM APIs. I am gently poking fun at the fact that most of us wouldn’t even consider writing code without first picking at least one framework or library, hence talking about JavaScript as though it was a framework. [end serious voice]

How does one go about replacing React with VanillaJS?

I am so, so glad you asked. I decided to try something unusual with this endeavor and write the blog post first. It worked out really well, because as I’m writing a post I’m imagining detractors in the comments picking apart every decision I make (you guys are mean).

It’s like rubber ducking on steroids, and it helped me get the design decisions stable in my head before starting to write any code.

One of the things that crystallized for me is that there are three distinct parts to React that make it great:

JSX syntax Components/composability One-directional data flow (UI > action > state > magic > UI)

As I picked these apart I came to realise something. The performance overhead that React brings comes from two places:

The sheer effort of parsing 60 KB of JavaScript. The magic that happens after you update the state, before the DOM updates.

The first of these — the time taken to parse the framework— I can solve by not using the framework (like how I avoid arguments with people by never talking to people).

The second one — the time taken to update the UI — is much more difficult; there’s something for you to look forward to in about 9 minutes.

So of the three things that make React great, only the third one introduces a performance penalty.

The result is, I want to replicate JSX, I want to replicate components, and I want to come up with some new way to update the UI when state changes.

[movie trailer voice]

And he’s only got 48 hours to do it.

[end movie trailer voice]

#1 Replicating JSX

I like JSX.

I like that it visually represents the output HTML, but doesn’t shy away from the fact that I’m using JavaScript. It taught me that ‘separation of concerns’ doesn’t mean ‘separation of languages into different files’.

My key objective in replicating JSX is to be able to define my components in a way that is visually similar to the resulting HTML — just like JSX does — but in VanillaJS.

First up, I don’t want to be writing document.createElement() over and over. So I’ll write a shorthand function for that:

This uses VanillaJS’s “virtual DOM” technology to create an element without actually writing it to the document.

My laziness doesn’t stop there, though. I don’t want to have to type makeElement('h1') all the time either, so I’ll write another shorthand function.

Let’s test this out…

That’s amazing.

I probably want some text in my h1 though, let me extend my functions…

I astound myself.

You know what though, I probably want to give that element a class. Maybe even set some other attributes one of these days. Hey I know! I’ll pass in an object with some properties and values. Then I’ll iterate over it, applying all the properties.

Since I’m now passing a few different arguments, I’ll update my h1 function to just pass all of its args along to makeElement .

I’m speechless.

…

Still speechless.

…

OK this is great but it’s of no use to me if I can’t nest my elements. That was, like, nine words in a row with three or less letters!

Before I go any further I will take a piece of HTML from my site and work toward being able to create that.

Looked at it? Good.

So, to generate this nested HTML, I will need to extend my makeElement function to handle other elements being passed in. It will simply append those to the element it returns. For example, I need a div that I pass a header to. And I will pass an h1 and an a to that header . Have you ever noticed how HTML tags are like functions?

No? Really? Whatever.

At this point I ran into a bit of complexity because for this to be useful, the arguments could be all sorts of things in all sorts of wacky orders. I’ll need to do some fancy footwork to work out what each argument is.

[David from the future here, this was the only difficult part, so stick in there, champ.]

I know the first argument to makeElement will always be a tag name, such as “h1”. But the second argument could be:

An object defining the props for the element

A string defining some text to display

A single element

An array of elements

Anything after the second argument will be an element or an array of elements, I’ll use the rest syntax again (the most relaxing of all the syntaxes) to gather these up into a variable called otherChildren . Most of the complexity here is to allow flexibility in what can be passed to makeElement .

Boom, there’s my frontend framework, 0.96 KB.

I should put it on npm and call it elementr and gradually add features until it’s 30 KB at which point I will realise that maintaining a package on npm is a thankless task that I regret deeply. My only recourse will be to escape to a dessert island and gorge myself on crème brulee until the end of my days.

One of the other great things about React is the helpful errors. They save so much time, so I’ve built in some checks ( if (propName in el) and if (styleName in el.style) ) so I get a nice warning when I inevitably try to set herf and backfroundColor .

I think half the skill in programming is predicting the stupid things you’ll do in the future and protecting against them now.

I now have a function that I can throw pretty much anything at and it will return a little DOM tree for me.

Let’s vigorously kick the tires:

I find that quite readable. In fact it looks remarkably similar to my desired output HTML. Don’t have the time to scroll back up?

If I try and look at all that JavaScript as functions, I’ll go (more) insane trying to work out what returns what. But I started to look at the h1 , div , etc. as HTML tags with different shaped brackets, and after a bit of adjusting, and a lot of squinting, my brain began to do a real-time transformation and I now just see the resulting HTML.

Thanks, brain.

Bonus: since the props you pass to an element are just objects, and JavaScript is wonderful and functions are objects, you can go right ahead and pass in a property called onclick with a function as the value and the VanillaJS event system will bind a click event to that element for you.

Isn’t that just bonkers? I love that I didn’t even think about events till I got halfway through, then felt stupid for not taking them into account, then felt like the god of programming when I realised that they would Just Work.

So that’s what love feels like. It’s nice!

#2 Replicating React components

Now, here’s the cool part. The above stuff is all just functions, right? And by nesting them, we have functions that return functions that return functions that eventually return elements.

And what’s a component in React? It’s just a function that returns an element (more or less). So I can arbitrarily group some functions into a function, give it a capital letter and call it a component. I can even pass it props just like I was using React.

The below outputs the same HTML as above, but is grouped into “Components”.

This feels like React doesn’t it?

And all for about 6 hours of writing code (yes it took me 6 hours to write 73 lines of code. Somehow I feel proud and ashamed of that at the same time. I don’t know why I’m telling you all this.)