はじめに
この記事は「2025年にQiitaで流行した技術スタック30選アドベントカレンダー」の一環として、Web Componentsについて解説します。2025年は、Web Componentsがついに主流の開発手法として認知された年となりました。長年の課題だったブラウザサポートやツールの成熟度が大幅に改善され、多くの開発者がこの技術に注目するようになっています。
Web Componentsとは
Web Componentsは、再利用可能でカプセル化されたカスタムHTML要素を作成するための、ブラウザネイティブなAPI群です。主に以下の3つの技術で構成されています。
1. Custom Elements
独自のHTMLタグを定義できる機能です。
class HelloWorld extends HTMLElement {
connectedCallback() {
this.innerHTML = `<p>Hello, <strong>world</strong>!</p>`;
}
}
customElements.define('hello-world', HelloWorld);
<!-- 使用例 -->
<hello-world></hello-world>
2. Shadow DOM
スタイルとマークアップをカプセル化し、外部からの干渉を防ぎます。
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
p { color: blue; }
</style>
<p>この青色は外部には影響しません</p>
`;
}
}
customElements.define('my-component', MyComponent);
3. HTML Templates
再利用可能なマークアップの雛形を定義します。
<template id="my-template">
<style>
.card { border: 1px solid #ccc; }
</style>
<div class="card">
<slot></slot>
</div>
</template>
2025年のWeb Components事情
完全なブラウザサポートの実現
2025年、すべての主要ブラウザ(Chrome、Firefox、Safari、Edge)がWeb Components標準を完全にサポートするようになりました。ポリフィルなしで、開発者は安心してWeb Componentsを本番環境で利用できるようになっています。これは、長年のブラウザベンダー間の調整が実を結んだ結果です。
Declarative Shadow DOMの標準化
2025年における最も重要な進化の一つが、Declarative Shadow DOMの普及です。これにより、JavaScriptを使わずにHTMLだけでShadow DOMを定義できるようになりました。
<my-card>
<template shadowrootmode="open">
<style>
.card-container {
border: 1px solid #ccc;
border-radius: 8px;
padding: 16px;
}
</style>
<div class="card-container">
<slot></slot>
</div>
</template>
<h2>カードタイトル</h2>
<p>カードの内容がここに入ります</p>
</my-card>
この技術により、以下のメリットが得られます:
- サーバーサイドレンダリング(SSR)対応: JavaScriptの実行前にコンテンツが表示可能
- SEO改善: 検索エンジンがShadow DOM内のコンテンツをインデックス可能
- 初期表示の高速化: Flash of Unstyled Content (FOUC) の軽減
アクセシビリティの向上
2025年12月、Chrome CanaryでReference Target for Cross-root ARIAのPhase 1が利用可能になりました。これは、Shadow DOM内の要素を外部から参照できる新機能です。
<div>
<label for="checkbox">チェックボックス</label>
<fancy-checkbox id="checkbox">
<template shadowrootmode="open" shadowRootReferenceTarget="inner-checkbox">
<input type="checkbox" id="inner-checkbox">
</template>
</fancy-checkbox>
</div>
この機能により、Web Componentsを使ったアクセシブルなUIコンポーネントの開発が容易になります。Interop 2026の提案項目にも含まれており、今後すべての主要ブラウザでサポートされる見込みです。
なぜ今、Web Componentsなのか
フレームワーク非依存性
React、Vue、Angularなどのフレームワークは強力ですが、以下の課題があります:
- 頻繁な破壊的変更
- 急な学習曲線
- 重い依存関係
- フレームワーク間の非互換性
Web Componentsは、これらの問題を解決します。一度作成したコンポーネントは、どのフレームワークでも、あるいはフレームワークなしでも動作します。
将来性の保証
JavaScriptフレームワークの栄枯盛衰は激しく、5年後にどのフレームワークが主流かを予測することは困難です。しかし、Web Componentsはブラウザの標準仕様として、長期的なサポートが保証されています。
パフォーマンス
Web Componentsは以下の点でパフォーマンスに優れています:
- バーチャルDOMの差分計算が不要
- ブラウザネイティブのAPIを直接使用
- 大きな依存関係のバンドルが不要
- 効率的なレンダリング
実践的な開発ツール
Lit - 最も人気のあるWeb Componentsライブラリ
LitはGoogleが提供する、軽量で高速なWeb Componentsライブラリです。2025年も引き続き人気を博しています。
import { LitElement, html, css } from 'lit';
class MyButton extends LitElement {
static styles = css`
button {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
`;
static properties = {
label: { type: String }
};
render() {
return html`
<button @click=${this._handleClick}>
${this.label}
</button>
`;
}
_handleClick() {
this.dispatchEvent(new CustomEvent('my-click', {
bubbles: true,
composed: true
}));
}
}
customElements.define('my-button', MyButton);
Shoelace - プロフェッショナルなUIコンポーネント集
Shoelace(現在はWeb Awesomeとしてバージョン3を開発中)は、すぐに使えるプロフェッショナルなUIコンポーネントライブラリです。
<!-- CDNから簡単に利用可能 -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/light.css" />
<script type="module"
src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/shoelace-autoloader.js">
</script>
<!-- 使用例 -->
<sl-button variant="primary">ボタン</sl-button>
<sl-dialog label="ダイアログ">
ダイアログの内容
</sl-dialog>
<sl-dropdown>
<sl-button slot="trigger">メニュー</sl-button>
<sl-menu>
<sl-menu-item>オプション1</sl-menu-item>
<sl-menu-item>オプション2</sl-menu-item>
</sl-menu>
</sl-dropdown>
Stencil - エンタープライズグレードのツール
Stencilは、TypeScriptベースのWeb Componentsコンパイラで、デザインシステムの構築に最適です。
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'my-card',
styleUrl: 'my-card.css',
shadow: true,
})
export class MyCard {
@Prop() title: string;
render() {
return (
<div class="card">
<h2>{this.title}</h2>
<slot></slot>
</div>
);
}
}
実用的なユースケース
デザインシステムの構築
多くの企業が、複数のフレームワークを使用しているプロジェクト間で一貫性を保つために、Web Componentsベースのデザインシステムを採用しています。
実際の課題として、あるデザインシステムチームからは次のような声が上がっています:
「当初Reactを選択しましたが、Reactを使わないチームがデザインシステムを採用できないという課題に直面しています。特に外部パートナーが、ドキュメントを見ながらコンポーネントを再実装しており、デザインシステムの本来の目的と逆行しています。」
この問題に対し、Web Componentsは理想的な解決策を提供します。
マイクロフロントエンド
異なるチームが異なる技術スタックで開発している場合、Web Componentsは共通のインターフェースを提供します。
// チームA: Reactで開発
import '@company/shared-components/header';
function App() {
return (
<div>
<company-header user={currentUser} />
{/* React のコンテンツ */}
</div>
);
}
// チームB: Vueで開発
<template>
<div>
<company-header :user="currentUser" />
<!-- Vue のコンテンツ -->
</div>
</template>
レガシーシステムの段階的移行
フレームワークの移行は大きな投資を必要としますが、Web Componentsを使えば段階的な移行が可能です。
2025年の現代的な技術スタック
2025年3月に紹介された、モダンなWeb Components開発スタックは以下のような構成です:
- Lit - コンポーネント開発の基盤
- Suunta - SPA向けのルーティングと状態管理
- TailwindCSS - ユーティリティファーストのスタイリング
- TypeScript - 型安全性の確保
- Vite - 高速な開発体験
// Lit + TypeScript の例
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('user-profile')
export class UserProfile extends LitElement {
static styles = css`
:host {
display: block;
padding: 16px;
}
`;
@property({ type: Object })
user?: { name: string; email: string };
render() {
return html`
<div class="bg-white rounded-lg shadow p-4">
<h2 class="text-xl font-bold">${this.user?.name}</h2>
<p class="text-gray-600">${this.user?.email}</p>
</div>
`;
}
}
Web Componentsのベストプラクティス
イベント駆動通信
フレームワークに依存しない通信パターンとして、CustomEventsを使用します。
class MyInput extends HTMLElement {
connectedCallback() {
this.innerHTML = `<input type="text">`;
this.querySelector('input').addEventListener('input', (e) => {
this.dispatchEvent(new CustomEvent('value-change', {
bubbles: true,
composed: true, // Shadow DOMの境界を越える
detail: { value: e.target.value }
}));
});
}
}
::part()によるスタイルのカスタマイズ
Shadow DOM内の特定要素を外部からスタイリング可能にします。
class MyButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<button part="button">
<slot></slot>
</button>
`;
}
}
/* 外部からのスタイリング */
my-button::part(button) {
background-color: var(--brand-primary);
color: white;
}
Form-Associated Custom Elements
2025年では、フォーム統合がより簡単になっています。
class MyInput extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.#internals = this.attachInternals();
}
get value() {
return this.#value;
}
set value(v) {
this.#value = v;
this.#internals.setFormValue(v);
}
}
課題と考慮事項
Reactとの統合
2025年時点でも、ReactのWeb Componentsサポートは完全ではありません。ただし、React 19では改善が予定されています。現時点では、ラッパーコンポーネントを使用することで問題を回避できます。
// Reactラッパーの例
function WebComponent({ tag, ...props }) {
const ref = useRef(null);
useEffect(() => {
const element = ref.current;
Object.entries(props).forEach(([key, value]) => {
if (key.startsWith('on')) {
element.addEventListener(key.slice(2).toLowerCase(), value);
} else {
element[key] = value;
}
});
}, [props]);
return React.createElement(tag, { ref });
}
// 使用例
<WebComponent tag="my-button" label="クリック" onClick={handleClick} />
SSRの複雑性
Declarative Shadow DOMにより改善されましたが、SSRの実装にはまだ注意が必要です。特に、動的なコンテンツやJavaScriptに依存する機能については、適切なハイドレーション戦略が求められます。
学習曲線
フレームワークに慣れた開発者にとって、Web Componentsの低レベルなAPIは最初は戸惑うかもしれません。しかし、Litなどのライブラリを使用することで、この課題は大幅に軽減されます。
異なる視点:批判的意見も存在
公平性を期すために、Web Componentsに対する批判的な意見も紹介します。SolidJSの作者であるRyan Carniato氏は、2024年10月に「Web Components Are Not the Future」という記事で、Web Componentsが標準化されすぎることで、逆にイノベーションを阻害する可能性があると指摘しています。
しかし、2025年の現状を見ると、Web Componentsは特定のユースケース(特にデザインシステムやマイクロフロントエンド)において、非常に有効なソリューションであることが証明されています。
まとめ
2025年は、Web Componentsが「実験的な技術」から「実用的な選択肢」へと進化した年となりました。以下のような場合に、Web Componentsは特に有効です:
- デザインシステムの構築:複数のフレームワーク間で共有できるコンポーネントライブラリ
- マイクロフロントエンド:異なる技術スタックを統合する必要がある場合
- 長期的な保守性:フレームワークの流行り廃りに左右されない開発
- 段階的な移行:既存システムを少しずつモダナイズする場合
次のステップ
Web Componentsを始めるには:
- Litの公式サイトでチュートリアルを試す
- Shoelaceでプロダクション品質のコンポーネントを体験
- MDN Web Componentsで基礎を学ぶ
- 小さなプロジェクトで実験してみる
Web Componentsは、フロントエンド開発の未来を切り開く技術の一つです。ブラウザネイティブの力を活用し、フレームワークに依存しない、持続可能なWeb開発を実現しましょう。