コンテンツにスキップ

オンデマンドレンダリング

Astroプロジェクトのコードはウェブに表示するためにHTMLとしてレンダリングされる必要があります。

デフォルトでは、Astroのページ、ルート、APIエンドポイントはビルド時に静的ページとして事前レンダリングされます。しかし、リクエストがあったときにサーバーで一部またはすべてのルートをオンデマンドレンダリングすることもできます。

オンデマンドレンダリングされたページやルートはアクセスごとに生成され、ユーザーごとにカスタマイズできます。たとえば、オンデマンドレンダリングされたページでログインユーザーのアカウント情報を表示したり、サイト全体を再ビルドせずに最新データを取得して表示したりできます。

リクエスト時にサーバーで行うオンデマンドレンダリングは**サーバーサイドレンダリング(SSR)**とも呼ばれます。

サーバーアダプター

任意のページをオンデマンドレンダリングするにはアダプターを追加します。アダプターは、Astroが特定のランタイム(NetlifyやCloudflareなど)上でプロジェクトを実行するスクリプトを出力できるようにします。ランタイムはリクエスト時にページを生成するサーバー環境です。

サイトが完全に静的でオンデマンドレンダリングを行わない場合でも、アダプターを追加する価値があります。たとえばNetlifyアダプターはNetlifyのImageCDNを有効にし、サーバーアイランドserver:deferを使うにはアダプターのインストールが必須です。

SSRアダプター

Astro公式アダプターはNode.jsNetlifyVercelCloudflare用が提供されています。公式およびコミュニティ製のアダプター一覧から、デプロイ環境 (EN)に合ったものを選んでください。

アダプターを追加する

Astroが保守する公式アダプター (EN)は、以下のastro addコマンドで追加できます。このコマンドはアダプターのインストールとastro.config.mjsへの設定変更を一度に行います。

例としてNetlifyアダプターをインストールする場合は、次のコマンドを実行します。

npx astro add netlify

アダプターを手動で追加 (EN)し、astro.config.mjsを自分で更新することもできます(例:@astrojs/netlify)。

アダプターによっては独自の設定が必要な場合があります。各アダプターのドキュメントを確認し、必要な設定をastro.config.mjsに追加してください。

オンデマンドレンダリングを有効にする

デフォルトではサイト全体が事前レンダリングされ、静的HTMLがブラウザに送信されます。たとえば、クッキーをチェックしてパーソナライズしたコンテンツを表示するページなど、サーバーレンダリングが必要なルートだけ事前レンダリングを無効化できます。

まず、オンデマンドレンダリングを有効にするためにアダプターを追加します。

次に、オンデマンドレンダリングしたいページやエンドポイントの先頭にexport const prerender = falseを追加します。その他のページは静的サイトのままです。

---
export const prerender = false
---
<html>
<!--
このコンテンツはリクエスト時にサーバーレンダリングされます!
サーバーランタイム用アダプターを追加するだけ!
他のページはビルド時に静的生成されます!
-->
<html>

以下は、事前レンダリングを無効にして、毎回ランダムな数値を返すエンドポイントの例です。

export const prerender = false;

export async function GET() {
  const number = Math.random();
  return new Response(
    JSON.stringify({
      number,
      message: `ランダムな数字はこちら:${number}`,
    }),
  );
}

'server'モード

動的なアプリの場合は、アダプターを追加したあとビルド出力をoutput: 'server'に設定すると、すべてのページがデフォルトでサーバーサイドレンダリングされます。これは、各ページで事前レンダリングをオフにするのと同じ効果です。

そのうえで、プライバシーポリシーや会社概要ページなど、サーバーを介さずともよいページだけを個別に事前レンダリングできます。

---
export const prerender = true
---
<html>
<!--
`output: 'server'`を設定していますが、このページは静的です!
他のページはオンデマンドレンダリングです!
-->
<html>

ページやルートを静的生成したい場合はexport const prerender = trueを追加します。

export const prerender = true;

export async function GET() {
  return new Response(
    JSON.stringify({
      message: `これは静的エンドポイントです`,
    }),
  );
}

:::tipまずはデフォルトの'static'モードで開始し、ほとんどのページ、または全ページをオンデマンドレンダリングしたいと確信できるまでモードを切り替えないことを推奨します。これにより、静的コンテンツをレンダリングするだけでサーバー関数を呼び出す必要がなくなり、パフォーマンスを最大限に引き出せます。

