Skip to content
Cloud AI エンジニア入門ガイド
Go back

Astro 7.2の新機能:インクリメンタルビルドとセッション無効化

Astro 7.2 が2026年8月6日に出ました。マイナーリリースなので派手さはありませんが、ビルド時間とサーバーバンドルに効く変更が入っています。

このうち、上げたその日から効くのは後半の2つです。session: false は設定1行で済みますし、astro preview --background はコマンドに1語足すだけ。インクリメンタルビルドのほうは実験的で、CIのキャッシュ設定まで用意して初めて効いてきます。ページ数が数百程度なら、しばらく様子見でいいと思います。

Astroを触ったことがある方向けですが、出てくる用語はその都度説明します。

これまでの困りごとと、Astro 7.2で使える設定やコマンドを4行で対比したマップ

Table of contents

Open Table of contents

リリースの中身

セマンティックバージョニングどおり、既存のコードを壊す変更はありません。追加されたのは次の5つです。

変更点触る場所ひとことで言うと
インクリメンタルスタティックビルド(実験的)experimental.incrementalBuild変わっていないページの生成を飛ばす
コンテンツコレクションの digest 公開getCollection() の戻り値エントリが変わったかを1つの文字列で判定できる
セッション機能の無効化session: false使わないセッション機能をバンドルから外す
astro preview のバックグラウンド起動astro preview --backgroundプレビューサーバーを別プロセスで動かす
ロガーの相対パス指定logger.entrypoint./src/logger.js のように書ける

アップグレードは、公式のアップグレード手順にあるとおり、専用のコマンドを使うのが推奨されています。Astro本体と公式インテグレーションをまとめて更新してくれます。

npx @astrojs/upgrade        # npm
pnpm dlx @astrojs/upgrade   # pnpm
yarn dlx @astrojs/upgrade   # Yarn

パッケージマネージャーから直接更新することもできます。

npm install astro@latest
pnpm add astro@latest
yarn add astro@latest

yarn upgrade --latest を使う手順を見かけますが、これはYarn 1系(Classic)のコマンドです。Yarn 2以降(Berry)では動かないため、バージョンを明示する yarn add astro@latest を使うのが確実です。

実験的機能:インクリメンタルスタティックビルド

Astro 7.2の目玉は、実験的なインクリメンタルスタティックビルドです。「インクリメンタル(incremental)」は「差分の」「積み増しの」という意味で、要するに前回のビルド結果を再利用して、変わっていない分の作業を省く仕組みです。

フルビルドの重さ

Astroの標準的な使い方である静的サイト生成(SSG: Static Site Generation)では、astro build を実行するたびに、サイト内の全ページのHTMLをゼロから作り直します。記事が50本ならたいした時間はかかりませんが、5,000本あると話は変わります。1本の誤字を直しただけでも、残りの4,999本を作り直すことになるからです。

インクリメンタルビルドは、作り直さなくてよかったページを見つけてスキップします。

18ページのサイトで記事を1本だけ直したときの、作業量の差です。

18ページのうち、フルビルドでは全ページを、インクリメンタルビルドでは変わった1ページだけをレンダリングする様子を色分けで対比した図

有効にする

実験的機能なので、設定ファイルでフラグを立てて有効にします。

import { defineConfig } from "astro/config";

export default defineConfig({
  experimental: {
    incrementalBuild: true,
  },
});astro.config.mjs

cacheKeyでデータの変化を伝える

フラグを立てただけでは、まだ何もスキップされません。Astroはページのソースコードの変化を自動で追えますが、そのページが表示するデータが変わったかどうかまでは分かりません。ブログ記事の本文がCMSから来ている場合、Astro側のコードは1文字も変わらないのに、表示すべき内容だけが変わる、ということが起きるからです。

そこで、データが変わったかどうかを判定するための目印を、開発者が渡します。それが cacheKey です。

cacheKey は、getStaticPaths() が返すオブジェクトに追加する文字列です。getStaticPaths() は、[slug].astro のような動的ルートに対してどのURLを生成するかをAstroへ伝える関数で、静的サイト生成では欠かせない仕組みです。

---
export async function getStaticPaths() {
  const posts = await fetchPosts();

  return posts.map(post => ({
    params: { slug: post.slug },
    props: { post },
    cacheKey: post.updatedAt,
  }));
}
---src/pages/blog/[slug].astro

cacheKey は、内容の指紋のようなものだと考えると分かりやすいです。指紋が前回と同じならページの中身も同じはずなので、Astroは前回のHTMLをそのまま使い回します。指紋が変わっていれば、そのページだけ作り直します。

したがって cacheKey には、ページの内容が変わったときに必ず変わる値を選ぶ必要があります。公式ドキュメントは、コンテンツのハッシュ値、バージョン番号、データソース側の更新日時を例として挙げています。逆に、本文を直してもタイトルは変わらないので、記事のタイトルを cacheKey にすると、更新の反映されない古いページが残り続けます。

