コンテンツにスキップ

サーバーアイランド

サーバーアイランドは、ページ全体のパフォーマンスを犠牲にせず、動的またはパーソナライズされた”アイランド”を個別にオンデマンドでレンダリングできます。

これにより、訪問者はページの最重要部分をより早く表示でき、メインコンテンツはより積極的にキャッシュできるため、パフォーマンスが向上します。

サーバーアイランドコンポーネント

Section titled “サーバーアイランドコンポーネント”

サーバーアイランドは、通常のサーバーレンダリングされたAstroコンポーネントであり、そのコンテンツが利用可能になるまでレンダリングを遅延させるよう指示されます。

ページは、プレースホルダーとして指定されたフォールバックコンテンツを含め、すぐにレンダリングされます。その後、コンポーネント独自のコンテンツがクライアント側で取得され、利用可能になった時点で表示されます。

インストール済みのアダプターで遅延レンダリングを実行する場合、ページ内の任意のコンポーネントにserver:deferディレクティブを追加すると、そのコンポーネントを独立したアイランドにできます。

src/pages/index.astro
---
import Avatar from '../components/Avatar.astro';
---
<Avatar server:defer />

これらのコンポーネントは、アダプターを使用することで、コンテンツの取得やCookieへのアクセスなど、オンデマンドレンダリングページで通常行えることがすべて可能です。

src/components/Avatar.astro
---
import { getUserAvatar } from '../sessions';
const userSession = Astro.cookies.get('session');
const avatarURL = await getUserAvatar(userSession);
---
<img alt="User avatar" src={avatarURL} />

サーバーアイランドへのpropsの受け渡し

Section titled “サーバーアイランドへのpropsの受け渡し”

サーバーアイランドコンポーネントに渡すpropsはシリアライズ可能でなければなりません: つまり、ネットワーク経由での転送や保存に適した形式に変換できる必要があります。また、Astroはすべてのシリアライズ可能なデータ構造をシリアライズするわけではありません。そのため、サーバーアイランドにpropsとして渡せるものにはいくつかの制限があります。

特に、関数はシリアライズできないため、server:deferが付いたコンポーネントには渡せません。循環参照を持つオブジェクトもシリアライズできません。

以下のprop型がサポートされています: プレーンオブジェクト、numberstringArrayMapSetRegExpDateBigIntURLUint8ArrayUint16ArrayUint32Array、および Infinity

サーバーアイランドのフォールバックコンテンツ

Section titled “サーバーアイランドのフォールバックコンテンツ”

server:defer属性を使ってコンポーネントのレンダリングを遅延させる場合、組み込みの"fallback"という名前のスロットを使って、デフォルトの読み込みコンテンツを”スロット挿入”できます。

フォールバックコンテンツは、ページ読み込み時に他のコンテンツと一緒にレンダリングされ、コンポーネントのコンテンツが利用可能になったときに置き換えられます。

フォールバックコンテンツを追加するには、サーバーアイランドコンポーネントに渡す子コンポーネントやHTML要素にslot="fallback"を指定します。

---
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
<GenericAvatar slot="fallback" />
</Avatar>

フォールバックコンテンツの例は次の通りです。

  • ユーザー固有のアバターの代わりの汎用アバター
  • カスタムメッセージなどのプレースホルダーUI
  • スピナーなどの読み込みインジケーター

サーバーアイランドの実装は、主にビルド時に行われ、コンポーネントのコンテンツが小さなスクリプトに置き換えられます。

server:deferが付いた各アイランドは、専用の特別なルートに分割され、実行時にスクリプトが取得します。Astroがサイトをビルドすると、コンポーネントは省略され、代わりにスクリプトとslot="fallback"でマークされたコンテンツが注入されます。

ブラウザでページが読み込まれると、これらのコンポーネントは特別なエンドポイントにリクエストされ、HTMLが返されます。このため、ユーザーはページの最重要部分を即座に表示できます。フォールバックコンテンツは短時間表示され、その後、動的アイランドが読み込まれます。

各アイランドは他と独立してロードされます。つまり、遅いアイランドがあっても、他のパーソナライズされたコンテンツの表示を遅らせることはありません。

このレンダリングパターンは、あらゆるホスティング環境で動作するように設計されています。Node.jsサーバー(Dockerコンテナ内)から任意のサーバーレスプロバイダーまで、サーバーインフラに依存しません。

サーバーアイランドのデータは、URLクエリ内の暗号化された文字列としてpropsを渡すGETリクエストで取得されます。これにより、標準のCache-ControlHTTPヘッダーを使用して、Cache-Controlディレクティブによるデータキャッシュが可能です。

ただし、ブラウザにはURL長の実用的な上限(2048バイト)が存在します。この制限を超えると、Astroは代わりにprops全体を本文に含めたPOSTリクエストを送信します。

POSTリクエストはデータ送信用に使われ、データの完全性やセキュリティ上の理由からブラウザによってキャッシュされません。そのため、プロジェクト内の既存のキャッシュロジックは動作しなくなります。可能な限り、必要最小限のpropsのみをサーバーアイランドに渡し、クエリサイズを小さく保つようにしてください。

サーバーアイランド内でページURLにアクセスする

Section titled “サーバーアイランド内でページURLにアクセスする”

通常、サーバーアイランドコンポーネントは、他のコンポーネントと同じようにpropsを渡すことで、レンダリングするページに関する情報を取得できます。

しかし、サーバーアイランドはページリクエストの外側にある独立したコンテキストで実行されます。そのため、サーバーアイランドコンポーネント内でのAstro.urlAstro.request.urlは、現在のブラウザのページURLではなく、/_server-islands/AvatarのようなURLを返します。さらに、ページをプリレンダリングしている場合、クエリパラメーターなどの情報にアクセスできないため、propsとして渡せません。

ページURLの情報を取得するには、Refererヘッダーを確認できます。これには、ブラウザでアイランドを読み込んでいるページのアドレスが含まれています。

---
const referer = Astro.request.headers.get('Referer');
const url = new URL(referer);
const productId = url.searchParams.get('product');
---

Astroはサーバーアイランドに渡されるpropsを暗号化するために暗号学を使用し、機密データが誤って露出するのを防いでいます。この暗号化はビルドごとに生成される新しいランダムな鍵に依存しており、その鍵はサーバーバンドルに埋め込まれます。

ほとんどのデプロイホストでは、フロントエンドとバックエンドの同期は自動的に処理されます。ただし、ローリングデプロイ、マルチリージョンホスティング、またはサーバーアイランドを含むページをキャッシュするCDNを使用している場合は、固定の暗号化キーが必要になることがあります。

ローリングデプロイ環境(例:Kubernetesなど)では、(propsを暗号化する)フロントエンドアセットと、(propsを復号化する)バックエンド関数が一時的に異なるキーを使用している可能性があります。また、CDNが古いキーでビルドされたページを配信し続けている場合もあります。このような状況では、サーバーアイランドに渡された暗号化済みpropsを復号化できなくなります。

このような状況では、Astro CLIを使用して、再利用可能なエンコード済み暗号化キーを生成し、ビルド環境の環境変数として設定してください。

ターミナルウィンドウ
astro create-key

この値を使ってASTRO_KEY環境変数を設定し(例:.env ファイル内など)、CI/CDやホストのビルド設定にも含めてください。これにより、生成されるバンドルで常に同じキーが再利用され、暗号化と復号化の同期が保たれます。

貢献する コミュニティ スポンサー