Web Componentsは、ブラウザ標準として規格化された「フレームワーク非依存の再利用可能なUI部品」を作るための技術仕様です。React・Vue・Svelteなどどのフレームワーク上でも動作し、長期保守が必要なデザインシステムやマイクロフロントエンドで威力を発揮します。本記事では、Web Componentsの基本を整理します。
Web Componentsの3本柱
- Custom Elements:独自のHTML要素を定義する仕組み
- Shadow DOM:スタイルとDOMを外部から隔離するカプセル化
- HTML Templates:
<template><slot>によるテンプレート化
最小コードで体験する
class MyBadge extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
span { padding: 4px 10px; background:#2563eb; color:#fff; border-radius:6px; }
</style>
<span><slot>label</slot></span>
`;
}
}
customElements.define('my-badge', MyBadge);
<my-badge>NEW</my-badge>
属性・プロパティ・イベント
observedAttributesとattributeChangedCallbackで属性変更を検知できます。イベントはネイティブのCustomEventを使い、ReactでもVueでも同じように購読できます。
class Counter extends HTMLElement {
static get observedAttributes() { return ['count']; }
attributeChangedCallback(name, oldVal, newVal) { this.render(); }
render() { this.textContent = `count: ${this.getAttribute('count') ?? 0}`; }
connectedCallback() {
this.render();
this.addEventListener('click', () => this.dispatchEvent(new CustomEvent('inc')));
}
}
customElements.define('my-counter', Counter);
フレームワークとの組み合わせ
- React:標準的なHTMLタグとして利用可能。プロパティ受け渡しはref経由が安全
- Vue:
compilerOptions.isCustomElementで許可するだけ - Svelte:そのまま使える。逆にSvelteコンポーネントをWeb Componentsとしてエクスポートも可能
メリットと注意点
- 長期保守に強い(フレームワーク刷新の影響を受けない)
- Shadow DOMでスタイルが他に漏れない/侵食されない
- SSR対応は実装が必要(Declarative Shadow DOMで改善中)
- FormAssociated未対応のライブラリでフォーム連携にひと工夫いる
ライブラリ選択
素のWeb ComponentsはAPIが冗長になりがち。実務ではLit(Google製・軽量)やStencil(Ionic製・型サポート充実)を使うのが定番です。
まとめ
Web Componentsは、特定のフレームワークに縛られない「長く使えるUI部品」を作るための標準技術です。デザインシステムやマイクロフロントエンドでの採用が進んでおり、知っておくと選択肢が広がります。Litで小さなコンポーネントを1つ作るところから始めてみましょう。