Zum Inhalt springen
CASOON

Web Components verstehen: Die Komponenten-Landschaft 2025

Von Framework-Komponenten zu Web Components – warum plattformnahe UI-Bausteine die bessere Investition sind

12 Minuten
Web Components verstehen: Die Komponenten-Landschaft 2025
#Web Components #JavaScript #Custom Elements #Shadow DOM
SerieWeb Components
Teil 1 von 4

Die Frontend-Welt ist voller Komponenten. React-Komponenten, Vue-Komponenten, Svelte-Komponenten, Astro-Komponenten. Jedes Framework hat seine eigene Art, UI-Bausteine zu definieren. Doch was passiert, wenn das Projekt wächst, ein zweiter Tech-Stack hinzukommt oder der Kunde das Widget in WordPress einbetten will?

Dann beginnt die Portierungs-Odyssee. Oder man entdeckt Web Components – die einzige Komponenten-Technologie, die zur Plattform selbst gehört.

Dieser Artikel ordnet die Komponenten-Landschaft ein, erklärt was Web Components sind und zeigt, warum sie 2025 relevanter sind denn je.

Die Komponenten-Landschaft heute

Framework-Komponenten: Mächtig, aber gebunden

React-Komponenten sind wahrscheinlich die bekanntesten. Sie nutzen JSX, haben eigene State-Management-Patterns und ein riesiges Ökosystem:

// React-Komponente
function ProductCard({ name, price }) {
  const [inCart, setInCart] = useState(false);
  
  return (
    <article className="product-card">
      <h3>{name}</h3>
      <p>{price} €</p>
      <button onClick={() => setInCart(true)}>
        {inCart ? 'Im Warenkorb' : 'Hinzufügen'}
      </button>
    </article>
  );
}

Vue-Komponenten folgen einem ähnlichen Muster mit Single File Components:

<!-- Vue-Komponente -->
<template>
  <article class="product-card">
    <h3>{{ name }}</h3>
    <p>{{ price }} €</p>
    <button @click="inCart = true">
      {{ inCart ? 'Im Warenkorb' : 'Hinzufügen' }}
    </button>
  </article>
</template>

<script setup>
import { ref } from 'vue';
defineProps(['name', 'price']);
const inCart = ref(false);
</script>

Das Problem: Diese Komponenten existieren nur innerhalb ihres Frameworks. Eine React-Komponente funktioniert nicht in Vue. Eine Vue-Komponente funktioniert nicht in Angular. Sie sind Framework-locked.

Astro-Komponenten: Perfekt für Seiten, aber…

Astro-Komponenten sind besonders interessant, weil sie einen anderen Ansatz verfolgen:

---
// Astro-Komponente
const { name, price } = Astro.props;
---

<article class="product-card">
  <h3>{name}</h3>
  <p>{price} €</p>
  <button>Hinzufügen</button>
</article>

<style>
  .product-card {
    padding: 1rem;
    border: 1px solid #e2e8f0;
  }
</style>

Astro-Komponenten werden zur Build-Zeit zu HTML kompiliert. Kein JavaScript im Browser, maximale Performance, perfekt für statische Inhalte.

Der Haken: Sie existieren nur im Astro-Kontext. Man kann sie nicht in ein React-Projekt importieren oder in ein CMS einbetten. Sie gehören dem Projekt, nicht der Plattform.

Die zentrale Frage: Wem gehört die Komponente?

Komponenten-TypExistiert inNutzbar in
ReactReact-ProjektenReact-Projekten
VueVue-ProjektenVue-Projekten
SvelteSvelte-ProjektenSvelte-Projekten
AstroAstro-ProjektenAstro-Projekten
Web ComponentsBrowserÜberall

Web Components gehören der Plattform. Sie sind echte HTML-Elemente, die in jedem Kontext funktionieren – ob React, Vue, Angular, Astro, WordPress oder statisches HTML.

Was sind Web Components?

Web Components sind ein Sammelbegriff für vier Browser-APIs, die zusammen wiederverwendbare Custom Elements ermöglichen:

1. Custom Elements

Die Kern-API: Eigene HTML-Elemente registrieren.

class ProductCard extends HTMLElement {
  connectedCallback() {
    const name = this.getAttribute('name');
    const price = this.getAttribute('price');
    
    this.innerHTML = `
      <article>
        <h3>${name}</h3>
        <p>${price} €</p>
        <button>Hinzufügen</button>
      </article>
    `;
  }
}

customElements.define('product-card', ProductCard);

Danach ist <product-card> ein echtes HTML-Element:

<product-card name="Widget Pro" price="49.99"></product-card>

Wichtig: Der Elementname muss einen Bindestrich enthalten, um Konflikte mit nativen HTML-Elementen zu vermeiden.

