WebコンポーネントをStencilで作る方法|再利用可能なUI部品を効率よく開発する仕組み
WebコンポーネントをStencilで作るとは、ブラウザ標準に基づく再利用可能なUI部品を、Stencilという開発道具を使って効率よく作成することです。Webコンポーネントは、特定のフレームワークに強く依存せず、カスタム要素、シャドウDOM、HTMLテンプレート、スロットなどのWeb標準技術を使って、独自のHTML要素を作るための仕組みです。Stencilは、そのWebコンポーネントをTypeScriptとJSXに近い書き方で開発し、最終的に標準的なWebコンポーネントとして出力するためのコンパイラです。
通常のWebコンポーネントは、素のJavaScriptだけでも作れます。しかし、部品の数が増えてくると、プロパティ、状態、イベント、メソッド、ライフサイクル、スロット、シャドウDOM、型定義、配布形式、ドキュメント生成などを自分で管理する必要があり、開発と保守が複雑になりやすくなります。Stencilを使うと、これらの部品開発に必要な仕組みを整理された形で扱えるため、共通UI部品やデザインシステムを作りやすくなります。
本記事では、WebコンポーネントとStencilの基本、Stencilを使う理由、部品の基本構造、プロパティ、状態、イベント、メソッド、スロット、シャドウDOM、ライフサイクル、React・Angular・Vueとの関係、向いているケース、注意点まで、初心者にも分かりやすく解説します。
1. Webコンポーネントとは
Webコンポーネントとは、ブラウザ標準の仕組みを使って、再利用可能なUI部品を作るための技術群です。独自のHTML要素を定義し、その中に構造、見た目、動作をまとめることができます。たとえば、<app-button>、<user-card>、<product-modal> のような独自要素を作り、通常のHTML要素のように画面へ配置できます。
Webコンポーネントの目的は、UIを部品として切り出し、複数の画面や複数のプロジェクトで再利用しやすくすることです。ボタン、入力欄、カード、モーダル、タブ、通知、メニューなどを部品として整理すれば、画面ごとに同じUIを作り直す必要が減ります。また、部品単位で見た目や動作を管理できるため、保守性も高くなります。
| 英語の用語 | 日本語での表現 | 役割 |
|---|---|---|
| Web Components | Webコンポーネント | 再利用可能なUI部品を作る標準技術群 |
| Custom Elements | カスタム要素 | 独自のHTML要素を定義する |
| Shadow DOM | シャドウDOM | 部品内部の構造やスタイルを分離する |
| HTML Templates | HTMLテンプレート | 再利用するHTML構造の雛形を作る |
| Slots | スロット | 外部から部品内部へ内容を差し込む |
| Component | 部品 / コンポーネント | UIを再利用可能な単位に分けたもの |
1.1 カスタム要素
カスタム要素とは、開発者が独自に定義できるHTML要素です。通常のHTMLには、button、input、select、section、articleなどの要素がありますが、カスタム要素を使うと、アプリケーションやデザインシステムに合わせた独自の要素を作れます。たとえば、<design-button>、<profile-card>、<app-dialog> のような要素を定義できます。
カスタム要素の良い点は、JavaScriptで作られた部品でありながら、利用側からはHTMLタグのように扱えることです。UI部品をHTMLとして自然に配置できるため、画面構造が分かりやすくなります。特に、複数のプロジェクトで同じ部品を使いたい場合、カスタム要素は再利用性を高めるうえで有効です。
1.2 シャドウDOM
シャドウDOMとは、部品内部のDOM構造やスタイルを外部のページから分離するための仕組みです。通常のHTMLでは、外部ページのCSSが部品内部に影響したり、部品内部のCSSが外部へ影響したりすることがあります。シャドウDOMを使うと、部品の内部構造とスタイルをある程度閉じ込めることができます。
この分離は、共通UI部品やデザインシステムを作るときに重要です。たとえば、複数のサービスで同じボタン部品を使う場合、利用先のCSSによってボタンの見た目が壊れると困ります。シャドウDOMを使えば、部品の見た目や内部構造を安定させやすくなります。
1.3 HTMLテンプレート
HTMLテンプレートとは、画面にすぐ表示されないHTMLの雛形を定義する仕組みです。必要なタイミングでテンプレートを複製し、部品の内部構造として使うことができます。Webコンポーネントでは、部品の基本構造をテンプレートとして持たせることで、同じ構造を再利用しやすくなります。
HTMLテンプレートを使うと、UIの構造をHTMLとして整理できます。JavaScript文字列でHTMLを組み立てるよりも、構造が分かりやすくなり、部品の保守性も高くなります。Stencilを使う場合は、開発者が直接HTMLテンプレートを細かく操作する場面は少なくなりますが、Webコンポーネントの基本として理解しておくと役立ちます。
1.4 スロット
スロットとは、Webコンポーネントの中に外部から内容を差し込むための仕組みです。部品の枠組みは固定しつつ、中に表示するテキスト、画像、アイコン、ボタン、補足情報などを利用側から渡せます。たとえば、カード部品の本文部分だけをページごとに変えたい場合に便利です。
スロットを使うと、部品の再利用性が高まります。部品側は基本の構造と見た目を提供し、利用側は必要な内容を差し込むだけで済みます。ただし、自由度を高くしすぎると見た目や使い方がばらつくため、どこを固定し、どこを差し替え可能にするかを明確に設計する必要があります。
2. Stencilとは
Stencilとは、Webコンポーネントを作るためのコンパイラです。開発者はTypeScriptやJSXに近い書き方でUI部品を作り、Stencilがそれを標準的なWebコンポーネントとして出力します。StencilはIonicチームによって作られており、特に部品ライブラリやデザインシステムを作る場面で利用されます。
Stencilの特徴は、開発時には現代的な部品開発の書き方を使いながら、配布時にはWeb標準に近い形にできることです。つまり、React専用、Angular専用、Vue専用の部品ではなく、複数の環境で利用しやすいUI部品を作るための道具として使えます。
| 項目 | 内容 |
|---|---|
| 名称 | Stencil |
| 種類 | Webコンポーネント用コンパイラ |
| 主な言語 | TypeScript |
| 記述形式 | JSXに近い記述 |
| 出力 | 標準的なWebコンポーネント |
| 主な用途 | 部品ライブラリ、デザインシステム、共通UI基盤 |
| 特徴 | 型安全性、部品化、シャドウDOM、フレームワーク非依存 |
2.1 Stencilはフレームワークではなくコンパイラ
Stencilは、ReactやVueのようにアプリケーション全体を構築するためのフレームワークというより、Webコンポーネントを作るためのコンパイラとして理解すると分かりやすいです。開発者はStencilの書き方で部品を定義し、ビルド時にブラウザで使えるWebコンポーネントへ変換します。
そのため、Stencilは「アプリ全体を作る道具」ではなく、「再利用可能なUI部品を作る道具」として特に強みを発揮します。アプリケーションの画面遷移や状態管理をすべてStencilだけで行うというより、共通ボタン、入力欄、モーダル、カードなどをWebコンポーネントとして作り、さまざまな環境で使う用途に向いています。
2.2 TypeScriptで部品を作れる
StencilではTypeScriptを使って部品を作れます。TypeScriptを使うことで、プロパティの型、イベントで渡す値、メソッドの戻り値、内部状態などを明確にできます。大規模な部品ライブラリでは、型があることで利用ミスを減らし、保守性を高めやすくなります。
複数人でUI部品を開発する場合、型の情報は非常に重要です。どのプロパティにどの値を渡せるのか、どのイベントが発生するのか、どのメソッドが利用できるのかを明確にすることで、部品を使う側も安全に実装できます。
2.3 JSXに近い書き方ができる
Stencilでは、JSXに近い書き方で部品の表示内容を記述できます。HTMLに似た構造をTypeScript内で書けるため、部品の見た目や構造を視覚的に理解しやすくなります。Reactの経験がある開発者にとっては、比較的なじみやすい書き方です。
ただし、StencilはReactそのものではありません。JSXに近い記法を使っていても、最終的に出力されるのはWebコンポーネントです。そのため、Reactの設計をそのまま当てはめるのではなく、カスタム要素、シャドウDOM、スロット、プロパティ、イベントといったWebコンポーネントの仕組みを理解する必要があります。
3. StencilでWebコンポーネントを作る理由
StencilでWebコンポーネントを作る理由は、標準技術に近いUI部品を効率よく開発できるからです。素のWebコンポーネントは強力ですが、すべてを手書きで作ると、記述量が多くなり、型管理、イベント設計、部品の更新処理、配布形式の整理が複雑になりやすくなります。Stencilは、そこに開発体験の良さを加えます。
特に、複数のフレームワークや複数のプロジェクトで同じUI部品を使いたい場合、Stencilは有力な選択肢になります。React用、Angular用、Vue用に別々の部品を作るのではなく、Webコンポーネントとして共通部品を作り、各環境で利用する考え方ができます。
| 理由 | 内容 |
|---|---|
| フレームワーク非依存 | 複数の環境で使えるUI部品を作りやすい |
| 型安全性 | TypeScriptで公開仕様を整理しやすい |
| 部品ライブラリ向き | 共通UIをまとめて配布しやすい |
| デザインシステム向き | 見た目と挙動を統一しやすい |
| 標準技術に近い | Web標準を活かした長期運用がしやすい |
| 開発体験が良い | デコレーターやJSXで部品を作りやすい |
3.1 フレームワーク非依存の部品を作れる
Stencilで作った部品は、Webコンポーネントとして配布できます。そのため、特定のフレームワークに強く依存しない部品を作りやすくなります。企業内でReact、Angular、Vue、素のHTMLが混在している場合でも、同じUI部品を利用できる可能性があります。
これは、デザインシステムを作る場合に大きなメリットになります。ボタン、入力欄、カード、モーダル、通知、タブなどの基本部品をStencilで作れば、複数の開発チームが同じUI品質を共有しやすくなります。
3.2 部品ライブラリに向いている
Stencilは、単一の画面を作るよりも、部品ライブラリを作る用途に向いています。部品ライブラリでは、各部品の公開プロパティ、イベント、スロット、スタイル調整方法、アクセシビリティ、利用例、ドキュメントが重要になります。Stencilは、これらを整理して開発しやすい構造を持っています。
デザインシステムでは、見た目の統一だけでなく、操作感、状態、エラー表示、キーボード操作、支援技術対応まで含めて部品化する必要があります。Stencilを使うことで、これらのルールを実装されたUI部品として配布しやすくなります。
3.3 標準技術を活かせる
Stencilの出力はWebコンポーネントであるため、カスタム要素、シャドウDOM、スロットなどのWeb標準技術を活かせます。HTML要素として利用できるため、外部からの使い方も比較的分かりやすくなります。
フロントエンドの流行は変わりますが、Web標準は比較的長く残ります。Stencilで標準に近い部品を作ることで、特定のフレームワークの寿命や移行に左右されにくいUI資産を作れる可能性があります。
4. Stencil部品の基本構造
Stencilの部品は、TypeScriptのクラスとして定義されます。@Component() デコレーターで部品の情報を指定し、render() メソッドで表示内容を返します。外部から受け取る値は @Prop()、内部で変化する値は @State()、外部へ通知する変化は @Event()、外部から呼び出せる処理は @Method() で定義します。
この構造により、部品の責務を整理できます。プロパティは外部入力、状態は内部管理、イベントは外部通知、メソッドは外部からの命令的な操作、スロットは外部からの内容差し込みとして扱えます。部品設計では、これらを混ぜずに使い分けることが重要です。
| 英語の用語 | 日本語での表現 | 役割 |
|---|---|---|
| Decorator | デコレーター | 部品や値に特別な意味を付ける |
| Component | 部品 / コンポーネント | UIの再利用単位 |
| Props | プロパティ | 外部から値を受け取る |
| State | 状態 | 部品内部で変化する値を持つ |
| Event | イベント | 外部へ変化を通知する |
| Method | メソッド | 外部から処理を呼び出せるようにする |
| Render | 描画 | 画面に出す構造を返す |
| Lifecycle | ライフサイクル | 部品の生成・更新・削除の流れ |
4.1 @Component() デコレーター
@Component() は、TypeScriptのクラスをStencil部品として定義するためのデコレーターです。ここで、HTMLで使う要素名、スタイルファイル、シャドウDOMを使うかどうかなどを指定します。Stencil部品の入口になる重要な設定です。
要素名は、Webコンポーネントのルールに従い、通常ハイフンを含む名前にします。たとえば、app-button や user-card のような名前です。これにより、既存のHTML要素と衝突しにくくなります。
4.2 render() メソッド
render() メソッドは、部品の表示内容を返す場所です。StencilではJSXに近い記法でHTML構造を書き、プロパティや状態に応じて表示を変えられます。たとえば、読み込み中ならローディング表示、エラーがあるならエラーメッセージを表示する、といった制御ができます。
ただし、render() に複雑な計算や副作用のある処理を詰め込みすぎると、部品が分かりにくくなります。render() は、できるだけ表示構造を分かりやすく返す場所として使い、重い処理や外部通信は別の責務として整理することが大切です。
4.3 スタイルの指定
Stencil部品では、部品ごとにCSSファイルを指定できます。シャドウDOMを使う場合、スタイルは部品内部に閉じ込められやすくなります。これにより、外部ページのCSSによって部品の見た目が壊れるリスクを減らせます。
ただし、完全に閉じたスタイルにすると、利用側から見た目を調整しにくくなる場合があります。デザインシステムでは、CSS変数などを使って、必要な範囲だけ外部から調整できる設計にすることが重要です。
5. プロパティ
プロパティとは、外部から部品へ値を渡すための仕組みです。Stencilでは @Prop() デコレーターを使って公開プロパティを定義します。HTML属性やJavaScriptのプロパティとして値を渡し、その値に応じて部品の表示や動作を変えられます。
たとえば、ボタン部品であれば、種類、サイズ、無効状態、読み込み状態、ラベルなどをプロパティとして受け取れます。カード部品であれば、タイトル、説明文、画像URL、リンク先などをプロパティとして受け取ることがあります。
| プロパティ例 | 役割 |
|---|---|
label | 表示するラベルを渡す |
disabled | 無効状態を指定する |
variant | 見た目の種類を指定する |
size | サイズを指定する |
value | 入力値や選択値を渡す |
required | 必須かどうかを指定する |
5.1 外部から値を渡す
プロパティの基本的な役割は、部品の外側から値を渡すことです。利用側はHTML属性のように値を指定し、部品側はその値を使って表示を変えます。これにより、同じ部品をさまざまな状態で再利用できます。
たとえば、同じボタン部品でも、主ボタン、補助ボタン、危険操作ボタン、無効ボタンなどをプロパティで切り替えられます。部品を増やしすぎず、プロパティで適切に制御することが大切です。
5.2 プロパティ設計の注意点
プロパティを増やしすぎると、部品が複雑になります。利用側はどのプロパティを組み合わせればよいのか分からなくなり、内部実装も保守しにくくなります。プロパティは、部品の目的に対して本当に必要なものに絞るべきです。
また、プロパティ名は分かりやすく、一貫性を持たせる必要があります。たとえば、サイズは size、見た目の種類は variant、無効状態は disabled のように、部品間で共通した命名規則を作ると、利用者が理解しやすくなります。
5.3 外部制御と内部状態を分ける
プロパティは外部から渡される値であり、内部で自由に変更する値ではありません。部品内部で変化させたい値は、状態として扱うほうが自然です。外部から渡された値を内部で勝手に変更すると、利用側の予測とずれることがあります。
部品設計では、「外部から制御される値」と「内部で管理する値」を分けることが重要です。これはStencilだけでなく、React、Angular、Vueなどの部品設計でも共通する考え方です。
6. 状態
状態とは、部品内部で変化する値です。Stencilでは @State() デコレーターを使って内部状態を定義します。状態が変わると、Stencilは部品を再描画し、画面表示を更新します。状態は、外部から直接操作されるものではなく、部品の内部動作を管理するために使います。
たとえば、開閉メニューの開閉状態、タブの選択状態、入力中の一時値、読み込み中かどうか、エラー表示の有無などは状態として扱えます。状態を適切に管理することで、部品の動作が分かりやすくなります。
6.1 内部だけで使う値
状態は、部品内部だけで使う値です。外部から渡されるプロパティとは違い、部品自身が値を変更します。たとえば、アコーディオン部品で開いているか閉じているかを管理する場合、内部状態として持つことがあります。
内部状態を使うと、部品は自分自身の表示を管理できます。しかし、外部から制御したい場合は、プロパティとイベントを組み合わせた設計が必要になります。完全に内部で閉じるのか、外部から制御可能にするのかを事前に決めることが大切です。
6.2 状態変更と再描画
Stencilでは、状態が変わると部品が再描画されます。これにより、状態に応じた表示を作れます。たとえば、isOpen がtrueならメニューを表示し、falseなら非表示にするといった処理です。
ただし、状態を細かく変更しすぎると、不要な再描画が増える可能性があります。大きなデータを状態に持つ場合や、頻繁に更新される値を扱う場合は、パフォーマンスにも注意が必要です。
6.3 状態を外部へ漏らしすぎない
状態は部品内部の実装に近いものです。外部に公開しすぎると、部品の内部構造が利用側に依存されてしまい、後から変更しにくくなります。外部に知らせる必要がある場合は、イベントで通知するほうが自然です。
たとえば、メニューが開いたことを外部に知らせたい場合、内部状態を直接見せるのではなく、開閉イベントを発火する設計にできます。これにより、内部実装を守りながら外部連携ができます。
7. イベント
イベントとは、部品内部で起きた変化や操作を外部へ知らせるための仕組みです。Stencilでは @Event() デコレーターを使って独自イベントを定義できます。ユーザーがボタンを押した、値が変わった、項目が選択された、処理が完了した、といった情報を外部へ通知できます。
WebコンポーネントはHTML要素として利用されるため、イベントは非常に重要です。部品は内部で動作しながら、必要なタイミングで外部へ通知します。利用側は、そのイベントを受け取ってアプリケーションの処理を実行します。
| イベント例 | 役割 |
|---|---|
valueChange | 値が変わったことを通知する |
itemSelect | 項目が選択されたことを通知する |
openChange | 開閉状態が変わったことを通知する |
submitClick | 送信操作が行われたことを通知する |
loadComplete | 読み込み完了を通知する |
errorOccur | エラー発生を通知する |
7.1 外部へ変化を伝える
イベントの基本的な役割は、部品内部の変化を外部へ伝えることです。たとえば、入力部品で値が変わったとき、外部のフォーム管理に通知する必要があります。このとき、部品は独自イベントを発火し、利用側がそれを受け取ります。
この設計により、部品は内部処理を隠しながら、必要な情報だけを外部へ伝えられます。部品の独立性と連携性を両立するために、イベント設計は重要です。
7.2 イベント名の設計
イベント名は、何が起きたのか分かりやすい名前にする必要があります。曖昧な名前にすると、利用側が意味を理解しにくくなります。たとえば、単に change とするより、部品の文脈に応じて valueChange や openChange のようにすると分かりやすい場合があります。
また、部品ライブラリ全体で命名規則を統一することも大切です。イベント名の形式が部品ごとにばらばらだと、利用者は覚えるのが大変になります。デザインシステムでは、イベント名も設計資産の一部です。
7.3 イベントに含める情報
イベントには、必要な情報だけを含めるべきです。たとえば、選択イベントなら、選択された値や識別子を渡します。不要な内部情報まで渡すと、利用側が部品の内部構造に依存しやすくなります。
イベントの情報設計では、外部が何を知る必要があるかを考えます。部品内部の詳細を隠しながら、利用側が必要な処理を行えるだけの情報を提供することが理想です。
8. メソッド
メソッドとは、外部から部品の処理を呼び出すための仕組みです。Stencilでは @Method() デコレーターを使って公開メソッドを定義できます。たとえば、モーダルを開く、入力欄にフォーカスする、フォームをリセットする、内部状態を初期化する、といった処理を外部から呼び出せます。
ただし、公開メソッドは使いすぎに注意が必要です。多くの場合、プロパティとイベントで十分に部品を制御できます。公開メソッドを増やしすぎると、利用側が部品の内部処理に強く依存し、保守しにくくなることがあります。
8.1 外部から処理を呼び出す
公開メソッドは、利用側が部品に対して命令を出したい場合に使います。たとえば、親画面からモーダル部品を開きたい場合、open() のようなメソッドを用意することがあります。フォーム部品であれば、reset() や validate() のようなメソッドが考えられます。
このようなメソッドは便利ですが、部品の公開仕様になります。一度公開すると、利用側が依存するため、後から変更しにくくなります。公開メソッドは慎重に設計する必要があります。
8.2 プロパティとイベントで足りる場合
部品の多くは、プロパティとイベントで制御できます。たとえば、モーダルの開閉状態を外部から制御したい場合、open プロパティを渡し、開閉変更をイベントで通知する設計もできます。この場合、公開メソッドを使わなくても連携できます。
どちらが良いかは、部品の性質によります。宣言的に状態を渡したい場合はプロパティ、命令的に一度だけ処理を呼びたい場合はメソッドが向いています。設計方針を混在させすぎないことが大切です。
8.3 メソッドを増やしすぎない
公開メソッドを増やしすぎると、部品は小さな公開仕様を持つ独立部品ではなく、複雑な操作対象になってしまいます。利用側が内部処理を細かく操作するようになると、部品の独立性が下がります。
そのため、公開メソッドは本当に外部から呼び出す必要があるものに限定します。部品の設計では、外部に見せる面をできるだけ小さく保つことが、長期的な保守性につながります。
9. スロット設計
スロット設計とは、部品のどの部分に外部から内容を差し込めるようにするかを決めることです。スロットを使うと、部品の基本構造を保ちながら、利用側が柔軟に内容を指定できます。カード、ボタン、モーダル、タブ、レイアウト部品などでよく使われます。
スロットは便利ですが、自由度を高くしすぎると、部品の見た目や使い方がばらつく可能性があります。どこを固定し、どこを差し替え可能にするかを明確にすることが重要です。
| スロット種類 | 役割 |
|---|---|
| 既定スロット | 名前なしで内容を差し込む |
| 名前付きスロット | 指定した場所へ内容を差し込む |
| 見出しスロット | タイトル部分を差し替える |
| 補助スロット | アイコンや補足表示を差し込む |
| 操作スロット | ボタンやリンクを差し込む |
9.1 既定スロット
既定スロットは、名前を指定しないスロットです。部品の中に自由な内容を差し込むために使います。たとえば、カード部品の本文部分に利用側が文章や画像を入れる場合に使えます。
既定スロットは使いやすい反面、自由度が高くなりすぎることがあります。利用側が想定外の構造を入れると、見た目が崩れたり、アクセシビリティに問題が出たりする場合があります。必要に応じて、利用ルールをドキュメントに書くことが大切です。
9.2 名前付きスロット
名前付きスロットは、特定の場所に内容を差し込むための仕組みです。たとえば、カード部品でヘッダー、本文、フッターを分けたい場合、header、content、footer のようなスロットを用意できます。
名前付きスロットを使うと、部品の構造を保ちながら柔軟性を持たせられます。ただし、スロット名が増えすぎると利用が難しくなります。部品の目的に合わせて、必要な差し込み口だけを用意することが重要です。
9.3 スロットとアクセシビリティ
スロットに差し込まれる内容は、利用側が自由に決めます。そのため、部品側だけではアクセシビリティを完全に保証できないことがあります。たとえば、スロットに入れるボタンや見出しが適切なHTML構造になっていないと、支援技術で使いにくくなる場合があります。
スロットを使う部品では、どのような要素を差し込むべきか、どの役割を期待しているかをドキュメント化することが大切です。部品側で構造を固定できる部分は固定し、利用側に任せる部分は明確に説明します。
10. ライフサイクル
ライフサイクルとは、部品が作成され、読み込まれ、表示され、更新され、削除されるまでの流れです。Stencilには、部品の状態に応じて呼び出されるライフサイクル用のメソッドがあります。これを使うことで、初期化処理、データ取得、更新後の処理、外部リソースの解除などを適切なタイミングで行えます。
ライフサイクルを理解していないと、不要な処理が何度も実行されたり、イベントリスナーやタイマーが解除されなかったり、メモリリークが起きたりすることがあります。部品開発では、見た目だけでなく、部品がいつ何をするかを設計する必要があります。
| ライフサイクルの考え方 | 役割 |
|---|---|
| 読み込み前 | 初期データを準備する |
| 読み込み後 | DOMに接続された後の処理を行う |
| 更新前 | 状態やプロパティ変更前に処理する |
| 更新後 | 再描画後の処理を行う |
| 削除前 | イベントやタイマーを解除する |
10.1 初期化処理
部品が表示される前や表示された直後に、初期化処理を行うことがあります。たとえば、外部データの取得、初期状態の計算、外部ライブラリの準備などです。ライフサイクルを使うことで、適切なタイミングで初期化できます。
ただし、初期化処理が重すぎると、部品の表示が遅くなります。必要な処理と後回しにできる処理を分けることが大切です。特に部品ライブラリでは、利用側の画面全体に影響しないよう、軽量な初期化を意識する必要があります。
10.2 更新処理
プロパティや状態が変わると、部品は更新されます。更新時に何か処理したい場合、ライフサイクルを使って変更を検知できます。たとえば、プロパティが変わったら内部状態を調整する、外部へ通知する、表示を再計算する、といった処理です。
ただし、更新処理が複雑になると、部品の動作が分かりにくくなります。プロパティ変更に対して何が起こるかを明確にし、副作用を最小限に保つことが重要です。
10.3 後処理
部品が画面から削除されるときには、後処理が必要になることがあります。イベントリスナー、タイマー、外部購読、外部ライブラリのインスタンスなどを解除しないと、メモリリークや不要な処理の原因になります。
部品ライブラリでは、後処理まで含めて品質です。表示が正しくても、画面遷移を繰り返すたびにメモリが増えるような部品は、実務では問題になります。ライフサイクルを使って、後片付けを確実に行う必要があります。
11. シャドウDOMとスタイル設計
Stencilでは、シャドウDOMを使うかどうかを部品ごとに設定できます。シャドウDOMを使うと、部品内部の構造やスタイルを外部から分離できます。これにより、共通部品の見た目が外部CSSによって壊れにくくなります。
一方で、シャドウDOMを使うと、外部からのスタイル調整が難しくなる場合があります。デザインシステムでは、完全に閉じるのではなく、CSS変数や公開されたスタイル調整の仕組みを通じて、必要な範囲で調整できるようにすることが重要です。
11.1 スタイルの分離
シャドウDOMの大きなメリットは、スタイルの分離です。外部ページのCSSが部品内部へ影響しにくくなり、部品の見た目を安定させやすくなります。複数プロジェクトで同じ部品を使う場合、この安定性は重要です。
たとえば、あるページで button に強いCSSが設定されていても、シャドウDOM内のボタンには影響しにくくなります。これにより、部品ライブラリの見た目を守りやすくなります。
11.2 外部から調整しにくい問題
シャドウDOMは便利ですが、外部から細かくスタイルを変更しにくくなるという問題もあります。利用側が色や余白を調整したい場合、通常のCSS選択子では内部要素に届かないことがあります。
この問題を避けるために、CSS変数や公開されたスタイル調整の仕組みを用意することがあります。たとえば、ボタンの主色、角丸、余白などをCSS変数として定義し、利用側が安全に調整できるようにします。
11.3 デザインシステムとの関係
デザインシステムでは、色、文字、余白、角丸、影、アニメーションなどのルールを統一する必要があります。Stencil部品でシャドウDOMを使う場合でも、デザイントークンをCSS変数として扱えば、共通ルールを保ちやすくなります。
重要なのは、部品ごとに見た目を自由に変えられるようにすることではなく、設計された範囲で一貫性を保ちながら調整できるようにすることです。シャドウDOMとCSS変数を組み合わせることで、保護と柔軟性のバランスを取れます。
12. React・Angular・Vueとの関係
Stencilで作ったWebコンポーネントは、React、Angular、Vueなどのフレームワークと組み合わせて使えます。これは、Stencilの大きなメリットです。部品をWeb標準として作ることで、複数のフロントエンド環境で同じUI部品を利用しやすくなります。
ただし、各フレームワークにはイベントの扱い方、プロパティの渡し方、型定義、フォーム連携などに違いがあります。そのため、実務では各フレームワーク向けの利用方法や補助パッケージを整備することがあります。
| 環境 | 関係 |
|---|---|
| React | Webコンポーネントを利用できるが、イベントや型に注意が必要 |
| Angular | Webコンポーネントとの相性が比較的良い |
| Vue | 独自要素として扱えるが設定が必要な場合がある |
| 素のHTML | そのままHTML要素として利用できる |
| デザインシステム | 複数環境で同じ部品を共有しやすい |
12.1 Reactで使う場合
ReactでもWebコンポーネントを使えます。ただし、React独自のイベント処理やプロパティの扱いと、Webコンポーネントの標準的なイベントや属性の扱いには違いがあります。特に独自イベントを受け取る場合、通常のReactイベントと同じ感覚で扱えないことがあります。
そのため、Reactで使いやすくするために、薄いラッパー部品を用意することがあります。ラッパーを用意すれば、React利用者は通常のReact部品に近い感覚でStencil部品を扱えます。
12.2 Angularで使う場合
AngularはWebコンポーネントとの相性が比較的良いとされることがあります。Angular側でカスタム要素を許可し、Stencil部品を読み込むことで利用できます。フォームや型の扱いについては、プロジェクトごとに設計が必要です。
Angularの大規模業務システムで、共通UI部品をStencilで作るケースも考えられます。複数チームが同じデザインシステムを使う場合、Stencil部品を中心にすることで統一しやすくなります。
12.3 Vueで使う場合
VueでもWebコンポーネントを利用できます。ただし、Vueのテンプレートコンパイラが独自要素をどのように扱うかに注意が必要です。必要に応じて、カスタム要素として認識させる設定を行うことがあります。
VueのプロジェクトでStencil部品を使う場合も、プロパティ、イベント、スロットの使い方を明確にする必要があります。ドキュメントで利用例を用意すると、導入しやすくなります。
13. Stencilが向いているケース
Stencilが向いているのは、複数の環境で使うUI部品を作りたい場合です。特に、企業内で複数のフロントエンド技術が混在している場合、同じデザインシステムを複数プロジェクトに提供したい場合、Web標準に近い部品を長期的に保守したい場合に向いています。
一方で、単一のReactアプリだけを作る場合、必ずしもStencilが必要とは限りません。Reactだけで完結するなら、React部品として作るほうが自然な場合もあります。Stencilは「どの環境でも使える部品資産」を重視する場合に強みがあります。
| 向いているケース | 理由 |
|---|---|
| デザインシステム | 共通UIを複数環境で使える |
| 部品ライブラリ | 再利用可能なWeb標準部品を作れる |
| 複数フレームワーク運用 | React・Angular・Vueなどで共有しやすい |
| 長期運用 | Web標準に近い形で資産化できる |
| 企業内共通基盤 | UIの統一と保守性を高めやすい |
| 埋め込み部品 | 外部サイトや複数ページへ組み込みやすい |
13.1 デザインシステム
Stencilはデザインシステムと相性が良いです。デザインシステムでは、ボタン、入力欄、選択部品、カード、モーダル、タブ、通知などを共通部品として提供します。これらをStencilで作れば、複数のフロントエンド環境で同じ部品を共有しやすくなります。
デザインシステムの目的は、見た目の統一だけではありません。操作性、アクセシビリティ、状態、エラー表示、余白、色、文言のルールも統一することです。Stencilを使うことで、これらのルールを部品として配布しやすくなります。
13.2 複数技術の混在
企業では、古いAngularアプリ、新しいReactアプリ、一部Vueアプリ、素のHTMLページなどが混在していることがあります。このような環境でUI部品を個別に作ると、同じボタンや入力欄を何度も実装することになります。
StencilでWebコンポーネントとして共通部品を作れば、複数環境で同じ部品を使える可能性があります。これにより、UIの一貫性と開発効率を高められます。
13.3 埋め込み部品
外部サイトや社内の複数ページに埋め込む部品にもStencilは向いています。たとえば、問い合わせフォーム、評価ウィジェット、通知バナー、予約部品、チャット起動ボタンなどをWebコンポーネントとして配布できます。
このような埋め込み部品では、外部ページのCSSやJavaScriptと衝突しにくいことが重要です。シャドウDOMや部品の独立性を活かせば、さまざまなページへ安全に組み込みやすくなります。
14. Stencilが向いていないケース
Stencilは便利ですが、すべての場面に向いているわけではありません。単一のReactアプリだけを作る場合や、チームがWebコンポーネントに慣れていない場合、部品配布の必要がない場合、単純な小規模サイトの場合は、Stencilを導入するメリットが小さいことがあります。
技術選定では、「Stencilが使えるか」ではなく、「Stencilを使うことで何が良くなるか」を考える必要があります。導入目的が曖昧なまま使うと、学習コストやビルド設定だけが増える可能性があります。
14.1 単一フレームワークで完結する場合
プロジェクトがReactだけ、Vueだけ、Angularだけで完結している場合、そのフレームワークの部品として作るほうが自然な場合があります。特にアプリ内部でしか使わない部品であれば、StencilでWebコンポーネント化する必要はないかもしれません。
Stencilは、再利用範囲が広いほど価値が出ます。複数プロジェクト、複数技術、長期的な共通部品化が目的でないなら、導入効果を慎重に考えるべきです。
14.2 小規模なUIだけの場合
小さなページや単純な部品だけであれば、素のHTML、CSS、JavaScriptで十分なことがあります。Stencilを導入すると、開発環境、ビルド、設定、配布形式、ドキュメントなどを管理する必要があります。
小規模なUIに対して重い仕組みを導入すると、かえって複雑になります。最初は標準技術で作り、部品の再利用範囲が広がってからStencilを検討するのも現実的です。
14.3 Webコンポーネントの理解がない場合
StencilはWebコンポーネントを作る道具です。そのため、Webコンポーネントの考え方を理解していないと、使い方を誤る可能性があります。カスタム要素、シャドウDOM、属性とプロパティ、イベント、スロット、アクセシビリティなどを理解する必要があります。
Stencilの書き方だけを覚えても、Webコンポーネントとして良い部品を作れるとは限りません。まずWeb標準の仕組みを理解し、そのうえでStencilを使うことが重要です。
15. Stencil部品設計の注意点
Stencilで部品を作るときは、単に動くものを作るだけでは不十分です。公開プロパティ、イベント、メソッド、スロット、スタイル調整、アクセシビリティ、型定義、ドキュメント、バージョン管理まで考える必要があります。部品ライブラリは、一度公開すると多くの利用者が依存するため、変更の影響が大きくなります。
特にデザインシステムでは、部品の仕様が安定していることが重要です。プロパティ名やイベント名を頻繁に変えると、利用側の実装が壊れます。最初から完璧にする必要はありませんが、公開仕様として何を保証するのかを明確にする必要があります。
| 注意点 | 内容 |
|---|---|
| 公開仕様 | プロパティ・イベント・メソッドを安定させる |
| 命名規則 | 部品名やプロパティ名を統一する |
| アクセシビリティ | キーボード操作や支援技術対応を確認する |
| スタイル調整 | CSS変数などで安全に拡張できるようにする |
| ドキュメント | 利用方法と注意点を書く |
| 破壊的変更 | 変更時は移行方法を用意する |
| テスト | 表示・動作・アクセシビリティを確認する |
15.1 公開仕様を小さく保つ
部品の公開仕様は、小さく保つほうが管理しやすくなります。プロパティ、イベント、メソッド、スロットを増やしすぎると、利用者にとって分かりにくくなり、保守も難しくなります。
公開仕様を決めるときは、「この部品の本来の役割は何か」を考えます。役割から外れる機能を詰め込みすぎると、部品が肥大化します。必要なら、複数の小さな部品に分けることも検討します。
15.2 アクセシビリティを最初から考える
UI部品は、多くの画面で使われます。そのため、部品レベルでアクセシビリティを考えることが重要です。ボタン部品、入力部品、モーダル、タブ、メニューなどは、キーボード操作、フォーカス管理、適切なラベル、支援技術対応が必要です。
後からアクセシビリティを追加しようとすると、構造を大きく変更しなければならない場合があります。Stencil部品を作る段階で、意味のあるHTML、適切な属性、キーボード操作を設計することが大切です。
15.3 ドキュメントを用意する
部品ライブラリでは、ドキュメントが非常に重要です。どのプロパティを使えるのか、どのイベントが発火するのか、どのスロットに何を入れるのか、どのCSS変数で調整できるのかを説明する必要があります。
ドキュメントがない部品は、利用者がソースコードを読まなければ使えません。これは導入コストを高めます。部品の品質は、実装だけでなく、利用方法の分かりやすさも含みます。
16. WebコンポーネントとStencilの今後
Web開発では、フレームワークが変化し続けています。React、Angular、Vue、Svelteなど、それぞれに強みがあります。しかし、企業内のUI資産を長期的に保つには、特定フレームワークだけに依存しない考え方も重要です。WebコンポーネントとStencilは、その選択肢の一つです。
今後も、Web標準の進化とともに、Webコンポーネントの活用範囲は広がる可能性があります。特にデザインシステム、複数プロダクト展開、埋め込み部品、長期運用される企業UI基盤では、Stencilのような道具が役立つ場面があります。
16.1 デザインシステムでの重要性
デザインシステムは、単なるデザイン資料ではなく、実装可能な部品として提供されることが重要です。StencilでWebコンポーネントを作れば、デザインルールを実際のUI部品として配布できます。これにより、デザインと実装のずれを減らせます。
複数の開発チームが同じ部品を使えば、UIの一貫性が高まります。これは、ユーザー体験の安定だけでなく、開発効率や保守性にもつながります。
16.2 フレームワーク移行への備え
企業では、数年ごとにフロントエンド技術が変わることがあります。ある時期はAngular、別の時期はReact、新しいプロジェクトではVueというように、技術が混在することもあります。このとき、UI部品が特定フレームワークに強く依存していると、移行コストが高くなります。
Webコンポーネントとして部品を作っておけば、フレームワーク移行時にもUI資産を再利用しやすくなる可能性があります。もちろん完全に移行コストがなくなるわけではありませんが、選択肢を広げることができます。
16.3 標準技術を理解する価値
Stencilを使う場合でも、Webコンポーネントの標準技術を理解することは重要です。カスタム要素、シャドウDOM、スロット、属性とプロパティ、イベント、アクセシビリティの基本が分かっていれば、Stencilの設計判断もしやすくなります。
道具だけを覚えるのではなく、その出力先であるWeb標準を理解することが、長期的に強いフロントエンド開発につながります。Stencilは、Web標準を実務で扱いやすくするための道具として位置づけると分かりやすいです。
おわりに
WebコンポーネントをStencilで作るとは、ブラウザ標準に基づく再利用可能なUI部品を、TypeScriptやJSXに近い書き方で効率よく開発することです。Stencilは、開発時には便利な部品開発の仕組みを提供し、最終的には標準的なWebコンポーネントとして出力します。そのため、複数のフレームワークや複数のプロジェクトで使えるUI部品を作りたい場合に有効です。
Stencilの中心には、部品を明確な公開仕様として設計する考え方があります。外部から渡す値はプロパティ、内部で変化する値は状態、外部へ知らせる変化はイベント、必要な命令的操作はメソッド、外部から内容を差し込む場所はスロットとして整理します。これらを適切に設計することで、使いやすく保守しやすい部品ライブラリを作れます。
ただし、Stencilはすべてのプロジェクトに必要なものではありません。単一フレームワークで完結する小規模なアプリでは、そのフレームワークの部品として作るほうが自然な場合もあります。Stencilが特に力を発揮するのは、デザインシステム、企業内共通UI、複数フレームワーク対応、埋め込み部品、長期的に保守したいUI資産の開発です。WebコンポーネントとStencilを正しく理解すれば、フロントエンド開発における部品設計の選択肢を大きく広げられます。
EN
JP
KR