なお、cacheKey を返せるのは getStaticPaths() を持つページだけです。getStaticPaths() を使わない普通の静的ページは、毎回レンダリングされます。

コンテンツコレクションならdigestを使う

Markdownファイルなどをコンテンツコレクションで管理している場合は、自分でハッシュを計算する必要はありません。コンテンツコレクションのローダーは、各エントリに対して digest という値を付けられます。これはエントリのデータから作られる短い文字列で、データが変わったときに変わることがローダー側で保証されています。

Astro 7.2では、この digestgetCollection() で取り出したエントリからも参照できるようになりました。そのまま cacheKey に使えます。

---
import { getCollection, render } from "astro:content";

export async function getStaticPaths() {
  const entries = await getCollection("docs");

  return entries.map(entry => ({
    params: { slug: entry.id },
    props: { entry },
    cacheKey: String(entry.digest),
  }));
}

const { entry } = Astro.props;
const { Content } = await render(entry);
---src/pages/docs/[...slug].astro

String() で囲んでいるのは、digest が省略可能な値(string | undefined)だからです。

キャッシュが無効になる条件

cacheKey が一致していても、そのページを組み立てているコードが変わっていれば作り直しが必要です。この判定にAstroが使うのは、モジュール依存グラフのハッシュです。モジュール依存グラフとは、このページがこのレイアウトを読み込み、そのレイアウトがこのコンポーネントを読み込み、という import のつながりを辿った関係図のことです。Astroはこのつながりに含まれるファイルの中身をまとめてハッシュ化し、前回のビルド時の値と比べます。レイアウトを1行直せばハッシュが変わるので、そのレイアウトを使う全ページをAstroが作り直します。

astro.config.mjs の設定やプロジェクトの依存パッケージを変えた場合は、全ページの出力に影響し得るので、Astroはキャッシュ全体を捨てます。

インクリメンタルビルドで、キャッシュの復元とレンダリングを振り分ける流れ

前回の getStaticPaths() にはあったのに今回は返ってこなくなったページについては、Astroが以前の出力を片付けます。削除した記事のHTMLが残り続ける心配はいりません。

インクリメンタルビルドを本番へ入れる前に

速くなるかどうかは、キャッシュをどこに置くかと、制限にどれだけ当たるかで決まります。

キャッシュの置き場所とCIでの扱い

キャッシュは、Astroの cacheDir に保存されます。既定値は node_modules/.astro/ です。ここにビルドのマニフェストと、前回レンダリングした出力の両方が入ります。

Astroはビルドのたびに出力先ディレクトリ(既定では dist/)を空にし、スキップしたページをキャッシュから戻します。そのため、CI(継続的インテグレーション)でビルドしているなら、astro build の前に cacheDir を復元しておかないと、キャッシュが見つからず全ページを作り直します。逆に言うと、CIで保存しておくのはこの1ディレクトリだけで足ります。

キャッシュを無視して全ページを作り直したいときは、--force を付けます。このときも次回のために新しいキャッシュは書き出されます。

astro build --force

制限事項

公式ドキュメントは、制限事項として次の3つを挙げています。

制限内容対処
build.concurrency値が1より大きいと、Astroは警告を出してキャッシュを使わず全ページを作り直す並列ビルドとは併用しない
サーバーアイランドAstroが暗号鍵を既定でビルドごとに作り直すため、毎回レンダリングされるASTRO_KEY を固定する
ミドルウェアAstroはミドルウェアの変更を追跡しないミドルウェアを編集したら astro build --force を実行する

このうちミドルウェアの扱いは注意が必要です。ミドルウェアは全リクエストの前後に差し込まれる処理で、事前レンダリングされるページのHTMLを書き換えることもできます。それが追跡されないということは、ミドルウェアを直したのに古いHTMLが出続ける、という状態があり得るということです。公式ドキュメントも、ミドルウェアが事前レンダリングされるページのHTMLを変えている場合は、編集後に astro build --force を実行するよう案内しています。

問題になるのは、ミドルウェアが出力HTMLを変えているかどうかです。提案時の議論では当初、i18nのようなミドルウェアベースのルーティングも影響を受けるかのように読める説明がありましたが、Astroの開発者があとから、i18nルーティングそのものはキャッシュの正しさに影響しないと訂正しています。i18nを使っているという理由だけで見送る必要はありません。

APIの形にも注文が付いています。cacheKey を渡せるのが getStaticPaths() のあるルートに限られること。ページの最上位で全データを把握しないといけないので、ネストしたコンポーネントの中でデータを取っている構成では書きにくいこと。どちらもRFCのコメントで開発者が挙げている点です。こうした宿題が残っているから、いまも実験的フラグの下にあるわけです。