2. Shadow DOM

Stil-Isolation für Komponenten. Das CSS innerhalb des Shadow DOM beeinflusst nicht den Rest der Seite:

class ProductCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }
  
  connectedCallback() {
    const name = this.getAttribute('name');
    const price = this.getAttribute('price');
    
    this.shadowRoot.innerHTML = `
      <style>
        article {
          padding: 1rem;
          border: 1px solid #e2e8f0;
          border-radius: 8px;
        }
        h3 { margin: 0 0 0.5rem; }
        button {
          background: #3182ce;
          color: white;
          border: none;
          padding: 0.5rem 1rem;
          cursor: pointer;
        }
      </style>
      <article>
        <h3>${name}</h3>
        <p>${price} €</p>
        <button>Hinzufügen</button>
      </article>
    `;
  }
}

Vorteil: Die Styles der Komponente sind gekapselt. Externe CSS-Regeln wie h3 { color: red; } haben keinen Einfluss auf die Komponente.

3. HTML Templates

Wiederverwendbare HTML-Strukturen, die erst bei Bedarf geklont werden:

<template id="product-card-template">
  <style>
    /* Styles hier */
  </style>
  <article>
    <h3><slot name="title">Produkt</slot></h3>
    <p><slot name="price">0,00 €</slot></p>
    <button>Hinzufügen</button>
  </article>
</template>
class ProductCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    
    const template = document.getElementById('product-card-template');
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
}

4. Slots

Content-Projektion – externe Inhalte in die Komponente einschleusen:

<product-card>
  <span slot="title">Widget Pro</span>
  <span slot="price">49,99 €</span>
</product-card>

Slots ermöglichen flexible Komponenten, bei denen der Inhalt von außen kommt, aber das Layout von der Komponente definiert wird.

Lifecycle einer Web Component

Web Components haben definierte Lifecycle-Callbacks:

class ProductCard extends HTMLElement {
  // Wird aufgerufen, wenn das Element erstellt wird
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }
  
  // Wird aufgerufen, wenn das Element ins DOM eingefügt wird
  connectedCallback() {
    this.render();
  }
  
  // Wird aufgerufen, wenn das Element aus dem DOM entfernt wird
  disconnectedCallback() {
    // Cleanup: Event-Listener entfernen, etc.
  }
  
  // Definiert, welche Attribute beobachtet werden sollen
  static get observedAttributes() {
    return ['name', 'price'];
  }
  
  // Wird aufgerufen, wenn ein beobachtetes Attribut sich ändert
  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue !== newValue) {
      this.render();
    }
  }
  
  render() {
    const name = this.getAttribute('name') || 'Produkt';
    const price = this.getAttribute('price') || '0.00';
    
    this.shadowRoot.innerHTML = `
      <style>/* ... */</style>
      <article>
        <h3>${name}</h3>
        <p>${price} €</p>
        <button>Hinzufügen</button>
      </article>
    `;
  }
}

customElements.define('product-card', ProductCard);

Der Lifecycle im Überblick:

CallbackWannTypischer Use Case
constructor()Element wird erstelltShadow DOM initialisieren
connectedCallback()Element wird ins DOM eingefügtRendern, Event-Listener registrieren
disconnectedCallback()Element wird aus DOM entferntCleanup, Ressourcen freigeben
attributeChangedCallback()Attribut ändert sichRe-Render auslösen

Browser-Support 2025

Web Components sind kein Experiment mehr. Alle modernen Browser unterstützen sie vollständig:

FeatureChromeFirefoxSafariEdge
Custom Elements✅ 67+✅ 63+✅ 10.1+✅ 79+
Shadow DOM✅ 53+✅ 63+✅ 10+✅ 79+
HTML Templates✅ 26+✅ 22+✅ 8+✅ 13+
Slots✅ 53+✅ 63+✅ 10+✅ 79+

Globale Unterstützung: > 95% der Browser weltweit. Für Legacy-Browser (IE11) gibt es Polyfills, aber 2025 ist das in den meisten Projekten kein Thema mehr.

Warum Web Components jetzt?

1. Lebensdauer und Investitionsschutz

Framework-Zyklen sind kurz. React Hooks ersetzten Class Components. Vue 2 wurde durch Vue 3 abgelöst. Angular hat mehrere Breaking Changes hinter sich.

Web Components basieren auf Web-Standards. Diese ändern sich langsam und abwärtskompatibel. Eine Web Component von 2018 funktioniert heute noch genauso.

Die Frage ist nicht: “Was ist heute am bequemsten?”

Sondern: “Was möchte ich in 3-5 Jahren noch nutzen können?“

2. Framework-Unabhängigkeit

