A better frontend experience
Or how choo came to be
Recently I’ve been building choo, a sturdy frontend framework. It’s functional, has a tiny footprint (now ~7kb, soon ~4kb) and is most of all fun.
Choo’s my first attempt at a framework in two years (I’ve been programming for three), and is the result of very slow iteration. This post is a little overview of how it came to be, because though the repo is barely six weeks old we’ve been going at this for way longer.
A couple of years back I landed my first job. The main project was written in backbone, and we weren’t happy with the router. We eventually landed on using page.js, but I thought the API and internals could be done better. So I started wayfarer, a 1kb router using a radix trie for performant path traversal.
I used to hook up the history API manually onto the router, but felt it became tedious after a while. So six months ago sheet-router was born; a tiny router built around Wayfarer, but specially geared towards browser applications.
Before React I’d tried both Angular and Backbone. Neither felt good to me, so when React came out it was amazing. I quickly developed a whole slew of packages, but by not using JSX I soon suffered the wrecking ball of breaking changes. It became apparent to me that such is the fate of those who use frameworks.
It must’ve been late 2014 when I discovered virtual-dom, which stripped itself of all of Reacts baggage and exposed a straight forward API based on hyperscript. It was called virtual-hyperscript, and I was loving it.
Creating elements with Virtual-dom wasn’t always straight forward though, so Shama came up with base-element which was meant to ease widget development. I thought it was a great idea, but not quite functional enough, so I created vel as an alternative.
But people around me were still using JSX. They claimed it made their code readable. To me it mostly meant it would break my tools (fun 😰), but there was definitely something to be said for using something that looked like HTML.
There was domify that could create raw DOM nodes, and Azer had created virtual-html that would output DOM nodes without event hooks. But it wasn’t until Substack created hyperx that JSX was made truly redundant.
After Hyperx Shama created bel, on top of which Max created yo-yo. This wave of elements used raw DOM nodes instead of virtual nodes, as perf showed it was comparable in speed. By leveraging Raynos’ global, these nodes can be created both in Node and the browser. And through morphdom, updates are made efficient.
This means we’ve now reached a point where the lowest common denominator is the DOM, and elements can be ported from framework to framework without ever being locked in again! Choo is built on this principle. We’re done, framework portability in JS is solved (well, once this issue is fixed at least — hah)
It must’ve been about my second or third project in JS ever when I started using React. It was new, and Facebook had just started talking about Flux. I felt it made sense and gave their lib a shot. It turned out, however, that it wasn’t good at handling async at all. So in a couple of nights in 2014 I whipped out barracks, a flux-like architecture.
People seemed to quite enjoy using it. React news even reviewed it, saying:
“Barracks boasts a minimal API surface area, which is actually something to behold — there are only 3 functions exposed. But it seems like, in these 3 functions, you can actually get everything you need”
Late last year I started learning more about functional architectures, particularly Mercury and Redux. They felt like a good idea, and Seth Vincent seemed to agree. He created virtual-app, as a way of creating small funcional Virtual-dom apps — and I was loving it. Actually I was using it right up until Max released Yo-yo.
So Virtual-app wasn’t compatible with Yo-yo, and wiring it up always required a bit of boilerplate. So on a sweaty evening in Vietnam, right after having read about the new Elm architecture I softly mumbled: “fuck it” and started drafting out Choo.
And that’s pretty much how choo came to be. Two years of working on routers, using different (virtual) DOM frameworks and playing around with functional architectures.
This is definitely not the end though; not everything in the browser has been solved yet. Spec makers seem sold on async-promise-cancel-observable-await, but pull-stream has made a casual entry as best in class for composable async. People have also started using Webworkers for all computation, leaving the main process open to only handle UI diffing. Progressive web applications are becoming more of a thing, and the distributed web is slowly chugging along. Not to speak of mobile (native / non-native) and desktop platforms.
The future is interesting. This is how I got here; I’m curious to see where we’ll go next.