Islands は Web Components ではない:似て見えて別物の「必要なときだけ読み込む」
Islands はビルド時にどこに JS が要るか・いつハイドレートするかを決めます。Web Components は実行時にブラウザへ自立した要素を渡します。混同すると道具を選び間違えます。
この 2 つの言葉は同じ段落によく現れ、どちらも「必要なときだけ読み込む仕組み」に見えます。実際は層が違います。片方はビルド成果物と読み込みのタイミング、もう片方はカプセル化と実行時を扱います。
Islands:ビルド時の分割とハイドレーションの時機
Astro の island はビルド時の概念です。操作を伴うコンポーネントは個別のチャンクに分かれ、ページの残りは素の HTML のままです。
<SearchBox client:idle />
<Comments client:visible />
client:idle と client:visible が決めるのはハイドレートの時機(メインスレッドが落ち着いたあと、ビューポートに入ったとき)です。ダウンロードするかどうかではありません。ハイドレート指示のないコンポーネントと、ページの静的な部分は JavaScript を 1 行も出しません。
Web Components:実行時の要素
カスタム要素はブラウザのプリミティブです。customElements.define('x-counter', ...) を登録すれば、マークアップの <x-counter> に挙動が付きます。Shadow DOM を使えばスタイルの分離も付いてきます。ビルドツールもフレームワークも要らず、どのページでも動きます。
ただし遅延読み込みの仕組みではありません。定義スクリプトは最初に読み込むか、どこかの時点で自分で import() するかです。<x-counter> を挿し込んでも、ブラウザがその定義を取りに行くことはありません。
では <my-counter> はなぜ island に見えるのか
描画結果が同じだからです。どちらもマークアップ上のカスタムタグです。違いは誰が生きた状態にするか。island はフレームワークがブラウザでマウント/ハイドレートして描画します。Web Component はブラウザがタグ名からレジストリを引いて解決します。前者はビルド成果物に、後者は読み込み済みの定義スクリプトに依存します。
このサイトが Web Components を使わない理由
2 つあります。まずスタイル。見た目の方向は :root のトークンで駆動していて、Shadow DOM をまたぐとカスタムプロパティの継承と ::part しか残らず、SCSS を直接書くより手間が増えます。次に役割分担。ここでの遅延読み込みは island で足りており、コンポーネント登録の仕組みをもう 1 つ足すと読み込み経路が 2 本に増えるだけです。
Web Components が本領を発揮するのはフレームワークをまたぐ再利用です。Vue のページ、古い jQuery の管理画面、他人の静的サイトの 3 か所に同じ部品を出したい場合や、ウィジェットを第三者ページに埋め込む場合です。
Islands はいつ読み込むかを決め、Web Components は誰が包むかを決める。同じページで両方使えます。

コメント
…