Server-side custom elements
You know how server-first frameworks like Enhance and Eleventy’s WebC let you “expand” custom elements right in the HTML that gets sent to the browser? These are great if you are building entire pages or websites.
Recently I came across linkedom
which, at first, looks like a lightweight alternative to jsdom
or a server emulation of DOMParser
. Something I quickly realized though, is that you can use it to expand individual custom elements on the server, without buying into a whole framework or templating engine.
Write your custom elements using the same familiar APIs:
import { parseHTML } from "https://esm.sh/linkedom";
const { customElements, HTMLElement, document } = parseHTML(`\
<my-thing></my-thing>
`);
customElements.define("my-thing", class extends HTMLElement {
connectedCallback() {
this.textContent = "hello world";
}
});
And then generate the final markup right away:
console.log(document.toString()); // <my-thing>hello world</my-thing>
This is already useful, but what I find even more interesting is that you can also write different logic for the same custom elements, depending on whether it executes on the server or the browser. The tag name serves as a shared interface for both the server and the client APIs to hook into. It’s like a weird DIY form of isomorphic JavaScript.
I made a playground you can poke around in if you’d like. Notice how I define the coun-ter
element twice:
- On the server, it simply expands the markup.
- On the client, it assumes the markup is already there and only adds interactivity.
Another cool lightweight library I found is html-tagged
which lets you do a similar thing without any boilerplate. And it even supports slots!
import { html } from "https://esm.sh/html-tagged";
import { renderToString } from "https://esm.sh/html-tagged/server";
const page = html`<my-thing>world</my-thing>`;
const elements = {
"my-thing": () => html`hello <slot></slot>`,
};
console.log(renderToString(page, { elements })); // "hello world"
There’s another one called ocean
from Matthew Phillips, who has been writing about web components for a long time. And another tiny one called ultrahtml
from Nate Moore (though be aware it sanitizes the markup by default).
I’m sure I could find a few more if I look around. These things are probably not that useful if you already have a component system going on in your server, but can be pretty handy for one-off situations.