Ein praktisches Szenario:

  1. Marketing-Website: Astro (statisch, SEO-optimiert)
  2. Web-App: React (interaktiv, State-heavy)
  3. Partner-Integration: WordPress-Plugin
  4. Mobile-App: React Native Web

Mit Framework-Komponenten: Jede Plattform braucht eigene Implementierung.

Mit Web Components: Einmal gebaut, überall nutzbar.

<!-- In Astro -->
<product-card name="Widget" price="49.99"></product-card>

<!-- In React -->
<product-card name="Widget" price="49.99"></product-card>

<!-- In WordPress -->
<product-card name="Widget" price="49.99"></product-card>

<!-- In statischem HTML -->
<product-card name="Widget" price="49.99"></product-card>

3. Kein Build-Step nötig

Eine Web Component ist Vanilla JavaScript. Man kann sie direkt in den Browser laden:

<script src="product-card.js"></script>
<product-card name="Widget" price="49.99"></product-card>

Kein Webpack, kein Vite, kein npm install. Das macht Web Components ideal für:

  • Widgets zum Einbetten (Analytics-Dashboards, Chat-Widgets)
  • Design-Systeme (Button, Card, Modal)
  • Micro-Frontends (unabhängige Team-Deployments)

4. Interoperabilität

Web Components arbeiten mit jeder Technologie zusammen:

---
// In Astro: Daten serverseitig laden
const products = await fetchProducts();
---

<!-- Web Components mit Astro-Daten -->
{products.map(product => (
  <product-card 
    name={product.name} 
    price={product.price}>
  </product-card>
))}
// In React: Web Component als JSX-Element
function ProductList({ products }) {
  return products.map(product => (
    <product-card
      key={product.id}
      name={product.name}
      price={product.price}
    />
  ));
}

Wann Framework-Komponenten, wann Web Components?

Die Entscheidung ist nicht entweder/oder. Beide haben ihren Platz.

Framework-Komponenten sind besser für:

Projekt-interne UI

  • Layouts, die nur in diesem Projekt existieren
  • Seitenkomposition (Header, Footer, Grid)
  • Content-Blöcke ohne Wiederverwendung

Komplexe State-Logik

  • Formulare mit verschachtelter Validierung
  • Real-Time-Updates mit vielen Abhängigkeiten
  • State, der über viele Komponenten geteilt wird

Team-Expertise

  • Das Team kennt React/Vue bereits sehr gut
  • Kein Bedarf an externem Teilen

Web Components sind besser für:

Wiederverwendbare UI-Bausteine

  • Buttons, Cards, Modals, Tabs
  • Design-System-Elemente
  • Widgets für externe Einbettung

Cross-Framework-Nutzung

  • Component Library für mehrere Projekte
  • Micro-Frontend-Architekturen
  • Partner-Integrationen

Langfristige Investitionen

  • Komponenten, die 5+ Jahre halten sollen
  • Unabhängigkeit von Framework-Zyklen
  • Vermeidung von Vendor-Lock-in

Web Components und Astro: Perfekte Partner

Astro ist der ideale Host für Web Components. Warum?

Astro übernimmt:

  • Routing und Seiten
  • SEO und Meta-Tags
  • Content Management
  • Build und Deployment

Web Components übernehmen:

  • Interaktive UI-Bausteine
  • Gekapselte Logik
  • Framework-unabhängige Widgets
---
// src/pages/products.astro
import '../components/wc/product-card.js';
const products = await getProducts();
---

<Layout title="Produkte">
  <h1>Unsere Produkte</h1>
  
  <div class="product-grid">
    {products.map(product => (
      <product-card
        name={product.name}
        price={product.price}
        image={product.image}>
      </product-card>
    ))}
  </div>
</Layout>

Astro rendert die Seite – mit SEO, Performance und allem drum und dran. Web Components bringen Interaktivität – ohne Framework-Overhead.

Zusammenfassung

Die Komponenten-Landschaft 2025 ist vielfältig. Framework-Komponenten haben ihren Platz für projekt-interne UI und komplexe State-Logik. Aber für wiederverwendbare, langlebige UI-Bausteine sind Web Components die bessere Wahl.

Die wichtigsten Punkte:

  1. Web Components gehören der Plattform – nicht einem Framework
  2. Browser-Support ist exzellent – über 95% Abdeckung
  3. Kein Build-Step nötig – direktes Laden im Browser möglich
  4. Perfekt mit Astro kombinierbar – Astro für Seiten, Web Components für Bausteine
  5. Langfristige Investition – Web-Standards ändern sich langsam und abwärtskompatibel

Im nächsten Teil bauen wir Web Components praktisch: Mit Astro, einem konkreten Use Case und einem GitHub-Repository zum Mitmachen.

Weiterführende Ressourcen