Logo

dev-resources.site

for different kinds of informations.

Web Components and SSR - 2024 Edition

Published at
11/19/2024
Categories
webcomponents
ssr
javascript
html
Author
stuffbreaker
Categories
4 categories in total
webcomponents
open
ssr
open
javascript
open
html
open
Author
12 person written this
stuffbreaker
open
Web Components and SSR - 2024 Edition

One of the biggest gripes I hear about web components is that they don't work with Server-Side Rendering. This is unfortunately a little misleading because it's only partially true. You see, there's server-side rendering and there's server-side rendering. It works in the former, but not the latter. Don't worry, I'll explain. 😉

Server-Side Rendering

There are really two kinds of server-side rendering that get conflated into the same concept. The first is server-side framework server-side rendering and client-side framework server-side rendering.

Server-Side Framework SSR

Server-side Framework SSR is when you use a framework that runs the HTML templating logic entirely on the server to compose the HTML that will be rendered in the browser. These are frameworks like Ruby on Rails, ASP.Net, PHP, or even Node.js frameworks that use templating languages like Pug or EJS.

Web components work great in this type of server-side rendering!

Client-Side Framework SSR

Client-side Framework SSR is when a frontend framework executes the client-side code on a Node.js server before sending it to the browser. This is done to reduce the amount of JavaScript that is shipped and executed in the browser.

There are some big advantages of doing this:

  • improve performance
  • better SEO
  • reduced dependency on JavaScript

The Problem

The problem is that this approach introduces some challenges for custom elements and other web APIs.

The first challenge is that when defining custom elements the API is window.customElements.define('my-element', MyElement). When you render client-side code on a Node.js server, guess what's missing - the window. Because of this, typical commands on the window object, and other APIs like localStorage and MutationObserver fail during SSRing.

The other challenge is that web components are interoperable, which means they can be used across frameworks like standard HTML elements, but client-side framework SSRing is not based on any standard. Each framework has its own bespoke method of executing its UI, so there is no clear approach for how and when to SSR custom elements. You need an implementation for each environment in which they are being used.

Current Solutions

You can do some things right now to use your web components with client-side framework SSRing.

Deferred Definition

The first thing you can do to get your components working right now is defer the component definition until the window object is present. Unfortunately, checking if the window exists before defining your components won't consistently work because the logic will be executed on the server and may not be run again when the code gets to the client. Most frameworks have a way to specify when code needs to be run on the "client only", so you will need to find out how to do that based on the framework you're using.

Declarative Shadow DOM (DSD)

A recent development has been the ability to define HTML templates in a shadow root declaratively. This has been dubbed declarative shadow DOM.

<my-button>
  <template shadowrootmode="open">
    <style>
      button {
        padding: 0.25rem;
        border: solid 1px black;
      }
    </style>
    <button>
      <slot></slot>
    </button>
  </template>
  My Button
</my-button>
Enter fullscreen mode Exit fullscreen mode

This provides some amazing capabilities and if you defer the component definition, they can be upgraded when the client is ready. The downside is that it doesn't scale very well for something like design systems with many components. You would need to do this for every custom element on the page.

<my-button>
  <template shadowrootmode="open">
    <style>
      button {
        padding: 0.25rem;
        border: solid 1px black;
      }
    </style>
    <button>
      <slot></slot>
    </button>
  </template>
  My Button 1
</my-button>

<my-button>
  <template shadowrootmode="open">
    <style>
      button {
        padding: 0.25rem;
        border: solid 1px black;
      }
    </style>
    <button>
      <slot></slot>
    </button>
  </template>
  My Button 2
</my-button>
Enter fullscreen mode Exit fullscreen mode

Teams are attempting to use this as a stop-gap for now (like @lit-labs/ssr). This often requires special code considerations like limitations on how and when you can use certain APIs, so I don't think this is an ideal solution.

WASM?

An interesting new solution from the Enhance team is that they are using WebAssembly to provide SSRing of custom elements. This is currently limited to their ecosystem, but there may be an opportunity to learn from this and try to create a more framework-agnostic approach in the future.

Future Solutions

There are some new proposals in the works that should provide a scalable solution to some of the pain points SSRing is trying to solve when it comes to web components.

Declarative Custom Elements (DCE)

Declarative Custom Elements (DCE) is a technology that may provide a more efficient approach to authoring web components. These are similar to custom elements using the Declarative Shadow DOM, but you only have to define them once and they can be used everywhere.

<template element="my-button">
  <style>
    button {
      padding: 0.25rem;
      border: solid 1px black;
    }
  </style>
  <button>
    <slot></slot>
  </button>
</template>

<my-button>My Button 1</my-button>
<my-button>My Button 2</my-button>
Enter fullscreen mode Exit fullscreen mode

This, in conjunction with HTML modules would provide a mechanism for custom elements that are both client-side framework SSR-friendly, reduce the dependency on JavaScript, and improve the performance of our custom elements that don't require any JavaScript. Also, like custom elements using the Declarative Shadow DOM, these custom elements can be upgraded once the client is available for more advanced user interactions.

Conclusion

If your application uses a server-side framework to render your UIs, you are safe to use web components. If you are using a client-side framework to render your UIs, there are some things you can do now to make your components work in those scenarios, but some new things are coming that should greatly improve the experience SSR for custom elements.

ssr Article's
30 articles in total
Favicon
Custom builder for Angular: My way
Favicon
Setting Up Dual Compilation (SSR + CSR) in ViteJS with vite-plugin-builder
Favicon
# Key New Features in React Router 7: Embracing the Remix Future
Favicon
Beginner SEO in React JS - React Helmet
Favicon
Setting up partial SSR for a React + TypeScript + webpack app from scratch
Favicon
Create an SSR Application with Vite, React, React Query and React Router
Favicon
Understanding Web Rendering: Performance Implications and Use Cases
Favicon
Make EditorJS work in Svelte(kit) SSR
Favicon
Client-side Rendering & Server-side Rendering
Favicon
A Practical Guide to CSR and SSR with React 19 and esbuild
Favicon
Fixing SSR Rendering Issues with Angular Resolver for Async Pipe Data
Favicon
Choosing Remix as a Server-Side Rendering (SSR) Framework
Favicon
Implementing Server-Side Rendering (SSR) with Next.js and Firebase for SEO-Friendly React Apps 🚀
Favicon
Do You Need to SSR Your Web Components?
Favicon
Web Components and SSR - 2024 Edition
Favicon
Dark side of Next.js - App Router
Favicon
How to achieve unified management of four types of global state data in Vue3?
Favicon
What do SSR, CSR, ISR and SSG mean? A complete guide for web developers
Favicon
Vue 3.5 “Tengen Toppa Gurren Lagann” Innovations: Advanced Features and Most Powerful Updates 🚀
Favicon
Inertiajs Server-side Rendering (SSR) For React (Vite Setup)
Favicon
Vaadin, the battery-included server-side AJAX framework
Favicon
How to add Supabase Auth to Astro
Favicon
Dive into Next.js Server-Side Rendering (SSR): From SPA to ISR
Favicon
Why do client components render as SSR in nextjs, marking components as "use client" still render its html as SSR why?
Favicon
Augmenting the client with Alpine.js
Favicon
Augmenting the client with Vue.js
Favicon
Server-Side Rendering (SSR): Uma Solução para SEO e Performance em Aplicações React
Favicon
SSR and CSR Explained
Favicon
A short history of AJAX and SSR
Favicon
How to Do Server-Side Rendering (SSR) in Next.js

Featured ones: