Skip to main content

Command Palette

Search for a command to run...

πŸš€ The Future of Server-Rendered Web Components: Enhance vs. Lit vs. WebC 🌐

Which is Best for Server-Rendered Web Components: Enhance, Lit, or WebC?

Updated
β€’4 min read
πŸš€ The Future of Server-Rendered Web Components: Enhance vs. Lit vs. WebC 🌐

Web components have been around for a while, but server-side rendering (SSR) of custom elements has always been a tricky subject. With modern frameworks moving towards server-first architectures, the demand for HTML-first, SSR-friendly components has never been higher.

So today, let's break down three popular ways to server-render web components in Node.js using:

βœ” Enhance
βœ” Lit
βœ” WebC

We'll explore how they work, their differences, and which one is best suited for building scalable, high-performance applications.


πŸ’‘ The Big Question: Can You Server-Render Web Components?

Absolutely! Web components have always been renderable on the server. Even without JavaScript, you can output basic custom elements on any backend.

Here's a simple example of an SSR-friendly custom element:

<my-custom-element>
  <my-custom-header><h1>Welcome!</h1></my-custom-header>
  <my-custom-button variant="primary"><button>Click Me</button></my-custom-button>
</my-custom-element>

And the CSS:

my-custom-element {
  display: block;
  background: lightyellow;
  padding: 1rem;
}

my-custom-header {
  display: block;
  padding-bottom: 1rem;
  border-bottom: 1px solid rebeccapurple;
}

my-custom-button[variant="primary"] button {
  background: navy;
  color: white;
}

πŸ”₯ No JavaScript needed. The browser renders it just fine. But… is that enough?

In modern component-driven applications, we need:
βœ… Shadow DOM support
βœ… Declarative server rendering
βœ… Hydration for interactivity

This is where Enhance, Lit, and WebC come in!


⚑ Enhance: The Lightweight Server-First Framework

Enhance is a fullstack framework designed with SSR web components in mind. The best part? It’s a standalone library, meaning you can use it in any Node.js app.

πŸ›  Example Enhance Component

export default function MyElement({ html, state }) {
  const { attrs } = state;
  const { hello = "?", easy = [] } = attrs;

  return html`
    <style>
      :host {
        display: block;
        padding: 0.5rem 1rem;
        border: 3px double orange;
      }
    </style>

    <h2>Hello ${hello}!</h2>
    <p>Easy as ${easy.join(", ")}. <slot></slot></p>
  `;
}

And the server-side rendering code:

import MyElement from "./my-element.js";
import enhance from "@enhance/ssr";

const html = enhance({
  elements: { 'my-element': MyElement },
});

const data = { hello: "world", easy: [1, 2, 3] };

const result = html`
  <my-element hello=${data.hello} easy=${data.easy}>Hello from SSR!</my-element>
`;

console.log(result);

πŸš€ Why Use Enhance?

βœ… Simple & lightweight
βœ… No Shadow DOM by default (great for flexibility)
βœ… 0kb JavaScript philosophy

Enhance is great if you want pure SSR components with easy expansion. However, it lacks built-in isomorphic rendering (components running both on server and client).


πŸ”₯ Lit: The Isomorphic Powerhouse

Lit is a popular web component library that provides both client-side and server-side rendering. Unlike Enhance, Lit uses Shadow DOM by default and works well in isomorphic setups.

πŸ›  Example Lit Component

import { LitElement, html, css } from "lit";

export class MyElement extends LitElement {
  static styles = css`
    :host {
      display: block;
      padding: 0.5rem 1rem;
      border: 3px double orange;
    }
  `;

  static properties = {
    hello: {},
    easy: { type: Array },
  };

  constructor() {
    super();
    this.hello = "?";
    this.easy = [];
  }

  render() {
    return html`
      <h2>Hello ${this.hello}!</h2>
      <p>Easy as ${this.easy.join(", ")}. <slot></slot></p>
    `;
  }
}

customElements.define("my-element", MyElement);

πŸ”„ How to Server-Render Lit Components

import { render } from "@lit-labs/ssr";
import { collectResult } from "@lit-labs/ssr/lib/render-result.js";
import { html } from "lit";
import { MyElement } from "./my-element.js";

const result = await collectResult(render(html`
  <my-element hello="world" easy=${[1, 2, 3]}>Hello from SSR!</my-element>
`));

console.log(result);

πŸš€ Why Use Lit?

βœ… Shadow DOM for encapsulation
βœ… Great for isomorphic apps (client & server run the same code)
βœ… Backed by Google & has a strong ecosystem

However, Lit’s SSR mechanism is still evolving, and using it requires some workarounds.


🌟 WebC: The Future of HTML-First SSR

WebC (Web Components Compiler) is a unique, HTML-based approach to writing server-rendered web components. It was created by Eleventy’s team and is quickly gaining traction.

πŸ›  Example WebC Component

<script webc:setup>
  const join = (input) => input.join(", ");
</script>

<style webc:scoped="my-element">
  :host {
    display: block;
    padding: 0.5rem 1rem;
    border: 3px double orange;
  }
</style>

<h2>Hello <span @text="hello"></span>!</h2>
<p>Easy as <span @text="join(easy)">...</span>. <slot></slot></p>

πŸ–₯ How to Server-Render WebC Components

import { WebC } from "@11ty/webc";

const page = new WebC();

page.defineComponents("./components/*.webc");
page.setInputPath("./page.webc");
page.setBundlerMode(true);

const { html } = await page.compile({
  data: { hello: "world", easy: [1, 2, 3] },
});

console.log(html);

πŸš€ Why Use WebC?

βœ… True HTML-first approach
βœ… No JavaScript required for basic components
βœ… Built for SSR-first workflows

WebC is perfect for Eleventy and other SSR-friendly environments, but it lacks built-in client-side hydration.


πŸ† Which One Should You Use?

FeatureEnhanceLitWebC
Shadow DOM❌ Noβœ… Yes⚠ Optional
SSR Supportβœ… Yesβœ… Yesβœ… Yes
Client Hydrationβœ… Yesβœ… Yes⚠ Limited
HTML-Firstβœ… Yes❌ Noβœ… Yes

My Pick? If you love HTML-first development, WebC is the future. However, if you need isomorphic components, Lit might be a better fit. And for pure SSR setups, Enhance is a solid choice!

What do you think? Would you switch to SSR web components? Let me know in the comments! πŸ’¬πŸš€


Hope you like this breakdown! Stay tuned for more web dev insights. πŸš€βœ¨