フレームワーク不問!Web Componentsで実現するUI部品の共存戦略と構築術
ReactやVue.jsなどのフレームワークで作ったUIコンポーネント、別のプロジェクトで使い回そうとして「フレームワークが違うから使えない…」と困った経験はありませんか?プロジェクトごとに似たようなボタンやカードを再実装するのは、非効率ですよね。もし、どんな技術スタックでも使える「究極の再利用コンポーネント」が作れたら、開発効率は劇的に向上するはずです。この記事では、そんな願いを叶えるWeb標準技術 Web Components について、その仕組みから実践的な作り方、フレームワークとの共存戦略まで、手を動かしながら徹底的に解説します。
Web Componentsって何?フレームワークに縛られないWeb標準技術の力
Web Componentsとは、特定のJavaScriptフレームワークやライブラリに依存せず、再利用可能な UIコンポーネント を作成するためのWeb標準技術の集合体です。HTML、CSS、JavaScriptというWebの基本技術だけで、カプセル化された独自のHTML要素(カスタム要素)を作ることができます。
皆さんが普段何気なく使っている <video> タグや <select> タグを想像してみてください。これらは一見するとただのHTMLタグですが、その裏側では再生ボタンやシークバー、オプションリストといった複雑なUIと機能が隠されています。Web Componentsは、これと同じような「独自の高機能なHTMLタグ」を、誰でも作れるようにする技術なのです。
重要なのは、これが特定の企業が作った「新しいフレームワーク」ではないという点です。W3Cという標準化団体によって策定されたブラウザのネイティブ機能であり、2026年現在、Chrome, Firefox, Safari, Edgeといった主要なモダンブラウザで標準サポートされています。つまり、特別なライブラリを読み込まなくても、ブラウザさえあればWeb Componentsは動作するのです。
なぜ今、Web Componentsを学ぶべきなのか?再利用性と長期的な保守性のメリット
数多くのUIフレームワークが存在する中で、なぜ今あえてWeb Componentsを学ぶ価値があるのでしょうか。その答えは、主に2つの大きなメリットにあります。
一つ目は、圧倒的な 再利用性 です。Web Componentsで作成したコンポーネントは、特定の技術スタックに縛られません。例えば、Web Componentsで作った <my-design-button> というボタンは、Reactプロジェクトでも、Vueプロジェクトでも、Angularプロジェクトでも、あるいはフレームワークを使わない素のHTML/JavaScriptのサイトでも、まったく同じように利用できます。これにより、企業やチームのデザインシステムを構築する際に、技術選定の壁を越えて一貫したUIを提供できます。
二つ目は、長期的な保守性 です。JavaScriptフレームワークの世界は変化が速く、5年前に主流だった技術が今ではレガシーになっていることも少なくありません。フレームワークに依存して作ったコンポーネントは、そのフレームワーク自体のアップデートや衰退に運命を左右されます。一方、Web Componentsはブラウザの標準技術です。Web標準が後方互換性を非常に重視していることを考えると、一度作ったコンポーネントは、フレームワークの流行り廃りに影響されにくく、長期にわたって安定して動作し続けることが期待できます。これは、プロジェクトの技術的負債を減らす上で非常に大きな利点です。
Web Componentsを構成する3つの主要技術:Custom Elements, Shadow DOM, HTML Templatesを徹底解説
Web Componentsは単一の技術ではなく、以下の3つの主要な技術仕様を組み合わせて実現されています。それぞれがどのような役割を担っているのか、詳しく見ていきましょう。
Custom Elements (カスタム要素)
Custom Elementsは、開発者が独自のHTMLタグを定義し、その動作をJavaScriptのクラスで記述するためのAPIです。例えば、<user-profile-card> のような、意味が分かりやすく再利用可能なタグを作成できます。
定義は非常にシンプルで、HTMLElement クラスを継承した独自のクラスを作成し、customElements.define() メソッドを使ってタグ名とクラスを関連付けるだけです。これにより、ブラウザは指定されたタグを見つけると、対応するJavaScriptクラスをインスタンス化し、そのタグに命を吹き込みます。
Shadow DOM (シャドウDOM)
Shadow DOMは、コンポーネントの内部構造とスタイルを、ページの他の部分から完全に「隔離」するための仕組みです。各カスタム要素は、それ自身の「影の」DOMツリーを持つことができます。この内部のDOMは、通常のDOM(Light DOMと呼ばれます)とは独立しています。
この「カプセル化」がもたらす最大のメリットは、スタイルの衝突を防げることです。Shadow DOM内部で定義されたCSSは、そのコンポーネントの外に影響を与えません。逆に、グローバルなCSSがコンポーネント内部の要素に意図せず適用されてしまうこともありません。これにより、コンポーネントの見た目が壊れる心配をせずに、どこでも安心して利用できます。
HTML Templates ( タグ)
HTML Templatesは、その名の通りHTMLのテンプレートを定義するための <template> タグと <slot> タグから構成されます。<template> タグの中に書かれた内容は、ページの読み込み時にはレンダリングされず、非表示の状態に保たれます。
JavaScriptを使ってこのテンプレートの内容をコピーし、コンポーネントのShadow DOMに追加することで、効率的にコンポーネントの構造を生成できます。また、<slot> タグを使うと、コンポーネントの利用者が外部から独自のHTMLコンテンツを「差し込む」ためのプレースホルダーを定義でき、より柔軟で再利用性の高いコンポーネント設計が可能になります。
手を動かそう!シンプルなカスタムコンポーネントを実際に作ってみるハンズオン
それでは、実際に簡単なユーザープロフィールカード(<user-profile-card>)を作って、Web Componentsの仕組みを体験してみましょう。以下のHTMLファイルとJavaScriptファイルを作成してください。
まず、index.html です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Web Components ハンズオン</title>
<script src="user-profile-card.js" type="module"></script>
<style>
body { font-family: sans-serif; padding: 2rem; }
</style>
</head>
<body>
<h1>私のチームメンバー</h1>
<user-profile-card
name="山田 太郎"
avatar-url="https://i.pravatar.cc/150?u=yamada"
>
<div slot="email">[email protected]</div>
<div slot="bio">フロントエンドエンジニア。趣味はキャンプです。</div>
</user-profile-card>
<user-profile-card
name="鈴木 花子"
avatar-url="https://i.pravatar.cc/150?u=suzuki"
>
<div slot="email">[email protected]</div>
<div slot="bio">UI/UXデザイナー。最近、猫を飼い始めました。</div>
</user-profile-card>
</body>
</html>
次に、コンポーネントの振る舞いを定義する user-profile-card.js です。
// 1. テンプレートを定義
const template = document.createElement('template');
template.innerHTML = `
<style>
.card {
display: flex;
align-items: center;
gap: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
max-width: 400px;
}
.avatar {
width: 80px;
height: 80px;
border-radius: 50%;
}
.info {
display: flex;
flex-direction: column;
}
h3 {
margin: 0;
}
</style>
<div class="card">
<img class="avatar" src="" alt="アバター画像">
<div class="info">
<h3 id="name"></h3>
<slot name="email"></slot>
<slot name="bio"></slot>
</div>
</div>
`;
// 2. Custom Elementのクラスを定義
class UserProfileCard extends HTMLElement {
constructor() {
super();
// Shadow DOMを作成してテンプレートをアタッチ
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
// 要素がDOMに追加されたときに呼ばれる
connectedCallback() {
this.updateProfile();
}
// 監視する属性を指定
static get observedAttributes() {
return ['name', 'avatar-url'];
}
// 属性が変更されたときに呼ばれる
attributeChangedCallback(name, oldValue, newValue) {
this.updateProfile();
}
// 属性値をもとに表示を更新するヘルパーメソッド
updateProfile() {
if (this.hasAttribute('name')) {
this.shadowRoot.querySelector('#name').textContent = this.getAttribute('name');
}
if (this.hasAttribute('avatar-url')) {
this.shadowRoot.querySelector('.avatar').src = this.getAttribute('avatar-url');
}
}
}
// 3. カスタム要素を登録
customElements.define('user-profile-card', UserProfileCard);
この index.html をブラウザで開いてみてください。ビルドツールやサーバーは不要です。2つのプロフィールカードが表示されれば成功です!HTML側では <user-profile-card> という見慣れないタグを使っているだけですが、JavaScript側で定義したクラスによって、リッチなUIコンポーネントとして機能していることがわかります。
モダンなJavaScriptフレームワークとWeb Components、どう使い分ける?共存戦略
「Web Componentsが便利なら、もうReactやVueは要らないの?」と思うかもしれませんが、それは早計です。Web Componentsはフレームワークを置き換えるものではなく、むしろ 共存させる ことで真価を発揮します。
使い分けの一般的な指針は以下の通りです。
-
Web Componentsが適しているもの:
- デザインシステムで定義されるような、自己完結したUI部品(ボタン、入力フォーム、アイコン、カードなど)
- 複数のプロジェクトや、異なるフレームワーク間で共有したいコンポーネント
- 外部に公開する埋め込みウィジェット
-
フレームワークが適しているもの:
- アプリケーション全体の状態管理やデータフロー制御
- 複雑なビジネスロジックと密接に連携するUI
- ページ全体のルーティングやレイアウト構成
幸いなことに、2026年現在、React, Vue, Angularといった主要なモダンフレームワークは、Web Componentsを特別な設定なしにネイティブ要素のように扱えます。つまり、Reactのコンポーネント内で、先ほど作った <user-profile-card> をJSXとしてそのまま記述できるのです。この特性を活かし、UIの末端部品をWeb Componentsで固め、アプリケーション全体の骨格をフレームワークで構築するというのが、非常に強力な共存戦略となります。
開発現場でWeb Componentsを最大限に活用するための実践的なヒントと注意点
最後に、実際のプロジェクトでWeb Componentsを導入する際に役立つヒントと、知っておくべき注意点をいくつか紹介します。
-
スタイルのカスタマイズ性: Shadow DOMはスタイルを強力にカプセル化しますが、時にはコンポーネントの利用者が一部のスタイルを上書きしたいケースもあります。その際は、CSSカスタムプロパティ (--primary-color: blue;) や、::part 擬似要素といった仕組みを使うことで、コンポーネントの内部スタイルの一部を外部に公開し、カスタマイズを許可するのが一般的です。
-
開発を効率化するライブラリ: 素のJavaScriptでWeb Componentsを書くと、属性の変更監視やレンダリングの更新処理など、定型的なコードが多くなりがちです。Googleが開発している Lit や、Ionicチームが開発した Stencil.js のようなライブラリを利用すると、より宣言的かつ効率的にコンポーネントを記述できます。これらのライブラリは、最終的に標準のWeb Componentsを生成するヘルパーツールなので、特定のフレームワークにロックインされる心配はありません。
-
サーバーサイドレンダリング (SSR) への配慮: Web Componentsは、本質的にはクライアントサイドでJavaScriptが実行されて初めて機能する技術です。そのため、SSRとの相性には注意が必要です。Declarative Shadow DOMのような、サーバー側でShadow DOMの構造をHTMLとして出力するための新しい仕様も登場し、主要ブラウザでのサポートが進んでいますが、フレームワークが提供するSSRの仕組みと比べると、まだ発展途上な面もあります。SEOや初期表示速度が非常に重要なページで利用する場合は、この点を考慮した設計が必要になります。
Web Componentsは、特定のフレームワークの知識をWebの普遍的なスキルへと昇華させてくれる強力な武器です。ぜひあなたの次のプロジェクトで、この標準技術の力を試してみてください。
<template> タグと <slot> タグから構成されます。<template> タグの中に書かれた内容は、ページの読み込み時にはレンダリングされず、非表示の状態に保たれます。<slot> タグを使うと、コンポーネントの利用者が外部から独自のHTMLコンテンツを「差し込む」ためのプレースホルダーを定義でき、より柔軟で再利用性の高いコンポーネント設計が可能になります。<user-profile-card>)を作って、Web Componentsの仕組みを体験してみましょう。以下のHTMLファイルとJavaScriptファイルを作成してください。index.html です。<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Web Components ハンズオン</title>
<script src="user-profile-card.js" type="module"></script>
<style>
body { font-family: sans-serif; padding: 2rem; }
</style>
</head>
<body>
<h1>私のチームメンバー</h1>
<user-profile-card
name="山田 太郎"
avatar-url="https://i.pravatar.cc/150?u=yamada"
>
<div slot="email">[email protected]</div>
<div slot="bio">フロントエンドエンジニア。趣味はキャンプです。</div>
</user-profile-card>
<user-profile-card
name="鈴木 花子"
avatar-url="https://i.pravatar.cc/150?u=suzuki"
>
<div slot="email">[email protected]</div>
<div slot="bio">UI/UXデザイナー。最近、猫を飼い始めました。</div>
</user-profile-card>
</body>
</html>user-profile-card.js です。// 1. テンプレートを定義
const template = document.createElement('template');
template.innerHTML = `
<style>
.card {
display: flex;
align-items: center;
gap: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
max-width: 400px;
}
.avatar {
width: 80px;
height: 80px;
border-radius: 50%;
}
.info {
display: flex;
flex-direction: column;
}
h3 {
margin: 0;
}
</style>
<div class="card">
<img class="avatar" src="" alt="アバター画像">
<div class="info">
<h3 id="name"></h3>
<slot name="email"></slot>
<slot name="bio"></slot>
</div>
</div>
`;
// 2. Custom Elementのクラスを定義
class UserProfileCard extends HTMLElement {
constructor() {
super();
// Shadow DOMを作成してテンプレートをアタッチ
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
// 要素がDOMに追加されたときに呼ばれる
connectedCallback() {
this.updateProfile();
}
// 監視する属性を指定
static get observedAttributes() {
return ['name', 'avatar-url'];
}
// 属性が変更されたときに呼ばれる
attributeChangedCallback(name, oldValue, newValue) {
this.updateProfile();
}
// 属性値をもとに表示を更新するヘルパーメソッド
updateProfile() {
if (this.hasAttribute('name')) {
this.shadowRoot.querySelector('#name').textContent = this.getAttribute('name');
}
if (this.hasAttribute('avatar-url')) {
this.shadowRoot.querySelector('.avatar').src = this.getAttribute('avatar-url');
}
}
}
// 3. カスタム要素を登録
customElements.define('user-profile-card', UserProfileCard);index.html をブラウザで開いてみてください。ビルドツールやサーバーは不要です。2つのプロフィールカードが表示されれば成功です!HTML側では <user-profile-card> という見慣れないタグを使っているだけですが、JavaScript側で定義したクラスによって、リッチなUIコンポーネントとして機能していることがわかります。Web Componentsが適しているもの:
- デザインシステムで定義されるような、自己完結したUI部品(ボタン、入力フォーム、アイコン、カードなど)
- 複数のプロジェクトや、異なるフレームワーク間で共有したいコンポーネント
- 外部に公開する埋め込みウィジェット
フレームワークが適しているもの:
- アプリケーション全体の状態管理やデータフロー制御
- 複雑なビジネスロジックと密接に連携するUI
- ページ全体のルーティングやレイアウト構成
<user-profile-card> をJSXとしてそのまま記述できるのです。この特性を活かし、UIの末端部品をWeb Componentsで固め、アプリケーション全体の骨格をフレームワークで構築するというのが、非常に強力な共存戦略となります。スタイルのカスタマイズ性: Shadow DOMはスタイルを強力にカプセル化しますが、時にはコンポーネントの利用者が一部のスタイルを上書きしたいケースもあります。その際は、CSSカスタムプロパティ (--primary-color: blue;) や、::part 擬似要素といった仕組みを使うことで、コンポーネントの内部スタイルの一部を外部に公開し、カスタマイズを許可するのが一般的です。
開発を効率化するライブラリ: 素のJavaScriptでWeb Componentsを書くと、属性の変更監視やレンダリングの更新処理など、定型的なコードが多くなりがちです。Googleが開発している Lit や、Ionicチームが開発した Stencil.js のようなライブラリを利用すると、より宣言的かつ効率的にコンポーネントを記述できます。これらのライブラリは、最終的に標準のWeb Componentsを生成するヘルパーツールなので、特定のフレームワークにロックインされる心配はありません。
サーバーサイドレンダリング (SSR) への配慮: Web Componentsは、本質的にはクライアントサイドでJavaScriptが実行されて初めて機能する技術です。そのため、SSRとの相性には注意が必要です。Declarative Shadow DOMのような、サーバー側でShadow DOMの構造をHTMLとして出力するための新しい仕様も登場し、主要ブラウザでのサポートが進んでいますが、フレームワークが提供するSSRの仕組みと比べると、まだ発展途上な面もあります。SEOや初期表示速度が非常に重要なページで利用する場合は、この点を考慮した設計が必要になります。