制限と対処の対応です。

build.concurrency、サーバーアイランド、ミドルウェアという3つの制限と、それぞれの対処を左右に対応づけた図

本番のビルドへ入れる前に、手元で astro build を2回続けて実行してください。2回目が速くなり、かつ出力されたHTMLが1回目と一致することを確かめてからです。

セッション機能の無効化

5つの変更のうち、いちばん少ない手間で効くのがこれです。

セッションの役割

Astroのセッションは、オンデマンドレンダリング(リクエストのたびにサーバーでHTMLを作る方式)のページ同士でデータを共有するための仕組みです。Astro 5.7で入りました。Cookieと違ってデータはサーバー側に保存されるので、サイズの上限や改ざんを気にせず、ショッピングカートの中身やフォームの入力途中の状態といった情報を持ち回せます。

---
export const prerender = false;
const cart = await Astro.session?.get("cart");
---

<a href="/checkout">🛒 {cart?.length ?? 0} items</a>src/components/CartButton.astro

セッションを動かすにはストレージドライバが必要です。Node、Cloudflare、Netlifyの各アダプターは、何も指定しなくても既定のドライバを自動で構成してくれます。

session: false で外れるもの

この自動構成が、セッションを使わないプロジェクトには余計でした。使っていないセッションランタイムがサーバーバンドルに含まれ、Cloudflare WorkersのようにKVネームスペースまで用意されてしまうからです。

Astro 7.2では、設定を false にしてセッション機能を切れるようになりました。

import { defineConfig } from "astro/config";

export default defineConfig({
  session: false,
});astro.config.mjs

こうすると、アダプターは既定のドライバを構成しなくなり、セッションランタイムはSSRバンドルから除外されます。Cloudflareアダプターであればデプロイ時のKVネームスペースの用意も行われません。

効いてくるのはサーバーレスやエッジのランタイムです。これらの環境では、リクエストが来てから関数が立ち上がるまでの時間(コールドスタート)にバンドルの読み込みと解析が含まれるため、使わないコードが減るとそのまま起動時間の短縮になります。

設定の前後で、バンドルに入るものはこれだけ違います。

既定のサーバーバンドルに含まれる4要素と、session falseを設定したときに残る2要素を左右に並べて対比した図

なお、ドライバを一切設定していなければ、セッションランタイムはもともとバンドルから除外されます。session: false が追加で伝えているのは、アダプターの既定ドライバも要らない、という意思表示です。

既存コードへの影響を確認する

セッションを無効にすると Astro.sessionundefined になります。ここで壊れないのは、もともとガードして書かれているコードだけです。

公式ドキュメントの例が最初から Astro.session?.get() のようにオプショナルチェーン演算子(?.。値が nullundefined なら、その先を評価せず undefined を返す書き方)になっているのはこのためです。if (Astro.session) のような存在チェックも同じく機能します。公式のリリース告知も、既存の存在チェックが動くことまでしか保証していません。

逆に、Astro.session.get("cart") のようにガードなしで直接アクセスしている箇所や、Astro.session! のように非nullアサーションを付けている箇所は、実行時にエラーになります。設定を入れる前に Astro.sessioncontext.session を検索し、すべてガードされているかを確かめてください。

astro previewのバックグラウンドモード

ターミナルを1枚節約できます。

—background フラグ

astro dev --background は、Astro 7.0で追加されたフラグです。開発サーバーをターミナルに張り付かない別プロセスとして起動し、あわせてJSON形式のログ出力を有効にします。Astro 7.2からは、これが astro preview でも使えるようになりました。

astro preview --background

astro preview は、astro build で作った出力を、本番に近い形でローカルに配信するコマンドです。フォアグラウンドで動かしているとそのターミナルが占有されてしまい、確認しながら別のコマンドを打つことができませんでした。

起動のしかたによる、手元のターミナルの違いです。

そのまま起動した場合のログで埋まったターミナルと、--backgroundを付けた場合の空いたターミナルおよび別プロセスのサーバーを対比した図

ロックファイルで多重起動を防ぐ

バックグラウンドで起動すると、Astroはロックファイルをプロジェクトへ書き出します。開発サーバーなら .astro/dev.json、プレビューサーバーなら .astro/preview.json です。ここにサーバーのURL、ポート、PID(プロセスID)が記録されます。

同じプロジェクトですでにサーバーが動いている状態でもう一度コマンドを打つと、Astroは新しいサーバーを起動せず、動いているサーバーの情報を表示して終了します。止めてから起動し直したいときは --force を付けます。

ここで見ているのは、ファイルの有無そのものではありません。クラッシュやコンテナの再起動でロックファイルだけが取り残されることがあるため、Astroは記録されたPIDのプロセスが本当にそのサーバーかを確かめ、古いロックだと分かれば取り除いて起動し直します。PIDが別のプロセスに再利用されたケースの取りこぼしは、7.2.2で修正されました。

