dxchester
Joined 14 years ago
Joined 14 years ago
They do a lot, but stop just short of being useful without something of a framework on top. I tried hard to use them directly, but found that it was untenable without sensible template interpolation, and without helpers for event binding.
Here's my shot at the smallest possible "framework" atop Web Components that make them workable (and even enjoyable) as an application developer:
https://github.com/dchester/yhtml
It's just ~10 SLOC, admittedly dense, but which make a world of difference in terms of usability. With that in place, now you can write markup in a style not too dissimilar from React or Vue, like...
<button @click="increment">${this.count}</button>
Whereas without, you need to bind your own events and manage your own template interpolation with sanitizing, handling conditionals, loops, and all the rest.If we could get something in this direction adopted into the spec, it would open up a lot of use cases for Web Components that it just can't address as-is.
Reactivity, composability, templates, etc with no dependencies, in ~150 SLOC.
With the WebComponents movement though, we are getting ever closer to being able to rely on native browser functionality for a good share of what frameworks set out to do. We're not all the way to bliss without frameworks, but for what it's worth here is my 481-byte library to support template interpolation with event binding in order to make WebComponents pretty workable mostly as-is: https://github.com/dchester/yhtml
Instead of taking the path of starting with DOM manipulation and then going to a framework as necessary, I've kept really trying to make raw web components work, but kept finding that I wanted just a little bit more.
I managed to get the more I wanted -- sensible template interpolation with event binding -- boiled down to a tag function in 481 bytes / 12 lines of (dense) source code, which I feel like is small enough that you can copy/paste it around and not feel to bad about it. It's here if anyone cares to look: https://github.com/dchester/yhtml
Our answer was to reimplement the Automerge API with different mechanics underneath that allows for a "snapshots + recent changes" paradigm, instead of "the doc is the sum of all changes". That way performance doesn't have to degrade over time as changes accumulate.
Project is here: https://github.com/frameable/pigeon, with some benchmarks: https://github.com/frameable/pigeon/wiki/Benchmarks in the wiki...
The answer is to do it all in strategic moderation: Use a subset of tailwind just for spacing and layout and revel in simple things being simple. Use modular CSS for UI patterns and revel in the readability of your HTML and visual consistency of your UI. And then use custom scoped CSS where required, and revel in interesting things being only as hard as need be, without ruining everything else along the way.
[0]: https://frameable.com/company/tech/how-we-found-sanity-in-a-...
I like the effort, but this is basically admitting defeat. Just naively using template strings and re-rendering the whole app on every change of state _is_ too slow, and so the author falls back instead to rendering via a series of bespoke methods that mix logic and template strings and DOM methods all interspersed. It still has all the shortcomings of 00's-era PHP, or piles of jQuery.
It is possible to do one step better than this still with vanilla js, if you use Web Components / custom elements. That way you can have each type of custom element (todo-app, todo-list, todo-item, etc) have its own render function using template strings, and you can still sneak in custom optimizations (like direct DOM insertion when adding and item to a long list instead of re-rendering).
But in the end, it's just so wonderful to be able to have reactive state and efficiently render your app from the state, and forget about all the rest.
We developed El.js[1] with all of this in mind, to be as little as possible on top of vanilla js and web components, to get the reactivity and efficient rendering.
https://github.com/frameable/el
It's just ~150 lines / 2kb, and leverages existing browser functionality to accomplish most of the hard parts. Has observability, reactive templates, scoped CSS, no need for a build process, etc.
There's a starter repo here if you want to try it out: https://github.com/frameable/el-starter
WebComponents give us so much, but just not quite enough to be usable on their own without a little bit more on top. Reactivity with observable store and templating with event binding are the big missing pieces.
[0]: https://github.com/frameable/el