'server'モードは新しい機能を追加するものではなく、レンダリング方式のデフォルトを切り替えるだけです。:::

設定リファレンスのoutput設定 (EN)を参照してください。

オンデマンドレンダリングの機能

HTMLストリーミング

HTMLストリーミングでは、ドキュメントをチャンクごとに分割し、順に送信して描画します。Astroはオンデマンドレンダリング時にコンポーネント単位でストリーミングを行い、描画済みの部分をすぐにユーザーへ表示します。これによりHTMLを可能な限り速く表示できますが、大きなドキュメントの場合はネットワーク状況によってダウンロードが遅くなったり、データ取得待ちで描画がブロックされることがあります。

:::cautionResponseヘッダーを変更する機能はページレベルでのみ利用できます。コンポーネント(レイアウトを含む)内部では使用できません。コンポーネントコードが実行される時点ではResponseヘッダーはすでに送信されているため、変更できないからです。:::

クッキー

オンデマンドレンダリングされたページやAPIエンドポイントでは、クッキーの確認・設定・取得・削除ができます。

以下の例はページビューのカウンターとしてクッキー値を更新しています。

---
export const prerender = false; // 'server'モードでは不要

let counter = 0

if (Astro.cookies.has('counter')) {
  const cookie = Astro.cookies.get('counter')
  const value = cookie?.number()
  if (value !== undefined && !isNaN(value)) counter = value + 1
}

Astro.cookies.set('counter', String(counter))
---
<html>
  <h1>Counter = {counter}</h1>
</html>

Astro.cookiesAstroCookie型 (EN)についてはAPIリファレンスを参照してください。

Response

Astro.response (EN)は標準のResponseInitオブジェクトで、ステータスやヘッダーを設定できます。

次の例は商品が存在しない場合にステータスを設定しています。

---
export const prerender = false; // 'server'モードでは不要

import { getProduct } from '../api';

const product = await getProduct(Astro.params.id);

// 商品が存在しない
if (!product) {
  Astro.response.status = 404;
  Astro.response.statusText = 'Not found';
}
---
<html>
  <!-- ページ内容 -->
</html>

Astro.response.headers

Astro.response.headersでヘッダーを設定できます。

---
export const prerender = false; // 'server'モードでは不要

Astro.response.headers.set('Cache-Control', 'public, max-age=3600');
---
<html>
  <!-- ページ内容 -->
</html>

Responseオブジェクトを返す

オンデマンドレンダリングを使用するページでは、Responseオブジェクトを直接返すこともできます。手動で返すか、Astro.redirect (EN)を使用します。

---
export const prerender = false; // 'server'モードでは不要

import { getProduct } from '../api';

const product = await getProduct(Astro.params.id);

// 商品が存在しない
if (!product) {
  return new Response(null, {
    status: 404,
    statusText: 'Not found'
  });
}

// 販売終了
if (!product.isAvailable) {
  return Astro.redirect("/products", 301);
}
---
<html>
  <!-- ページ内容 -->
</html>

Request

Astro.requestは標準のRequestオブジェクトで、urlheadersmethod、ボディなどを取得できます。静的生成されないページで追加情報を取得する際に利用します。

Astro.request.headers

リクエストヘッダーはAstro.request.headersで取得します。これはブラウザのRequest.headersと同じくHeadersオブジェクトです。

---
export const prerender = false; // 'server'モードでは不要

const cookie = Astro.request.headers.get('cookie');
// ...
---
<html>
  <!-- ページ内容 -->
</html>

Astro.request.method

HTTPメソッドはAstro.request.methodで取得できます。ブラウザのRequest.methodと同様で、文字列で返されます。

---
export const prerender = false; // 'server'モードでは不要

console.log(Astro.request.method) // ブラウザ遷移時はGET
---

Astro.request (EN)について詳しくはAPIリファレンスを参照してください。

サーバーエンドポイント

サーバーエンドポイント(APIルートとも呼ばれます)は、src/pages/フォルダー内の.jsまたは.tsファイルからエクスポートされる特殊な関数です。オンデマンドのサーバーサイドレンダリングにおける強力な機能で、安全にサーバー上でコードを実行できます。

この関数はエンドポイントコンテキスト (EN)を受け取り、Responseを返します。

詳しくはEndpointsガイド (EN)を参照してください。

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