My year on the frontend, 2020 edition
Tags: frontend, react, elm, svelte
Published: 2020-12-28 13:27:04

My, oh my, what a year. Lockdown or no lockdown, the terminal blinked and the projects came and went, clocking in at the following stats for the year:
- ongoing maintenance of 5 reasonably complicated apps ranging between 15k and 75k lines. Hi there, [NLX Studio](https://nlx.ai/studio)!
- 4 marketing sites, with the lovely [voicecompass.ai](https://voicecompass.ai/) coming in last.
- one reasonably complicated backend.
- one Figma plugin (fun!!).
- around 15 or so quick interactive prototypes for clients.
- one 3d app plus a [3d pet project](https://splytlight.surge.sh/).
- 4 app frameworks: React, Elm, Svelte and Vue.
- 4 styling solutions: ✨Tailwind✨, vanilla CSS4, [CSS in JS](https://emotion.sh), [elm-ui](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/).

Never would I have imagined there would be so much going on, and it seems next to impossible to sort out a coherent story. Nonetheless, here is a catalog of thoughts:

## Elm is wonderful. Elm purism isn't.

Elm is an absolute delight of a language, bringing a strict yet friendly Haskell-like environment to the frontend. The main selling points are a bulletproof type system including type-safe IO, delightful error messages, a spotlessly designed ecosystem, and strong guarantees across the board.

I got invested in Elm way before TypeScript got decent (> v2.6) or React came out with hooks, and for the longest time I thought the best thing was to write as much in Elm as possible:
- actor model for ports that are almost always used in a request-response style? Bring it!
- sub-views with laborious wiring? No problem, I just use some Vim macros.
- no FFI, no local state, no effect modules? Thanks for looking out for me!

Yet today, my idealism is crumbling. I am maintaining a 75k line Elm app with some [straaange stuff in it](https://github.com/peterszerzo/elm-porter) just to keep it sane. Because of the boilerplate, I still find places where subscriptions aren't wired up at the detriment of UX, or even worse, conflict with each other. I re-wrote the dropdown and the list editor about 5 times each, still not happy with either of them.

Time for a change: my next year in Elm will be one that embraces custom elements *a whole lot more*, limiting Elm to handle sensitive logic, the simpler chunks of UI, and the crucially valuable JSON encoding/decoding. I will no longer write up [clickaway handlers](https://dev.to/margaretkrutikova/elm-dom-node-decoder-to-detect-click-outside-3ioh) or set up dictionaries of dropdown UI states in Elm.

Why? I lost faith that this kind of Elm purism will get me to a level of UI quality I can defend in front of project owners. React makes a painlessly reusable [generic drag-and-drop list manager](https://dev.to/peterszerzo/generics-for-user-interfaces-hak) in a few dozen lines. Elm never will.

The narratives of the Elm community continue to confuse me. What in the world did the 'no components' campaign even mean? Do we still advise against nesting model-view-update triplets in favor of the [elm-sortable-table pattern](https://github.com/evancz/elm-sortable-table), even though [drag and drop](https://package.elm-lang.org/packages/annaghi/dnd-list/latest/) can't be set up in the latter? Are the guarantees really that strong if people can just pass in proxies and use custom elements as they please?

Elm is definitely here to stay for me. However, I am hoping that a more critical and pragmatic approach to it will help me stay happy in the ecosystem.

## React hooks are fantastic

Here's a pattern I have no complaints about: good old React hooks (GORH or something?). I wrote a number of custom hooks this year including one that [fully manages a chat experience](https://www.npmjs.com/package/@nlxchat/react), and I simply can't think of a better way to package and share effectful, headless UI logic.

My time spent in Elm continues to influence me in the way I write React:
- I strive for a limited and (allegedly) thoughtful use of local state.
- no matter how good TypeScript is getting, I really miss type-safe IO the way Elm does it. I hope to use [io-ts](https://dev.to/peterszerzo/safe-functional-io-in-typescript-an-introduction-1kmi) in production someday.
- I never got interested in projects like [immer](https://github.com/immerjs/immer) and [MobX](https://github.com/mobxjs/mobx) have declined even further, in favor of what I could only call 'vanilla React'. Explicitly immutable code is alright.
- this is not to say I have a beef with libraries now: I actually grew really fond of [Formik](https://formik.org/). It does some very thoughtful, semantically sound heavy lifting on forms.

## What about Svelte and Vue?

While I kept working on fancy(-looking) architectures in Elm and React, I also built a ton of smaller Svelte and Vue projects this year - all with satisfied owners and mostly happy users. Which got me wondering: just how much better are sites made the 'rigorous way'?

Rich Harris makes the argument that terse code is good on account of research that shows (paraphrasing here):

> The `bugs/lines of code` ratio of software projects is more or less constant.

This is something I didn't think I would pay any attention to, but then here I am, staring at it with curious eyes.

Truth is, Svelte is just very promising right now. I can implement features in no time, the HTML templates are - regardless of how long they it takes me to warm up to them - amazing for dev speed. Best of all, the API is impressively comprehensive (springs even!!) and yet with such a tiny and well-designed total surface.

I will probably keep shying away from writing anything very complicated in it and go by the thinking of [this excellent blog post](https://www.swyx.io/svelte-sites-react-apps/). Additionally, Svelte gets bonus points for powering pretty much all my [creative programming](http://sketches.peterszerzo.com) these days.

As for Vue, which I never really liked for reasons that are outside the scope of this post to explain, things might be turning around. With the community slowly upgrading to Vue 3 (including a faithful port of React hooks and proper TypeScript support), I might just wind up writing more of it myself. Let's see, let's see.

## The hype I still don't buy

This year I fully stopped listening to people preaching vanilla JavaScript or out on a bundle-shaming crusade. I refuse to apologize for shipping 100 kilobytes of `react-dom` if it means I get to avoid hacking a static site with `document.querySelector` (I happen to have a site that does that and it literally keeps me up at night).

I am happy to talk about bundle sizes, loading times and the challenges of SSR-hydration as UX issues, as long as we keep in mind that the worst UX issue is and forever will be [drumrolls] [drumrolls] a runtime error. You know, the one caused by a haphazard architecture.

I should mention that more formalized alternatives like [Alpine.js](https://github.com/alpinejs/alpine/) or [Hotwire](https://hotwire.dev/) do look very promising, hopefully I will get the chance to engage with them in production soon.

## Onwards to 2021

I really look forward to this next year. I wonder if I will stay a Vim user in twelve months, what my next terminal color scheme will be, whether there is going to be another super cool 3d project in store for me, and how much of the thoughts and rambles above will still hold. Look forward to writing it all up again in one year's time.

🍾Happy New Year🍾 everybody!