シリーズ目次 / 前章: 08. AstroのアイランドアーキテクチャとUIフレームワーク / 次章: 10. AstroのエンドポイントとActions
Table of contents
Open Table of contents
この章のねらい
ここまでのページは、すべてビルド時にHTMLを作る前提でした。ただ、ログイン状態の表示や在庫数のように、ビルド時点では決めようがない内容もあります。
そこで出てくるのがオンデマンドレンダリングと、その実行に要るアダプターです。
2つのレンダリング方式
Astroは既定で、すべてのページをビルド時に静的HTMLとして生成します。これに対し、リクエストが来てからサーバーでHTMLを組み立てる方式がオンデマンドレンダリング(いわゆるSSR、サーバーサイドレンダリング)です。
両者の性質を比べます。
| 観点 | 静的生成 | オンデマンドレンダリング |
|---|---|---|
| HTMLを作る時点 | ビルド時 | リクエスト時 |
| 表示速度 | 非常に速い | サーバー処理の分だけ待つ |
| 内容の鮮度 | ビルド時点で固定 | 常に最新 |
| 利用者ごとの出し分け | できない | できる |
| 必要なもの | ファイルを置ける場所 | 実行環境とアダプター |
| 運用コスト | 低い | 相対的に高い |
選ぶ基準はひとつ、ビルド時点で内容が決まるかどうかです。ブログ記事や製品紹介は静的生成、マイページやカートはオンデマンド。それだけです。
アダプターとは
オンデマンドレンダリングを行うには、アダプターが必要です。アダプターは、Astroが生成したサーバー処理を、実際の実行環境(Netlify、Vercel、Cloudflare、Node.jsサーバーなど)で動く形に変換する部品です。
環境ごとにサーバー関数の書式も使えるAPIも違うので、アダプターがその差を吸収します。要するに変換プラグです。
公式アダプターは次のとおりです。
| アダプター | 対象 |
|---|---|
@astrojs/node | 自前のNode.jsサーバー |
@astrojs/netlify | Netlify |
@astrojs/vercel | Vercel |
@astrojs/cloudflare | Cloudflare |
図にすると次のようになります。
導入はコマンド1つで、astro.config.mjs の更新まで自動で行われます。
npx astro add netlify
設定ファイルには次のような記述が追加されます。
import { defineConfig } from "astro/config";
import netlify from "@astrojs/netlify";
export default defineConfig({
adapter: netlify(),
});
ページ単位で切り替える
Astroの推奨は、既定の静的生成のままにしておき、必要なページだけをオンデマンドにするやり方です。ページファイルで次のように宣言します。
---
export const prerender = false;
const now = new Date();
---
<p>現在時刻: {now.toLocaleString("ja-JP")}</p>
prerender = false を書いたページだけがリクエスト時に生成され、他のページは静的なまま保たれます。
サイト全体をオンデマンドにする
大半のページが動的になることが確実なら、設定ファイルで一括指定できます。
export default defineConfig({
output: "server",
adapter: netlify(),
});
この場合は逆に、静的でよいページに export const prerender = true; を書きます。
公式ドキュメントは、まず既定の static から始めて、大半のページが動的になる確信が持てるまで待つよう勧めています。迷ったら静的のままです。
オンデマンドレンダリングで使える機能
オンデマンドのページでは、リクエストに関する情報を扱えるようになります。
リクエストを読む
---
export const prerender = false;
const method = Astro.request.method;
const userAgent = Astro.request.headers.get("user-agent");
---
Cookieを扱う
---
export const prerender = false;
const visits = Number(Astro.cookies.get("visits")?.value ?? 0) + 1;
Astro.cookies.set("visits", String(visits));
---
<p>{visits}回目の訪問です。</p>
get / set / has / delete が用意されています。
レスポンスを制御する
---
export const prerender = false;
Astro.response.status = 404;
Astro.response.headers.set("Cache-Control", "public, max-age=3600");
---
ステータスコードやキャッシュ制御ヘッダーを、ページごとに指定できます。
HTMLストリーミング
オンデマンドレンダリングでは、HTMLを細かく分割して順次送信できます。ページ全体の生成完了を待たずにブラウザが表示を始められるため、体感速度が上がります。特別な設定は不要で、Astroが自動的に行います。
サーバーアイランドという中間解
「ページのほとんどは静的でよいが、一部だけ動的にしたい」という場面では、ページ全体をオンデマンドにする前に、前章で触れたサーバーアイランド(server:defer)を検討してください。
---
import CartSummary from "../components/CartSummary.astro";
---
<h1>商品一覧</h1>
<!-- ここまでは静的HTMLとして高速に配信される -->
<CartSummary server:defer>
<p slot="fallback">カートを読み込み中…</p>
</CartSummary>
ページ本体は静的生成の速さを保ったまま、島の部分だけがサーバーで描画されます。動的にする範囲は最小に保つ。Astroを使う限り、これは最後まで効きます。
判断の流れ
| 状況 | 選択 |
|---|---|
| 内容がビルド時に確定する | 静的生成のまま(何もしない) |
| ページの一部だけ都度変わる | サーバーアイランド(server:defer) |
| ページ全体が利用者ごとに変わる | そのページに prerender = false |
| サイトの大半が動的 | output: "server" に切り替える |
| データだけ返したい | 次章のエンドポイントを使う |
要点
- Astroは既定で静的生成を行い、オンデマンドレンダリングは選択して使う。
- オンデマンドレンダリングにはアダプターが必要で、
astro add <name>で導入できる。 - 推奨は「静的のまま始めて、必要なページにだけ
prerender = falseを付ける」進め方である。 - オンデマンドのページでは
Astro.request、Astro.cookies、Astro.responseが使える。 - ページ全体を動的にする前に、サーバーアイランドで済まないかを検討する。
参考資料
- On-demand Rendering — Astro Docs
- Server Islands — Astro Docs
- Integrations Guide — Astro Docs
- Configuration Reference — Astro Docs
シリーズ目次 / 前章: 08. AstroのアイランドアーキテクチャとUIフレームワーク / 次章: 10. AstroのエンドポイントとActions