astro preview --background --force

起動後のサブコマンド

バックグラウンドのサーバーは、3つのサブコマンドで管理します。

コマンドできること
astro preview status動いているサーバーのURL、PID、稼働時間を表示する
astro preview logsサーバーのログを表示する。--follow-f)で追従できる
astro preview stopサーバーを停止する

stop は、まずSIGTERMを送って最大5秒待ち、それでも終了しなければSIGKILLへ切り替えます。SIGTERMは終了のお願い、SIGKILLは拒否できない強制終了です。Astroが段階を踏むので、サーバーは後片付けをしてから落ちられます。

astro preview --background が、有効なロックの有無で既存サーバーの表示と新規起動を分け、起動後はstatus、logs、stopで操作できることを示した流れ図

AIコーディングエージェント向けの既定値

このバックグラウンドモードは、AIコーディングエージェントが検出されたときには自動的に有効になります。エージェントがサーバーを起動したままターミナルを塞ぐのを、Astroチームが先回りして防いでいます。Astro 7.0では astro dev だけが対象でしたが、7.2からは astro preview も同じ扱いになりました。

自動で切り替わるのが困る場合は、環境変数で明示的に無効化できます。

ASTRO_DEV_BACKGROUND=0 astro dev
ASTRO_PREVIEW_BACKGROUND=0 astro preview

ちなみに開発サーバーには /_astro/status というヘルスチェック用のエンドポイントがあり、{"ok": true} というJSONを返します。サーバーが待ち受け可能になったかをプログラムから確認するためのもので、本番ビルドには存在しません。

logger.entrypoint の相対パス指定

この中では一番効果の小さい変更です。設定ファイルの書き味だけが変わります。

ロガーの差し替え

Astro 7.0で入ったロガーAPIは、Astroが出力するログの行き先を差し替えるための仕組みです。既定ではコンソールへ人が読みやすい形で出しますが、これをJSONにしたり、ログ集約サービスへ送ったりできます。

自作のロガーを使う場合は、その実装ファイルの場所を logger.entrypoint で指定します。

7.2 前後の書き方

Astro 7.2より前は、プロジェクト内のファイルを指すときに URL を組み立てる必要がありました。

import { defineConfig } from "astro/config";

export default defineConfig({
  logger: {
    entrypoint: new URL("./src/custom-logger.js", import.meta.url),
  },
});astro.config.mjs

7.2からは、プロジェクトルートからの相対パスをそのまま書けます。

import { defineConfig } from "astro/config";

export default defineConfig({
  logger: {
    entrypoint: "./src/custom-logger.js",
  },
});astro.config.mjs

npmパッケージ名(@org/astro-logger など)や、これまでどおりの URL 形式も引き続き使えます。

logger.entrypoint に書ける形は3つです。

npmパッケージ名、プロジェクト相対パス、URLオブジェクトの3つの指定方法を並べ、相対パスがAstro 7.2で追加されたことを示した図

1つ注意点があります。ロガーのエントリーポイントはJavaScriptファイルである必要があり、TypeScriptはサポートされていません。読み込みに失敗した場合、Astroは既定のロガーへフォールバックします。

7.2系で入った修正

CHANGELOGから、この記事の主題に関わる修正を拾っておきます。

とくにインクリメンタルビルドを試すなら、最新のパッチまで上げてからにしてください。2026年8月18日時点の最新は7.2.3です。

アップグレード前に確認したいこと

  1. まずは npx @astrojs/upgrade でAstro本体を7.2系へ上げ、既存のビルドが通ることを確認する。ここまでは新機能を触らなくてもよい。
  2. セッションを使っていないなら session: false を追加する。その前に Astro.sessioncontext.session を検索し、ガードなしで直接アクセスしている箇所がないことを確かめる。
  3. インクリメンタルビルドは、並列ビルド、サーバーアイランド、ミドルウェアの使用状況を先に確認する。ミドルウェアが事前レンダリングされるページのHTMLを書き換えているなら、編集のたびに astro build --force が要ることを前提にする。
  4. 試すときは、astro build を2回続けて実行し、2回目の出力が1回目と一致することを確かめる。CIへ入れるのは、ローカルで挙動を把握してからにする。
  5. CIで使う場合は、cacheDir(既定では node_modules/.astro/)をビルド間で保存・復元する設定を先に用意する。

本体を上げる、セッションを切る、制限を調べる、2回続けてビルドする、CIのキャッシュを整えるという5ステップを上から順に並べた図

要点

参考資料


Share this post:

Previous Post
OpenAIがCursorへのモデル提供を打ち切る:SpaceXによる買収と「借り物の頭脳」というリスク
Next Post
デジタル庁が公開した行政手続データのMCPサーバーを読む