Von Framework-Komponenten zu Web Components – warum plattformnahe UI-Bausteine die bessere Investition sind
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-Typ | Existiert in | Nutzbar in |
|---|---|---|
| React | React-Projekten | React-Projekten |
| Vue | Vue-Projekten | Vue-Projekten |
| Svelte | Svelte-Projekten | Svelte-Projekten |
| Astro | Astro-Projekten | Astro-Projekten |
| Web Components | Browser | Ü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:
| Callback | Wann | Typischer Use Case |
|---|---|---|
constructor() | Element wird erstellt | Shadow DOM initialisieren |
connectedCallback() | Element wird ins DOM eingefügt | Rendern, Event-Listener registrieren |
disconnectedCallback() | Element wird aus DOM entfernt | Cleanup, Ressourcen freigeben |
attributeChangedCallback() | Attribut ändert sich | Re-Render auslösen |
Browser-Support 2025
Web Components sind kein Experiment mehr. Alle modernen Browser unterstützen sie vollständig:
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| 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:
- Marketing-Website: Astro (statisch, SEO-optimiert)
- Web-App: React (interaktiv, State-heavy)
- Partner-Integration: WordPress-Plugin
- 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:
- Web Components gehören der Plattform – nicht einem Framework
- Browser-Support ist exzellent – über 95% Abdeckung
- Kein Build-Step nötig – direktes Laden im Browser möglich
- Perfekt mit Astro kombinierbar – Astro für Seiten, Web Components für Bausteine
- 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
- MDN: Web Components – Offizielle Dokumentation
- webcomponents.org – Community und Komponenten-Verzeichnis
- Custom Elements Everywhere – Framework-Kompatibilitätstests
- Lit – Library für einfachere Web Components
- Open Web Components – Empfehlungen und Tools