最近、私は最初の Web コンポーネントを構築する方法に関する記事と、基本的な v1 Web コンポーネント仕様の歴史と説明に関する記事を書きました。しかし、2020 年に v1 が完全にサポートされて以来、Web Components の世界はさらに多くの変化を遂げました。未来にはさらに多くの計画があります。現在の標準を使用して構築された注目すべき例をいくつか見てみましょう。また、2023 年以降に登場する新しい Web Components 標準の作業についても調査します1。
Web Components のアプリケーション例#
すべてのブラウザが v1 Web Components をサポートする中で、多くの企業がこれらの新しい標準を採用し、重要なビジネスを構築しています。以下は、私が注目すべきだと思ういくつかの例です。
YouTube#
YouTube は、Web Components 技術を最初に採用したアプリケーションの一つであり、長年にわたりこの技術を使用してインターフェースを構築しています。ソースコードを確認すると、ytd-video-preview
から iron-ally-announcer
までのさまざまなカスタム要素が見られます。
Photoshop#
はい、Adobe は Lit を使用して Photoshop をブラウザに持ち込みました。現在はベータ版で、Adobe のサブスクリプションユーザーであれば自分で試すことができます。アプリケーション全体には、アプリケーションのルートを構成する psw-app
から、psw-layers-panel
のようなシェル要素、sp-action-button
のような UI コンポーネントまで、多くのカスタム要素があります。
MSN、Edge、Bing、VS Code、そして Microsoft のその他#
数年前、Microsoft は FAST に基づく Web Components を使用して MSN を再構築しました。これにより、パフォーマンスが 30% から 50% 向上し、以前の React を使用して構築されたバージョンよりも優れたパフォーマンスを実現しました。
OpenAI に基づく New Bing も FAST Web Components を使用して構築されており、以下のスクリーンショットは最近その開発者の一人によって共有されました。
VS Code の新機能を拡張するための Webview UI ツールキットも FAST Web Components を使用して構築されています。
過去 3 年間で、Microsoft では約 1,500 のチーム / プロジェクトが FAST Web Components を採用しました。
Salesforce#
顧客関係管理(CRM)、販売およびマーケティング自動化プラットフォーム業界で最大のブランドの一つである Salesforce は、長年にわたり Lightning Web Components に基づいて開発を行っています。
SpaceX#
現在、Web Components は宇宙でも使用されています。SpaceX の乗組員ディスプレイは Chromium を実行しており、Web Components を広く使用しています。
標準の現状#
Web 標準は進化し続けており、その中には Web Components も含まれています。v1 バージョンがすべての主要ブラウザにリリースされてからの 3 年間で、Web Components の下での機能の数はほぼ倍増しました。以下は、さまざまな公開済み、進行中、計画中の Web Components に関連する標準の図示です。
図示された機能に基づいて、6 つの高レベルのカテゴリを一つずつ見ていきましょう:組み合わせとスコープ、プラットフォームの相互運用性、レンダリングとパフォーマンス、スタイル、パッケージと配布、API パラダイム。
組み合わせとスコープ#
Web コンポーネントのスコープ / カプセル化機能は、従来のプログラミングにおける情報隠蔽、メンテナンス、コードベースの拡張性などにとって非常に重要です。しかし、Web Components に関しては、HTML と CSS のランタイムに追加のメタデータを提供し、描画とレイアウトの最適化に利用できるという利点もあります。
Shadow DOM
Shadow DOM は、スコープ、カプセル化、DOM および関連スタイルの組み合わせのための HTML の基本的なメカニズムです。これは多面的な機能であり、さまざまな拡張可能な能力を持っています。
-
名前付きスロット割り当て(完全サポート)—— 元の v1 Shadow DOM 仕様は、Shadow DOM 内で名前付きの
<slot>
要素を使用して要素の組み合わせのプレースホルダーを定義するための完全に宣言的なメカニズムを提供します。開発者はホスト要素の任意の子要素にslot
属性を配置するだけで、ブラウザは自動的にその要素の表示出力をスロットの位置に「挿入」します。 -
オープンおよびクローズドモード(完全サポート)—— v1 Shadow DOM 仕様の attachShadow() API の
mode
オプションはその一部です。これにより、コンポーネント開発者は好みのカプセル化モードを選択できます。open
モードはホスト要素の外部からshadowRoot
にアクセスを許可し、closed
モードはアクセスを禁止します。 -
イベントのリダイレクト(完全サポート)—— Shadow DOM 内の要素でイベントがトリガーされると、これらのイベントは「リダイレクト」され、ホスト Shadow DOM から発生したように見えます。この v1 Shadow DOM 仕様の機能は、内部構造を正しくカプセル化するための重要な部分です。
-
手動スロット割り当て(完全サポート)——
slot
要素の新しい assign API は、v1 の元のスロット割り当て機能を拡張し、以前の宣言的スロットメカニズムに加えて、命令的 API を提供します。 -
フォーカス委譲(完全サポート)—— この v1 以降の機能により、Shadow DOM はブラウザに対して、ホスト要素がフォーカスを取得したときに、特定の要素にフォーカスを委譲すべきであることを通知できます。デフォルトでは、最初のフォーカス可能な要素が選択されますが、
autofocus
属性を使用してこの動作を上書きできます。 -
Cross-root ARIA(合意に近い)—— 近づいている機能で、コミュニティとブラウザベンダーの間で合意に達しつつあるCross-root ARIAは、Shadow DOM の外部と内部の ARIA 重要要素を関連付ける操作を大幅に簡素化します。たとえば、Shadow DOM の外部の
label
要素を Shadow DOM 内部のinput
要素に関連付けることができます。この種の ARIA シナリオには、現在すでに解決策がありますが、実装は容易ではありません。Cross-root ARIA はこの状況を大幅に改善します。 -
Shadow CSS でのカスタムプロパティの使用(合意)—— 現在、一部のブラウザは@property 構文を使用して CSS プロパティをカスタマイズできます。しかし、現在のところ、Shadow DOM では機能していません。CSS オブジェクトモデルは常にカスタム要素コードからこれらのプロパティをグローバルに定義できますが、Shadow DOM で宣言形式でこの機能を提供することは常識的な改善です。これは合意に達しており、私たちはこの機能をすぐに見ることができることを期待しています。ブラウザが新しい CSS 構文をより広くサポートするにつれて。
スコープ要素登録簿(合意)
カスタム要素の v1 仕様では、すべての要素が customElements
グローバルオブジェクトを介してグローバルカスタム要素登録簿に登録されます。この新しい補完機能により、非グローバル登録簿をインスタンス化し、その中にカスタム要素を登録できるようになります。
const myRegistry = new CustomElementRegistry();
myRegistry.define("my-element", MyElement);
この登録簿内の要素は、その登録簿に割り当てられた Shadow DOM としてのみ定義されます。これはブラウザ内のスコープを大幅に改善し、必要に応じて各シャドウルートに要素を定義できるようにします。これがブラウザに適用されると、これは大きな進歩となり、新しいアーキテクチャの可能性を開くことになります。現在、コミュニティとベンダーの間で合意が得られており、Chromium は最初の実装を開発しています。
プラットフォームの相互運用性#
Web Components の最も重要な側面の一つは、コンポーネントとプラットフォーム間で相互運用性を実現する方法です。現在および将来の機能をいくつか見てみましょう。
カスタム要素
-
自治カスタム要素(完全サポート)—— Web Components v1 のこのコア機能は、
customElements
グローバルオブジェクトにクラスを登録することによってHTMLElement から継承されたカスタム要素を定義します。基本的なライフサイクルコールバックとプロパティの監視も仕様の一部です。 -
カスタム組み込み要素(拒否)—— 当初、組み込み要素(たとえば
HTMLParagraphElement
)から継承することを許可する提案がありましたが、WebKit の実装者は複数の技術的問題を発見したため、この仕様は拒否されました。将来的には削除される可能性が高いため、使用を避けるべきです。より良い代替案については、以下の「カスタムプロパティ」を参照してください。
Element Internals
v1 以降の新しい API、ElementInternals
により、カスタム要素は既存の DOM サブシステムとプラットフォームレベルで統合することができます。
-
Shadow Root アクセス(完全サポート) —— このシンプルな機能追加により、コンポーネント開発者は
closed
モード要素の Shadow Root インスタンスを取得できます。この機能がなければ、closed
モードの宣言的 Shadow DOM を持つ要素は、実行時にそのルートノードにアクセスできません。 -
フォームに関連付けられたカスタム要素(完全サポート) —— この重要な新機能により、カスタム要素はフォームに完全に参加することができます、フォームの検証、送信、リセットを含みます。
-
デフォルトのアクセシビリティロール、状態、およびプロパティ(大部分がサポート) —— この新しい API セット により、カスタム要素のデフォルトのアクセシビリティ特性を、ホスト要素上の外部プロパティを通じてではなく、内部でプラットフォームと直接通信することによって設定できます。現在、Firefox を除くすべての主要ブラウザがこの新しい API をサポートしています。Firefox では、ポリフィルが提供されています。Firefox はすでに
ElementInternals
の他の部分の API を実装しているため、近い将来にこの機能をリリースしない場合、私は驚くでしょう。
組み合わせ選択(合意 / 無仕様)
この改善は、Selection オブジェクトの新しい getComposedRange()
API を提案し、範囲の開始と終了が複数の Shadow Root を跨ぐことを可能にします。また、ブラウザがこれらの状況を処理する際の一貫性を向上させます。この API 草案には広く合意がありますが、ブラウザが実装できるようになる前に、完全な仕様が必要です。Web Component の通常の開発プロセスでは、この状況に遭遇することはあまりありません。主にリッチテキストエディタの実装に関係しています。
カスタムプロパティ(確定)
この機能は必ずしも Web Components の一部ではありませんが、Web Components がサービスを提供するシナリオと高い重複があります。この草案は、HTML 要素に追加できる再利用可能な動作の作成を有効にすることを提案しています。たとえば、Material Design の水波紋効果を任意の HTML 要素に適用したい場合、これを実現するのは素晴らしいことではないでしょうか?
<button material-ripple>Click Me</button>
私が TPAC 2022 のために準備した草案提案では、この機能のプログラミングモデルがどのようになるかを示しました:
class MaterialRipple extends Attr {
// ownerElement inherited from Attr
// name inherited from Attr
// value inherited from Attr
// ...
connectedCallback () {
// ownerElement が DOM に接続されたときに呼び出される
// または属性がすでに接続されたオーナーに追加されたとき
}
disconnectedCallback () {
// ownerElement が DOM から切断されたときに呼び出される
// または属性が接続されたオーナーから削除されたとき
}
attributeChangedCallback() {
// この属性の value プロパティが変更されたときに呼び出される
}
}
customAttributes.define("material-ripple", MaterialRipple);
このモデルとライフサイクルが Web Components と一致していることに気付くでしょう。これは、拒否されたカスタム組み込み要素提案の is
属性に対して、より良く、より堅牢な代替案を提供します。
レンダリングとパフォーマンス#
レンダリングとパフォーマンスは Web Components にとって非常に重要です。基本的な機能はすでに整っていますが、これは依然として活発な探求、議論、未来の革新の分野です。
HTML テンプレート要素(完全サポート)
HTMLTemplateElement
とその遅延 HTML コンテンツを定義する能力は、v1 Web コンポーネント機能の重要な部分です。この要素が導入される前は、ブラウザによってアクティブ化されない HTML を宣言する方法がなかったため、需要に応じて同じ HTML を再描画する必要があるコンポーネントを作成するのが非常に困難でした。
宣言的 Shadow DOM(大部分がサポート)
Shadow DOM の v1 仕様では、attachShadow()
JavaScript API を介してのみ Shadow Root を作成することが許可されていました。この Shadow DOM の新たな強化機能により、JavaScript を使用せずに HTML 内で完全に Shadow DOM コンテンツを宣言できるようになり、サーバーフレームワークに興味深い可能性を提供します。
<host-element>
<template shadowrootmode="open">
<slot></slot>
</template>
<h2>Light content</h2>>
</host-element>
この仕様は template
要素を再利用しています。これを混同しないでください。これはテンプレートではなく、HTML パーサーが Shadow Root に流入するアクティブな DOM です。
現在、Firefox を除くすべてのブラウザが宣言的 Shadow DOM をサポートしています。 必要に応じて、この機能は数行の JavaScript コードでポリフィルできます。
子ノード変更コールバック関数(提案)
Web Components にはカスタム要素の v1 仕様に明確に定義されたライフサイクルがありますが、将来的にこのライフサイクルを拡張できないわけではありません。開発者にとって一般的な課題の一つは、Web Component が子ノードの追加または削除に応答できるようにすることです。現在は slotchange イベント と MutationObserver を使用してこれを実現できますが、childrenChangedCallback()
のようなライフサイクルコールバック関数があれば、より良いパフォーマンス、簡素化、および HTML パーサー自体との統合を提供できます。現在、草案提案があり、実装者も興味を示しています。この機能を次の段階に進めるためには、完全な提案が必要です。
テンプレートインスタンス化
HTML にはテンプレートがありますが、データに接続されたテンプレートをインスタンス化し、関連データが変更されたときにそれらを更新するメカニズムはまだありません。この「テンプレートインスタンス化」の分野には、いくつかの独立した価値のある部分があります。
- DOM 部品(提案) - この提案は、DOM ツリーの特定の位置にコンテンツを挿入または置き換えるための標準メカニズムを提供します。これは、より効率的なテンプレートエンジンを作成し、既存の Web Component ライブラリや JavaScript フレームワークを一括更新するのを助けるための低レベルのイネーブラーと見なすことができます。これは、応答性の解決策やテンプレート構文を提供するものではなく、DOM 部分を定位して更新するための低レベルの標準インフラストラクチャを提供します。
- テンプレート構文(確定) - 一度定位と一括更新の低レベルのインフラストラクチャが整い、既存のライブラリで成功裏に使用されると、構文に関する大きな議論が始まります。テンプレート構文は非常に議論の余地がある問題ですが、HTML にはこの問題を処理するための基本的な言語が必要であることが認識されています。たとえそれが他のライブラリにコンパイルターゲットを提供するだけであっても。
- 応答性(確定) - DOM 部品は、DOM を一括更新するための標準メカニズムを提供します。テンプレート構文は、DOM 部分を作成するための宣言的メカニズムを提供します。残るのは、DOM 部品の更新をいつ実行すべきかを決定するメカニズムです。これが応答性の役割であり、全体像を完成させるのです。これは別の議論の余地がある問題ですが、Web Components の
attributeChangedCallback()
などの先例がいくつかあります。このテーマにはさらなる探求が必要です。
テンプレートインスタンス化の作業カテゴリは、上記の 3 つのサブ機能に分解され、まずは議論の余地が少ない問題を解決し、既存のライブラリやフレームワークがあまり主観的でない、パフォーマンスを改善する機能を利用できるようにすることを目指しています。
スタイル#
Shadow DOM はスタイルのカプセル化を提供しますが、Web Components に直接関連し、日常的に非常に重要な多くの CSS 特性があります。
使用
現在および将来のいくつかの標準は、Web Components がスタイルを使用して Shadow DOM の表示を作成する方法に関連しています。Shadow DOM 内でスタイル要素を作成することは常に可能でしたが、新しい標準は可読性とパフォーマンスの利点を提供します。
- 構築可能なスタイルシート(完全サポート) — 実際、この標準の前には
CSSStyleSheet
インスタンスを作成することができませんでした。この標準はこの問題を修正し、今ではnew CSSStyleSheet()
と書くことができます。この能力により、Web Components 内でスタイルをより動的に作成および使用することが可能になり、コンポーネント間でスタイルシートを共有することもできます。 - 採用スタイルシート(完全サポート) — 特定の
CSSStyleSheet
インスタンスをどのように特定の Shadow Root またはグローバル document に関連付けるか?この新しい標準は、document
とすべての Shadow Root インスタンスにadoptedStyleSheets
配列を追加します。スタイルシートをその配列にプッシュするだけで、使用を開始できます。 - CSS モジュールスクリプト(Chromium) — 構築可能なスタイルシートと採用スタイルシート自体は、ドキュメントスタイルを作成、共有、および関連付けるための原始的なメカニズムを提供しますが、依然として JavaScript で CSS コードを書く必要があります。CSS モジュールスクリプト標準は、JavaScript モジュールを使用して
.css
ファイルをインポートできるようにし、プラットフォームが自動的にCSSStyleSheet
インスタンスを作成します。これにより、CSS ランタイムと JavaScript ランタイムの間を行き来する必要がなくなります。 - 宣言的 CSS モジュール(確定) — 宣言的 Shadow DOM と採用スタイルシートの出現に伴い、宣言 CSS モジュールを作成し、宣言的 Shadow DOM に関連付けるためのいくつかの一時的な提案が作成されました。この分野にはさらなる探求が必要ですが、HTML と CSS の未来にとって興味深い可能性があります。
レンダリング
主に、CSS はレンダリングに関する問題に焦点を当てています。いくつかの標準が Web Components のスタイル設定の可能性を拡張しています。
Web Components に限らず、コンポーネントシステムを作成するためにカスタム CSS プロパティは非常に重要な仕様であり、ローカル CSS 変数を作成し、shadow roots 内で使用できます。
- CSS Shadow Parts(完全サポート) — CSS 部分は、Shadow DOM 内で要素を「部分」として宣言し、外部セレクタでスタイルを設定できるようにします。これは、
part
属性と the exportparts 属性 を使用して、ネストされたシナリオで実現されます。 - CSS カスタムステータス(Chromium) — ネイティブ要素は、CSS セレクタで使用できるカスタムステータスを持つことができます。たとえば、チェックボックスの「選択済み」と「未選択」状態。この新機能により、Web Components は独自の状態を定義できます。合意に達しており、Chromium は最初の実装をリリースしました。
ElementInternals
を介してアクセスできます。他のブラウザが追随するのを待つ間、ポリフィルを使用してサポートできます。 - CSS テーマ(提案) — CSS カスタムプロパティと CSS Shadow Parts を慎重に使用することで豊富なテーマを実現できますが、テーマの概念を CSS に明示的に導入することでこのプロセスを簡素化し、改善できます。
- オープンな Shadow Root スタイル(確定) — 構築可能なスタイルシートと採用スタイルシートを使用して、任意のグローバル CSS を Shadow Root で共有できますが、一般的な Web 開発者にとっては直感的なプロセスではないかもしれません。外部 CSS を特定の shadow roots に明示的に選択して許可する方法を探るメカニズムがいくつかあります。
パッケージと配布#
これまで、私たちは主に Web Components の実装に関連する標準について話してきました。しかし、コンポーネントがどのようにパッケージ化され、ロードされるかを考慮することも同様に重要です。
カスタム要素の遅延ロード(提案)
現在、グローバルな customElements
登録簿を使用してコンポーネントを定義できますが、すぐにカスタム登録簿を使用できるようになります。しかし、これらのいずれの場合も、コンポーネントを定義する前に、その実装がロードされている必要があります。カスタム要素の遅延ロードを使用すると、開発者は要素に関する情報をプラットフォームに伝えられますが、要素が最初に document に表示されるまでロードを遅延させることができます。これは次のように機能する可能性があります:
customElements.defineLazy(
"my-element",
async () => (await import("my-element.js")).default
);
この仕様は、特に特定のアーキテクチャにとって良いものであると大多数の人に考えられています。しかし、提案の詳細はまだ議論中です。
HTML モジュールスクリプト(確定)
HTML モジュールスクリプトは、CSS モジュールスクリプトの HTML 等価物です。HTML モジュールスクリプト提案により、テンプレート(および他の HTML 断片)は、JS モジュールシステムを介して直接インポート可能になります。現在、草案提案が一つあるだけで、多くの詳細についてさらに議論が必要ですが、これは重要な長期的な強化機能と見なされています。特に、将来的に単一の HTML ファイルのみの Web Components が存在する可能性を考慮すると。
API パラダイム#
最後の標準カテゴリは、私が以前に議論したすべての内容とは少し異なります。これらの標準は、Web Components の基本的なプログラミングパラダイムに関係しています。Web Components v1 は主に命令的な JavaScript プログラミングモデルです。宣言的な slot 割り当てのような注目すべき例もいくつかありますが、基本的には完全に命令的です。v1 以来、私たちはますます多くの宣言的機能を導入する努力を続けています。その良い例の一つが宣言的 Shadow DOM です。全体として、すべてのシナリオに対して宣言的および命令的な API を提供することが最善です。しかし、最終的な目標は、サーバーがブラウザに要素定義を送信できるようにする、完全に宣言的に定義された Web Components を持つことです。noscript コンテキストで完全に機能することができます。私たちはまだ道のりがありますが、そこに到達したとき、それはクライアントとサーバーの開発を根本的に変えるでしょう。
次のステップは何か#
標準の作業は常に進行中です。実際、今日から W3C Web コンポーネントコミュニティグループは 2023 年春の対面イベントを開催しています。TPAC と同様に、これはライブラリの作者、コンポーネントの作成者、ブラウザベンダーなどが集まり、合意が必要な仕様の詳細や未解決の問題に専念する機会です。私は、今後のブログ記事でイベントの結果を皆さんに更新することを楽しみにしています。更新を受け取るためにフォロー / 購読してください 😄
まとめ#
私は、この Web Components 標準の旅があなたにとって意味のあるものであったことを願っています。私たちがどれだけ進んできたか、未来に何が待っているかを見るのは興味深いことです。v1 バージョンのリリースに伴い、過去数年で公開された機能は倍増し、今後のエキサイティングな新機能も待っています。今こそ、Web 開発者になる良い時期です。