🎍

Astro ゆく年くる年 2024-2025

2024/12/31に公開

はじめに

Astro は、コンテンツが豊富なウェブサイトの作成に適したウェブフレームワークです。Islands Architecture のもとで静的なページの上に動的な要素を配置し、パフォーマンスとインタラクティビティの両立を図れることを一つの特徴としていますが、SSR や Middleware、Endpoints などを活用し、サーバーサイドでも動作するようなアプリケーションを作成することも可能です。最近は特に後者のダイナミックなサイトを作るための機能強化にも力を入れており、フルスタックなアプリケーションフレームワークとしての可能性も見え始めてきています。Astro についてより詳しくは、公式ドキュメントの Why Astro? やその日本語訳などを参照してください。

以下では、2024 年の Astro の動向のなかでも特に筆者が重要であると感じたものについてまとめていきます。また 2025 年にどういった動きがありそうかについても、筆者が認識している範囲で触れていきます。

なお、本記事の 2023 版も公開していますので、興味がある方は以下のリンクからご覧ください:

https://zenn.dev/morinokami/articles/astro-2023-2024

いくつかの指標

バージョンの推移

2024 年が明けた時点での Astro のバージョンは v4.0.8 でしたが、年末にこの記事を書いている時点では v5.1.1 がリリースされています。beta 版も含めると、2024 年のリリースの総数は 169 でした。昨年のリリース総数は 175 でしたので、昨年とほぼ同じペースでリリースがおこなわれたようです。一方、2023 年はメジャーバージョンが 1 から 4 へと上がり、かなり急速なペースで機能追加がおこなわれていた印象ですが、2024 年は 4 から 5 へと上がっただけであり、バージョンの変化のペースはやや緩やかになったようです。

2024 年に公開されたリリースタグと公開日時の一覧を以下のアコーディオン内に置いてありますので、興味がある方は中身を確認してみてください。

2024 年に公開されたリリースタグと公開日時の一覧
リリースタグ 公開日時
astro@5.1.1 2024-12-20T12:23:12Z
astro@5.1.0 2024-12-19T12:25:07Z
astro@4.16.18 2024-12-18T12:04:59Z
astro@5.0.9 2024-12-17T03:03:34Z
astro@5.0.8 2024-12-16T19:52:37Z
astro@5.0.7 2024-12-16T17:41:04Z
astro@5.0.6 2024-12-16T15:31:07Z
astro@5.0.5 2024-12-11T11:09:33Z
astro@5.0.4 2024-12-09T15:39:48Z
astro@5.0.3 2024-12-05T13:27:58Z
astro@4.16.17 2024-12-05T15:46:20Z
astro@5.0.2 2024-12-03T22:29:55Z
astro@5.0.1 2024-12-03T12:30:02Z
astro@5.0.0 2024-12-03T10:58:51Z
astro@4.16.16 2024-11-27T14:22:39Z
astro@5.0.0-beta.12 2024-11-27T14:37:10Z
astro@4.16.15 2024-11-26T09:05:05Z
astro@5.0.0-beta.11 2024-11-26T11:40:17Z
astro@4.16.14 2024-11-21T14:49:11Z
astro@5.0.0-beta.9 2024-11-21T12:47:38Z
astro@5.0.0-beta.10 2024-11-21T16:13:21Z
astro@4.16.13 2024-11-15T11:28:54Z
astro@4.16.12 2024-11-13T14:22:45Z
astro@4.16.11 2024-11-13T00:02:24Z
astro@5.0.0-beta.8 2024-11-13T14:33:46Z
astro@4.16.10 2024-11-06T14:57:13Z
astro@5.0.0-beta.7 2024-11-06T15:49:47Z
astro@4.16.9 2024-11-04T14:22:13Z
astro@4.16.8 2024-10-31T07:58:03Z
astro@5.0.0-beta.6 2024-10-31T09:09:09Z
astro@4.16.7 2024-10-22T12:12:07Z
astro@4.16.6 2024-10-17T12:59:49Z
astro@4.16.5 2024-10-15T17:11:38Z
astro@4.16.4 2024-10-15T07:38:47Z
astro@5.0.0-beta.5 2024-10-15T17:50:28Z
astro@4.16.3 2024-10-14T08:57:08Z
astro@4.16.2 2024-10-12T14:16:39Z
astro@4.16.1 2024-10-11T17:22:00Z
astro@4.16.0 2024-10-10T11:23:07Z
astro@4.15.12 2024-10-07T13:43:22Z
astro@5.0.0-beta.4 2024-10-07T13:58:05Z
astro@4.15.11 2024-10-03T13:51:43Z
astro@4.15.10 2024-10-01T13:28:21Z
astro@5.0.0-beta.3 2024-10-01T13:48:40Z
astro@5.0.0-beta.2 2024-09-24T09:12:05Z
astro@4.15.9 2024-09-23T17:28:10Z
astro@4.15.8 2024-09-19T13:15:21Z
astro@4.15.7 2024-09-17T22:23:13Z
astro@5.0.0-beta.1 2024-09-17T10:25:42Z
astro@4.15.6 2024-09-13T19:57:56Z
astro@4.15.5 2024-09-13T11:06:03Z
astro@5.0.0-alpha.8 2024-09-13T20:36:33Z
astro@5.0.0-alpha.7 2024-09-13T13:29:11Z
astro@5.0.0-alpha.6 2024-09-10T12:30:35Z
astro@5.0.0-alpha.5 2024-09-09T15:11:53Z
astro@4.15.4 2024-09-06T16:49:00Z
astro@4.15.3 2024-09-05T01:43:29Z
astro@5.0.0-alpha.4 2024-09-04T11:45:59Z
astro@5.0.0-alpha.3 2024-09-03T11:53:43Z
astro@4.15.2 2024-09-02T11:21:00Z
astro@5.0.0-alpha.2 2024-08-30T20:14:06Z
astro@4.15.1 2024-08-29T15:32:17Z
astro@4.15.0 2024-08-29T11:52:21Z
astro@4.14.6 2024-08-28T10:53:21Z
astro@5.0.0-alpha.1 2024-08-23T17:47:23Z
astro@4.14.5 2024-08-22T20:58:22Z
astro@4.14.4 2024-08-21T21:10:08Z
astro@4.14.3 2024-08-20T14:37:15Z
astro@5.0.0-alpha.0 2024-08-19T18:39:53Z
astro@4.14.2 2024-08-15T16:35:54Z
astro@4.14.1 2024-08-15T15:08:16Z
astro@4.14.0 2024-08-15T09:50:20Z
astro@4.13.4 2024-08-14T08:16:28Z
astro@4.13.3 2024-08-09T21:50:44Z
astro@4.13.2 2024-08-08T11:53:44Z
astro@4.13.1 2024-08-02T13:20:21Z
astro@4.13.0 2024-08-01T09:57:09Z
astro@4.12.3 2024-07-30T15:56:33Z
astro@4.12.2 2024-07-19T14:08:23Z
astro@4.12.1 2024-07-18T21:32:09Z
astro@4.12.0 2024-07-18T15:07:14Z
astro@4.11.6 2024-07-17T12:48:52Z
astro@4.11.5 2024-07-03T22:04:20Z
astro@4.11.4 2024-07-03T14:12:09Z
astro@4.11.3 2024-06-26T13:10:43Z
astro@4.11.2 2024-06-26T09:30:46Z
astro@4.11.1 2024-06-24T16:51:53Z
astro@4.11.0 2024-06-20T11:00:10Z
astro@4.10.3 2024-06-17T13:42:06Z
astro@4.10.2 2024-06-11T12:17:27Z
astro@4.10.1 2024-06-08T09:30:10Z
astro@4.10.0 2024-06-06T15:04:28Z
astro@4.9.3 2024-06-05T07:46:48Z
astro@4.9.2 2024-05-27T11:00:05Z
astro@4.9.1 2024-05-23T16:06:29Z
astro@4.9.0 2024-05-23T10:08:12Z
astro@4.8.7 2024-05-22T07:42:06Z
astro@4.8.6 2024-05-17T11:02:26Z
astro@4.8.5 2024-05-16T17:02:48Z
astro@4.8.4 2024-05-15T14:44:47Z
astro@4.8.3 2024-05-13T11:31:37Z
astro@4.8.2 2024-05-09T18:22:20Z
astro@4.8.1 2024-05-09T14:42:04Z
astro@4.8.0 2024-05-09T10:09:00Z
astro@4.7.1 2024-05-02T12:01:08Z
astro@4.7.0 2024-04-25T09:30:08Z
astro@4.6.4 2024-04-23T23:35:05Z
astro@4.6.3 2024-04-18T15:38:04Z
astro@4.6.2 2024-04-16T16:10:10Z
astro@4.6.1 2024-04-12T15:33:28Z
astro@4.6.0 2024-04-11T11:27:14Z
astro@4.5.18 2024-04-10T01:02:13Z
astro@4.5.17 2024-04-09T06:44:12Z
astro@4.5.16 2024-04-04T17:13:13Z
astro@4.5.15 2024-04-03T17:14:16Z
astro@4.5.14 2024-04-02T20:17:15Z
astro@4.5.13 2024-04-02T07:48:49Z
astro@4.5.12 2024-03-28T18:23:07Z
astro@4.5.11 2024-03-28T17:28:58Z
astro@4.5.10 2024-03-26T21:26:20Z
astro@4.5.9 2024-03-22T16:37:33Z
astro@4.5.8 2024-03-20T15:17:55Z
astro@4.5.7 2024-03-20T08:43:04Z
astro@4.5.6 2024-03-18T17:08:42Z
astro@4.5.5 2024-03-15T20:26:36Z
astro@4.5.4 2024-03-14T16:02:43Z
astro@4.5.3 2024-03-13T20:00:35Z
astro@4.5.2 2024-03-12T11:47:42Z
astro@4.5.1 2024-03-11T20:11:08Z
astro@4.5.0 2024-03-11T10:27:32Z
astro@4.4.15 2024-03-08T01:54:38Z
astro@4.4.14 2024-03-07T15:32:39Z
astro@4.4.13 2024-03-06T16:09:30Z
astro@4.4.12 2024-03-06T01:00:02Z
astro@4.4.11 2024-03-04T18:18:47Z
astro@4.4.10 2024-03-04T11:10:32Z
astro@4.4.9 2024-03-02T08:43:46Z
astro@4.4.8 2024-03-01T12:12:42Z
astro@4.4.7 2024-03-01T09:32:53Z
astro@3.6.5 2024-03-01T12:09:23Z
astro@4.4.6 2024-02-28T13:19:28Z
astro@4.4.5 2024-02-26T15:35:30Z
astro@4.4.4 2024-02-23T14:33:44Z
astro@4.4.3 2024-02-22T16:19:02Z
astro@4.4.2 2024-02-21T20:42:23Z
astro@4.4.1 2024-02-20T14:50:10Z
astro@4.4.0 2024-02-15T11:01:43Z
astro@4.3.7 2024-02-13T21:27:38Z
astro@4.3.6 2024-02-12T14:27:24Z
astro@4.3.5 2024-02-07T18:27:11Z
astro@4.3.4 2024-02-07T14:40:21Z
astro@4.3.3 2024-02-06T16:29:44Z
astro@4.3.2 2024-02-02T21:00:53Z
astro@4.3.1 2024-02-01T22:17:19Z
astro@4.3.0 2024-02-01T10:05:33Z
astro@4.2.8 2024-01-31T10:41:33Z
astro@4.2.7 2024-01-30T15:42:48Z
astro@4.2.6 2024-01-26T23:34:47Z
astro@4.2.5 2024-01-26T13:32:28Z
astro@4.2.4 2024-01-24T00:29:01Z
astro@4.2.3 2024-01-22T23:39:02Z
astro@4.2.2 2024-01-22T20:12:49Z
astro@4.2.1 2024-01-18T18:05:13Z
astro@4.2.0 2024-01-18T10:32:05Z
astro@4.1.3 2024-01-16T11:46:43Z
astro@4.1.2 2024-01-11T08:33:52Z
astro@4.1.1 2024-01-05T20:47:21Z
astro@4.1.0 2024-01-04T15:18:14Z
astro@4.0.9 2024-01-02T15:28:17Z

GitHub スター数の推移

https://star-history.com によると、2024 年初頭の GitHub スター数は 37,000 程度ですが、年末には 48,000 程度にまで増加しました。2023 年は 15,000 近く増加していたため、その伸びはやや鈍化しているようですが、それでも 1 年で 10,000 以上の増加であるため堅調に数を伸ばしているといえるでしょう。

Star History Chart

パッケージのダウンロード数の推移

https://npmtrends.com によると、2024 年初頭における週間のダウンロード数は 185,902 ですが、12 月 15 日には 364,201 にまで増加しました。約 2 倍の増加であり、こちらも順調に数を伸ばしているといえそうです。

https://npmtrends.com における Astro のダウンロード数の推移

https://npmtrends.com/astro

State of JavaScript

12 月に発表された State of JavaScript 2024 のメタフレームワーク部門において、Astro は Interest(聞いたことがある人の中でポジティブな意見を持つ人の割合)、Retention(使ったことがある人の中でポジティブな意見を持つ人の割合)、Positivity(何らかの感情を表明した人の中でポジティブな意見をもつ人の割合)の 3 つの指標で 1 位を獲得しました。また、Usage(使ったことがある人の割合)についても昨年の 4 位から上昇し、Next.js に次ぐ 2 位となりました:

State of JavaScript 2024 のメタフレームワーク部門における Astro の評価

Awareness(聞いたことがある、または使ったことがある人の割合)についても 5 位に上昇しており、すべての指標で「前年より上昇」もしくは「1 位をキープ」という結果となっています。State of JavaScript の結果を信頼するならば、2024 年は Astro にとって飛躍の年であったといえるでしょう。

https://2024.stateofjs.com/
https://2023.stateofjs.com/

機能の追加・変更

Content Layer

Markdown などで記述されたコンテンツを型安全に取り扱うための仕組みである Content Collections が導入されたのは v2.0 ですが、v5.0 において新たに追加された Content Layer API によりコンテンツの定義が拡張され、より様々なケースに対応できるようになりました。

従来、Astro の Content Collections により扱うことができるコンテンツの対象は、ローカルに存在する Markdown や MDX ファイルなどに限定されていました。そこでは、たとえば

- src/content/
  - blog/
    - post-1.md
    - post-2.md

のように src/content ディレクトリにコンテンツを配置し、また

src/content/config.ts
import { z, defineCollection } from "astro:content";

const blogCollection = defineCollection({
  type: "content",
  schema: z.object({
    title: z.string(),
    tags: z.array(z.string()),
    image: z.string().optional(),
  }),
});

export const collections = {
  blog: blogCollection,
};

のように src/content/config.ts ファイルにコンテンツのコレクションを定義することにより、フロントマターに対してバリデーションをおこなったり、getCollection などの関数により取得したコンテンツデータを取り扱う際にエディター上で補完を効かせたりすることができました。

v5.0 において導入された Content Layer API により、コンテンツに対するバリデーションやエディター上の補完などの利点はそのままに、コンテンツの定義を任意に拡張できるようになりました。たとえば以下のようなコードにより、外部 API から取得したコンテンツをコレクションとして扱うことができます[1]:

src/content.config.ts
import { defineCollection, z } from "astro:content";

const countries = defineCollection({
  loader: () => fetch("https://api.example.com/countries").then(res => res.json()),
  schema: z.object({ /* スキーマの定義 */ }),
});

export const collections = { countries }

このようにコンテンツの定義を拡張することにより、本来は同じように扱うべきコンテンツ(たとえばローカルの Markdown ファイルと CMS 上で管理されたデータなど)を統一的に扱うことができるようになりました。

新しい Content Layer のもとでは、defineCollection に従来与えていた type はレガシー扱いとなり、代わりに loader というプロパティを指定するようになりました。これは名前の通りデータのローダーであり、ここに所望のデータをロードするための処理を記述することにより、任意のコンテンツを扱うことが可能となります。

v5 では glob()file() という組み込みのローダーが提供されており、たとえば

src/content.config.ts
const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
  schema: z.object({ /* スキーマの定義 */ }),
});

のように記述することで、従来のようにローカルのファイルをコレクションとして扱うことも可能です。また、上で示したように loader には任意の関数を指定できるため、外部 API やデータベースなど、様々なデータソースからデータを取得することができます。

さらに面白いことに、自身で作成したローダーを npm パッケージとして公開し、第三者に利用してもらうことも可能です。すでに StoryblokCloudinaryHygraph といった CMS サービスが自身のサービス向けのローダーを公開しており、これらのサービスからデータを取得するために自らローダーを記述する手間は不要となっています:

https://astro.build/blog/storyblok-loader/
https://astro.build/blog/cloudinary-loader/
https://astro.build/blog/hygraph-loader/

以上のように、新たに追加された Content Layer により Astro におけるコンテンツの扱いが一般化され、さらにデータローダーを自由に定義し配布可能であることから、コンテンツの使用可能性がより高まりました。また、カスタムローダーを作成する際に使用する Content Loader API には、データの更新タイミングの記録などに使用可能な meta ストアや、データのレンダリング結果を格納するための rendered フィールドなど、便利な機能が多数用意されています。Content Layer API のもとで刷新された Content Collections を使い、ぜひ自身のローダーを定義し、出来のいいものは npm パッケージとして公開していきましょう。

Astro Actions

Astro には以前から、サーバーサイドで HTTP リクエストをハンドルするための Endpoints という機能がありましたが、サーバーサイドとの通信をより少ないボイラープレートコードで型安全に実現するための Astro Actionsv4.15 において追加されました。Actions により、以下のようなメリットを手軽に享受できます:

  • Zod による入力データのバリデーション
  • アクションを呼び出すための型安全な関数の自動生成
  • isInputError 関数や ActionError 型により標準化されたエラーハンドリング

具体的には、src/actions/index.ts に以下のようなコードを書くことにより Action を定義できます:

src/actions/index.ts
import { defineAction } from "astro:actions";
import { z } from "astro:schema";

export const server = {
  // Action の定義
  getGreeting: defineAction({
    // クライアントから送信されるデータのスキーマ
    input: z.object({
      name: z.string(),
    }),
    // サーバーサイドで実行されるロジック
    handler: async (input) => {
      return `Hello, ${input.name}!`; // input はバリデーション済みであり、型安全にアクセスできる
    }
  })
}

handler に記述するロジックから、Content-Type の確認やインプットのバリデーション処理が省略されていることに注目してください。Astro Actions を使うと、HTTP エンドポイントにおいておこなうこうした定型的な処理を Astro に任せられるため、開発者はビジネスロジックに集中することができるというわけです。

Actions を呼び出すコードは以下のようになります:

---
---

<button>挨拶する</button>

<script>
// getGreeting が定義された actions を import
import { actions } from "astro:actions";

const button = document.querySelector("button");
button?.addEventListener("click", async () => {
  // getGreeting の呼び出し
  const { data, error } = await actions.getGreeting({ name: "Actions" });
  // エラーがなければアラートを表示
  if (!error) alert(data);
})
</script>

astro:actions から actions を import していますが、ここには上で定義した getGreeting を呼び出す関数が含まれています。この関数は Action の定義時に与えたインプットのスキーマにより型が付与されているため、型安全に呼び出すことができます。もちろん、エディター上でホバーし型を確認したり、cmd + click により定義へのジャンプも可能です。

また、上のコードには登場していませんが、Actions の返り値にある error がバリデーションエラーかどうかを isInputError 関数により判定したり、Actions 側から ActionError を throw することで HTTP ステータスコードを指定することなども可能です。

その名前から分かるように、Astro Actions は React の Server Actions (Functions) を意識して作成された機能であり、実際 Astro Actions と Server Actions が解決する問題には共通点が少なくありませんが、Astro Actions は自動バリデーションや返り値の定式化など、後発として一歩進んだ機能を提供しているように思われます。Astro により作成するサイトにおいてサーバーサイドとの通信を大量におこなうことはそれほど多くはないかもしれませんが、たとえば記事への Like など、必要な場面でピンポイントに Actions を差し込むことも可能であるため、ぜひ以下のドキュメントを読み自身のプロジェクトでも活用してみてください:

https://docs.astro.build/en/guides/actions/

Server Islands

Astro v5 において、コンポーネントの新しいレンダリング方式として Server Islands が追加されました。Astro では従来から Islands Architecture によりページ内の一部の領域を個別にハイドレーションすることができましたが、Server Islands はこの Islands Architecture を拡張し、ページ内の一部の領域をサーバーサイドでレンダリングすることを可能としました。以下は Server Islands が発表された際に示されたイメージ図です:

Server Islands のイメージ図

図からもわかるように、Server Islands を使用すると、基本的に静的なページの中にサーバーサイドでレンダリングしたコンテンツを埋め込むことができます。静的な領域は CDN にキャッシュし、動的な領域は初期表示後に遅延ロードすることで、初期表示速度を担保しつつコンテンツの柔軟性を高めることができ、従来の SSR では達成できなかったパフォーマンスが実現できるようになります。

Server Islands を使用するためには、新規に追加された server:defer ディレクティブをコンポーネントに指定します。たとえば

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} />

のように、ユーザーごとのアバター画像をサーバーサイドで取得するコンポーネントがあるとします。このコンポーネントを使用するページにおいて server:defer ディレクティブを指定するだけで、コンポーネントは Server Island となり、その結果コンポーネントの外部は静的に生成され、コンポーネント自体はサーバーで都度レンダリングされるようになります:

src/pages/index.astro
---
import Avatar from "../components/Avatar.astro";
---

<Avatar server:defer />

また、React の Suspense のように、Server Islands のロード中に表示するフォールバックコンテンツを指定することも可能です:

src/pages/index.astro
---
import Avatar from "../components/Avatar.astro";
import GenericAvatar from "../components/GenericAvatar.astro";
---

<Avatar server:defer>
  <GenericAvatar slot="fallback" />
</Avatar>

Server Islands についてより詳しく知りたい場合は、従来の Prerendering や On-demand Rendering との違いを詳細に解説した筆者の以下記事も参考にしてみてください。Next.js の各レンダリング方式を説明した上で、それらと比較するかたちで Astro の Server Islands を解説しているため、モダンなレンダリング方式全般に関する解像度を高められるはずです:

https://zenn.dev/morinokami/articles/astro-server-islands-vs-nextjs-ppr

Server Islands に関する公式ドキュメントは以下となります:

https://docs.astro.build/en/guides/server-islands/

Astro DB

2024 年 3 月、Astro からデータベースを管理するための機能として @astrojs/db がリリースされました:

https://astro.build/blog/astro-db/

リリース当初、プロダクション環境では Astro Studio というマネージドサービスに接続することを前提としていましたが、現在では任意の libSQL サーバーへと接続できるようになっています。Astro Studio について詳しくは、関連プロジェクトを参照してください。

Astro DB を使用するには、db/config.ts ファイルにテーブルの定義を記述します。具体的には、以下のように defineTablecolumn などを使用してテーブルを定義します:

db/config.ts
import { defineTable, column } from "astro:db";

const Author = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    name: column.text(),
  }
});

const Comment = defineTable({
  columns: {
    authorId: column.number({ references: () => Author.columns.id }),
    body: column.text(),
  }
});

export default defineDb({
  tables: { Author, Comment },
});

さらに、db/seed.ts ファイルにて

db/seed.ts
import { db, Comment, Author } from "astro:db";

export default async function() {
  await db.insert(Author).values([
    { id: 1, name: "Kasim" },
    { id: 2, name: "Mina" },
  ]);

  await db.insert(Comment).values([
    { authorId: 1, body: "Hope you like Astro DB!" },
    { authorId: 2, body: "Enjoy!"},
  ])
}

のようにシード用の関数をエクスポートすることにより、開発サーバーを立ち上げると自動的にデータベースが作成され、シードが実行されるようになります。

データベースへのクエリは、Drizzle クライアントを通じておこないます。astro:db からインポート可能な db クライアントは自動的に対象のデータベースに接続されるため、特に設定などする必要なしにそのままクエリを実行できます:

---
import { db, Comment } from "astro:db";

const comments = await db.select().from(Comment);
---

<h2>Comments</h2>

{
  comments.map(({ author, body }) => (
    <article>
      <p>Author: {author}</p>
      <p>{body}</p>
    </article>
  ))
}

以上、Astro DB により、Astro らしいシンプルな設定と Drizzle によるパワフルなクエリ機能を組み合わせ、Astro 上でのデータベースへの接続・管理をおこなえることを見てきました。後述する Astro Studio の動向の問題もあり、まだ本番環境で使用しているユーザーはそれほど多くはないと思われますが、データベースが必要なちょっとした機能を実現するには必要十分な能力があるため、ぜひ手元のプロジェクトなどで素振りしてみてください。

Astro DB に関する公式ドキュメントは以下となります:

https://docs.astro.build/en/guides/astro-db/

また、筆者が以前作成した、Next.js のチュートリアル Learn Next.js にて作成するプロジェクトの Astro 版クローンも、興味がある方は参考にしてみてください。Astro DB や Actions、Server Islands などを利用してダッシュボードアプリケーションを作成し、実際に Vercel 上にデプロイしています。2024 年に追加されたサーバー寄りの機能をふんだんに使っているため、非常に新鮮かつ楽しい気持ちで開発することができました:

https://github.com/morinokami/astro-dashboard

astro:env

環境変数を型安全に取り扱うための機能である astro:env が、v5 において導入されました。astro:env により、以下のようなことが可能となります:

  • 変数の使用箇所を指定し(クライアントまたはサーバー)、用途を区別しやすくする
  • API キーなど、クライアントに公開したくない情報やビルド出力に含まれてほしくない情報をシークレットとして指定する
  • 変数が必須かどうかを指定し、サーバー起動時に必須の値が設定されているかどうかをチェックする
  • 変数の型を定義し、アプリケーション内での型変換を不要とする

環境変数のスキーマを定義するには、設定ファイルにて env.schema を指定します:

astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  env: {
    schema: {
      // ...
    }
  }
});

続いて envField ヘルパーを用いて、環境変数のスキーマを以下のように記述します:

astro.config.mjs
import { defineConfig, envField } from "astro/config";

export default defineConfig({
  env: {
    schema: {
      API_URL: envField.string({ context: "client", access: "public", optional: true }),
      PORT: envField.number({ context: "server", access: "public", default: 4321 }),
      API_SECRET: envField.string({ context: "server", access: "secret" }),
    }
  }
});

コードからわかるように、上で述べた「アクセス可能なコンテクスト」や「シークレットかどうか」、「必須かどうか」などの情報は、contextaccessoptional などのオプションを通じて指定します。また、変数の型は envField.stringenvField.number などから指定します。

こうして定義した環境変数は、以下のように astro:env/* からインポートして使用できます:

import { API_URL } from "astro:env/client";
import { PORT } from "astro:env/server";
import { API_SECRET } from "astro:env/server";

地味な機能ですが、アプリケーション開発において環境変数の扱い方について悩むことは少なくないため、こうした組み込みの方式を通じて型安全に環境変数を取り扱えるようになったことは嬉しいです。ドキュメントは以下にあり、ここで示したように設定も簡単ですので、ぜひ手元のプロジェクトで試してみてください:

https://docs.astro.build/en/guides/environment-variables/#type-safe-environment-variables

Request Rewriting

v4.13 において、リダイレクトなしにリクエストを書き換えるための Request Rewriting が可能となりました。これにより、ブラウザ上の URL は変化させずに、サーバーサイドでは異なるパスにリクエストを再送信し、その結果をもとのリクエストに対するレスポンスとして返すことができます。この機能は、複数のパスで同じコンテンツを表示したい場合などに便利です。

リライトは、

---
return Astro.rewrite("/login")
---

のように Astro コンポーネントにおいて Astro.rewrite を呼び出すか、あるいは次の例のようにミドルウェアにおいて APIContext オブジェクトに含まれる rewrite メソッドを呼び出すことで実現できます:

import type { APIContext } from "astro";

export function GET({ rewrite }: APIContext) {
  return rewrite("/login");
}

Request Rewriting について、より詳しくは以下のドキュメントを参照してください:

https://docs.astro.build/en/guides/routing/#rewrites
https://docs.astro.build/en/guides/middleware/#rewriting
https://docs.astro.build/en/reference/api-reference/#rewrite

Container API

昨年は Astro の Public Roadmap において Stage 2 の状態であった Container API ですが、今年になり実験的な機能として v4.9 で実装されました。これにより、たとえば React の react-dom/server の各メソッドのように、Astro コンポーネントをアプリケーションコンテクストから独立してレンダリングできるようになります。Container API の背景などについては昨年の記事でも触れていますので、より詳しくはそちらも確認してください:

https://zenn.dev/morinokami/articles/astro-2023-2024#container-api%3A-render-components-in-isolation

Container API を使用するためには、まずコンポーネントをレンダリングするための環境であるコンテナを作成し、コンテナオブジェクトに含まれる renderToString などのメソッドを呼び出します。以下は Container API を使用して Astro コンポーネントを文字列へとレンダリングする例となります:

import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";

const container = await experimental_AstroContainer.create();
const result = await container.renderToString(Card);

result には Card をレンダリングした結果である HTML が含まれており、これを用いてたとえば期待される特定の文字列が含まれているかどうかを確認するテストを書くことができます。Container API を使ったテストの書き方については、以下のプロジェクトも参照してください[2]:

https://github.com/withastro/astro/tree/main/examples/container-with-vitest

Container API には renderToString 以外にも renderToResponse などのメソッドが存在し、またオプションを駆使することにより props や slot などの情報を渡すことも可能です。Container API についてより詳しく知りたい場合は以下のドキュメントを参照してください:

https://docs.astro.build/en/reference/container-reference/

また、下でも触れる Astro Together というイベントにおいて、Container API を駆使し PHP プロジェクト内に Astro コンポーネントをアイランド込みで埋め込むという興味深いデモもおこなわれています。こちらもぜひ参考にしてみてください:

https://www.youtube.com/watch?v=lm2br5_zcHg

関連プロジェクト

Astro Studio

Astro 初のマネージドサービスとして 2024 年初頭にローンチされた Astro Studio ですが、残念ながら早くも 9 月にサービスの終了がアナウンスされることとなりました:

https://astro.build/blog/goodbye-astro-studio/

上の記事では、Astro Studio が目指していたものとして

  • すべての Astro 開発者に、Astro フレームワーク内から気軽に利用できる、手頃で高速な SQL データストレージを提供すること
  • Astro の継続的な開発と成長を支えるために、Astro Studio を収益性のあるビジネスとして構築すること

という二点が挙げられており、後者に関して上手くいかなかったことが率直に述べられています。

また、Astro Studio の今後について、

  • Astro Studio への招待は引き続き停止される
  • 既存ユーザーは、2024 年 10 月 1 日以降は新しいデータベースを作成できなくなる
  • 既存データベースは、2025 年 3 月 1 日以降はアクセスできなくなる
  • 2025 年 3 月 1 日以降、サービス上に存在するデータベースは順次削除される

といったスケジュールも示されていますので、Astro Studio を利用している方は早めに対応するようにしましょう。

なお、関連する Astro DB は存続し、v4.15 において任意の libSQL サーバーへと接続できるように機能が拡張されました。よって、自前の libSQL サーバーを用意するか、あるいは Turso などのマネージドサービスを利用することで、今後も引き続き Astro DB を使用することは可能です。

Astro Storefront

Astro Storefront は、上でも触れた Actions や astro:env などの機能を駆使して作られた、Astro の現在の到達点を示す EC サイトプロジェクトです。以下のリポジトリにソースコードが公開されており、このコードは Astro 公式のグッズストアである Astro Shop として実際に運用されています:

https://github.com/withastro/storefront
https://shop.astro.build/

静的サイトジェネレータとしてスタートした Astro ですが、近年はサーバーサイド機能の強化も積極的に進められてきました。そして現在では EC サイトのような動的なコンテンツを扱うプロジェクトも高い UX を保ちながら構築できるようになったことを示すために、こうしたプロジェクトが作成されたものと思われます。2024 年 3 月には E-commerce ガイドも公開されており、同様のモチベーションが垣間見えます:

https://docs.astro.build/en/guides/ecommerce/

Storefront の README にはプロジェクトの設計方針なども記載されており、コードと合わせて参考にすることで、Astro での実践的な開発手法を学ぶことができるでしょう。Astro により本格的なサイトを構築しようと思った際には、ぜひ一度 Storefront のコードを確認することをおすすめします。

Astro Ecosystem CI

「あるソフトウェアを中心としたエコシステムの品質を保つための取り組み」の一つとして、Ecosystem CI という仕組みが広まっています。Ecosystem CI は、もともと dominikg らを中心に Vite において導入されました:

https://www.youtube.com/watch?v=UgQtYT1DMiw
https://www.youtube.com/watch?v=7L4I4lDzO48

Vite のエコシステムは巨大であり、Vite に依存するライブラリやツールも年々増え続けています。一方このことは、予想外の破壊的変更を Vite に組み込んでしまえば、その影響は巨大なエコシステム全体に波及することを意味します。こうしたリスクを軽減するために、Vite では Ecosystem CI という仕組みが導入され、Vite の変更によりエコシステムの主要なパッケージが意図せず壊れていないことや、また壊れた場合にも早期に連携し修正をおこなえることを担保し、エコシステム全体の品質の維持が図られています。

Ecosystem CI によりエコシステムの品質を保つ試みは Vite 以外にも拡がっており、たとえば以下のようなプロジェクトにおいても導入されています:

こうした流れを受け、Astro にも Ecosystem CI が導入されました。以下がそのリポジトリです:

https://github.com/withastro/astro-ecosystem-ci

Ecosystem CI の実行結果は https://github.com/withastro/astro-ecosystem-ci/actions から確認でき、個別のワークフローを開くと Starlight などエコシステムに属するいくつかのパッケージに対応するジョブが実行されていることがわかります。各ジョブの実行内容については、たとえば https://github.com/withastro/astro-ecosystem-ci/actions/runs/12512049615/job/34904909147 などを読むとパッケージのビルドやテストがおこなわれており、withastro/astro パッケージとの互換性が確認されていることがわかります。

Ecosystem CI はどちらかというとパッケージ開発者向けの仕組みであり、Astro をただ単に使う分には意識する必要はありませんが、エコシステム内のパッケージが突然動かなくなった場合などにヒントになるかもしれません。また、直接 OSS の開発に携わらずとも、たとえば社内システムとして開発しているパッケージ群の安定性の維持を図る際などに、Ecosystem CI の考え方を知っておくと有用であることなどもあるでしょう。

Starlight

2023 年にリリースされたドキュメントサイト向けテーマである Starlight が、一周年を迎えました:

https://astro.build/blog/starlight-turns-one/

年初におけるバージョンは v0.15.2 でしたが、最新のバージョンは v0.30.3 となっており、機能の追加も順調におこなわれています。たとえば v0.21.0 ではディレクトリ構造を表示するための <FileTree> コンポーネントや、順序をもつ複雑なタスクを表示するための <Steps> コンポーネントが追加され、また v0.27.0 ではサーバーサイドレンダリングもサポートされるようになりました。

また、すでに昨年の時点で BiomeKnip などの有名なプロジェクトのドキュメントサイトに採用されていましたが、2024 年も採用例は増え続けています。すべてを列挙することは難しいですが、たとえば以下のようなプロジェクトが Starlight を採用しています:

  • Cloudflare Docs: Cloudflare の公式ドキュメント
  • jscodeshift: Meta が作成している Codemod 作成のためのツールキット
  • Style Dictionary: Amazon が作成しているデザイントークンのビルドシステム
  • vlt /vōlt/: isaacs 等により作成された新たなパッケージ管理ツール

Starlight の UI は日本語を含む多言語対応も進んでいるため、日本語のドキュメントサイトを作成する際にも適しています。ドキュメントサイトを構築することになった場合はぜひ Starlight を検討してみてください。

https://starlight.astro.build/

Clack と Bombshell

2024 年 6 月、Astro の co-creator である Nate Moore 氏がコアメンバーから離脱することを発表しました:

https://x.com/n_moore/status/1798030024525885888

これに伴い、彼が以前から進めていた CLI ツール作成用フレームワークである Clack にこれから注力していくことも明かされました。そして 10 月には Bombshell というブランディングのもとで彼のプロジェクトが進められていくことも発表され、Clack も Bombshell の一部としてリポジトリが移管されました:

https://x.com/bombshell_dev/status/1849600726734971299
https://github.com/bombshell-dev/clack

Clack ではテキスト入力や複数選択、スピナーなど CLI アプリ向けの入力コンポーネントが複数提供されており、それらを組み合わせることによりインタラクティブかつリッチな CLI アプリケーションを簡単に作成することができます。Clack のデモアプリが https://www.clack.cc/ に公開されていますが、こちらを参照してもらうとどういったものが作成できるかイメージが湧くはずです:

Clack のデモアプリ

まだ Clack のドキュメントなどは十分に整備などされていませんが、すでに

といった有名なプロジェクトにも採用されています。Clack を含めた Bombshell プロジェクトのサイトは以下からアクセスできますので、気になった方は Discord などにも参加し情報収集してみてください:

https://bomb.sh/

その他

Astro Together

2024 年の 5 月 28 日、カナダのモントリオールにて、Astro 初となるオフラインのミートアップが開催されました。以下のブログ記事に概要や当日の写真が掲載されており、イベントの雰囲気を感じることができます:

https://astro.build/blog/astro-together-montreal/

また、イベント内での発表は以下の YouTube にまとめられています。Fred K. Schott 氏が Astro の現状と未来について語り、Ben Holmes 氏がデモを交え Astro Actions を発表し、Matthew Phillips 氏が v4.10 の変更点について解説し、最後に Sarah Rainsberger 氏が Astro の Docs や Starlight、コミュニティへの想いを述べる、という流れとなっています:

https://www.youtube.com/playlist?list=PL8Qn4kutqAEsxDfIjyD-sxNnxJ4WkuV0H

本イベントに合わせ複数のブログ記事も公開されました:

https://astro.build/blog/future-of-astro-zero-js-view-transitions/
https://astro.build/blog/future-of-astro-content-layer/
https://astro.build/blog/future-of-astro-server-islands/

なお、筆者が YouTube 動画を視聴しながらダラダラと感想などを述べたスクラップも存在するため、一応ここにリンクを貼っておきます:

https://zenn.dev/morinokami/scraps/f616027f93e61f

Bluesky

Astro の Bluesky アカウントが作成されました:

https://bsky.app/profile/astro.build

また、Bluesky には Starter Pack という、複数のユーザーを何らかの観点からパッケージングする機能があり、これを使うとその Starter Pack に含まれるユーザーを一括でフォローすることなどができるのですが、Astro 公式の Starter Pack も存在しています。Astro 関連の人々を一気に見つけることができるため、こちらもぜひ活用してみてください:

https://bsky.app/starter-pack/astro.build/3la4wq3fb7x24

公式デプロイパートナーとしての Netlify

Netlify が Astro の公式デプロイパートナーとなりました:

https://astro.build/blog/netlify-official-deployment-partner/

これにより、Netlify から毎月 $12,500 が Astro の開発に寄付されることになりました。また、上の記事の発表時点において、Netlify が Server Islands の開発を支援していることなどについても触れられています。

昨年は Vercel が公式ホスティングパートナーとなったことがアナウンスされましたが、現在はドキュメントに記載されているスポンサーのリストに Vercel の名前がないため、おそらく Vercel の代わりに Netlify がインフラ面でのパートナーとなったものと思われます[3]

また、Netlify が提供する開発者向けのプラットフォームサイトも Astro により構築・運用されています:

https://developers.netlify.com/

公式オンラインエディターパートナーとしての Google IDX

Google IDX が Astro の公式オンラインエディターパートナーとなりました:

https://astro.build/blog/idx-official-online-editor-partner/

Google IDX の正式名称は Project IDX だと思われますが、これは StackBlitz のようなオンラインの開発環境を提供するサービスです[4]。Google が提供するサービスであるため、GeminiGoogle Cloud などと連携可能な点が特徴となっています。Google の David East 氏がこのプロジェクトのリード DevRel を務めていますが、彼は以前に Firebase の開発者であったときから Astro と関わっており、昨年は Firebase のブログを Astro によってリニューアルするプロジェクトを進めていました:

https://astro.build/case-studies/firebase/
https://firebase.blog/

このパートナシップ提携により、IDX から毎月 $10,000 が Astro の開発に寄付されることになりました。

Biome v1.6.0

JavaScript や JSON、CSS など、複数の言語に向けて Formatter や Linter 機能を提供する Biome が、v1.6 において Astro を部分的にサポートするようになりました:

https://biomejs.dev/blog/biome-v1-6/

v1.6 では、Astro だけではなく VueSvlete などに対しても部分的なサポートを開始しましたが、Astro に関してはコードフェンス(---)内のスクリプト部分のみがサポート対象となります。設定方法などについて詳しくは、Biome の Language support のページを参照してください:

https://biomejs.dev/internals/language-support/

また、上で述べた Storefront プロジェクトにおいても Biome が使用されているため、そちらも導入の際の参考となるはずです。

Clerk Astro SDK

ユーザー認証に関するプラットフォームやコンポーネントライブラリなどを提供する Clerk が、Astro 向けの SDK をリリースしました:

https://clerk.com/changelog/2024-07-18-clerk-astro

筆者はまだ使用経験はありませんが、この記事によるとサインイン用の Astro コンポーネントや、ミドルウェアにおいてページへのアクセス可否を判定するための clerkMiddleware 関数など、Astro でのユーザー認証をサポートするための様々な機能が提供されているようです。Astro における認証というと Lucia などのライブラリも有名ですが、Clerk はインフラも含めた総合的なソリューションに近い選択肢であり、選択の幅が広がることは歓迎すべきでしょう。

実際に使用を検討する際には、以下の Clerk Astro SDK の公式ドキュメントも参照してください:

https://clerk.com/docs/references/astro/overview

TutorialKit

TutorialKit は、StackBlitz が開発しているチュートリアル作成ツールです。内部では Astro が使用されており、StackBlitz の既存資産である WebContainer API を援用することで、ブラウザ内で完結するインタラクティブなチュートリアルを簡単に作成することができます。以下のデモチュートリアルを開くと、作成できるものの雰囲気がつかめるはずです:

https://demo.tutorialkit.dev/

具体的な使い方については以下の公式サイトを参照してください:

https://tutorialkit.dev/

IKEA、Porsche

多くのウェブサイトで Astro が導入されていますが、その中でも IKEA や Porsche などの大手企業による Astro の採用は SNS 等で話題となりました:

https://www.ikea.com/
https://www.porsche.com/usa/

IKEA のサイトは View Transition が効果的に使われており、サイト内を移動していて非常に楽しいです。また Porsche のサイトは Astro の上で Vue を動かすなど、Islands Architecture を積極的に活用しているようです。これらは Astro の採用例のほんの一部であり、筆者が把握していない素敵なサイトは無数にあるはずです。そうしたサイトをご存知の方はコメント欄などでぜひ教えてください!

2025 年の展望

Astro にはパブリックな Project Roadmap があり、そこで今後の開発方針などが議論されています。ロードマップには 4 つの段階があり、各段階の内容は以下のようになっています:

  • Stage 1: Proposal (提案)
  • Stage 2: Accepted Proposal (提案が承認された)
  • Stage 3: RFC & Development (RFC の作成と開発)
  • Stage 4: Ship it! (リリース)

つまり、Astro に今後どのような機能が追加されるかについて知るためには、ステージ 2 と 3 の段階にある提案内容を確認すればいいことになります。

具体的な提案内容を確認するには、以下の Public Roadmap という Project にアクセスします:

https://github.com/orgs/withastro/projects/11

この記事を書いている時点では、以下の 6 つの提案が Stage 2 と 3 となっています:

Container API と SVG コンポーネントについてはこの記事や昨年の記事においてすでに触れているため、ここでは他の提案内容について簡単に紹介します。

Sessions

セッションは、ログイン状態やショッピングカートなど、特定のユーザーに紐づく一時的なデータを保持するための仕組みです。同様の仕組みを達成するために、これまではユーザー側で Cookie や Local Storage などを利用する必要がありましたが、この提案により Astro 組み込みの方式でセッションを扱うことが可能となります。セッションに紐づくデータはサーバーサイドで管理され、クライアントにはセッション ID のみがクッキーとして送信されるため、セキュリティ上のリスクも軽減されるでしょう。

セッションはすでに実験的な機能として v5.1 において導入されています:

https://astro.build/blog/astro-510/
https://docs.astro.build/en/reference/experimental-flags/sessions/

セッションを使用するには、Astro.session オブジェクトの getset メソッドを使用します。Astro ページやコンポーネント、エンドポイント、アクション、ミドルウェアなど、様々な場所でセッションにアクセスできます。以下は上の記事にある、セッションのカートデータを取得・更新する例となります:

src/components/CartButton.astro
---
export const prerender = false;
const cart = await Astro.session.get("cart");
---

<a href="/cart">🛒 {cart?.length ?? 0} items</a>
src/actions/addToCart.ts
import { defineAction } from "astro:actions";
import { z } from "astro:schema";

export const server = {
  addToCart: defineAction({
    input: z.object({ productId: z.string() }),
    handler: async (input, context) => {
      const cart = await context.session.get("cart");
      cart.push(input.productId);
      await context.session.set("cart", cart);
      return cart;
    },
  }),
};

セッションデータの保存先は、実験的な機能である現状では driver という設定値を通じて手動で指定する必要があります。たとえば以下は、Node.js 環境にデプロイした場合に使用可能なファイルシステムドライバーを指定する例です:

astro.config.mjs
{
    adapter: node({ mode: "standalone" }),
    experimental: {
      session: {
        driver: "fs",
      },
    },
  }

使用可能なドライバーは環境ごとに異なっており、Cloudflare KV や Redis などのドライバーを選択することもできます。ドライバーのリストについては、Astro Sessions が内部で使用している unstorage のドキュメントを参照してください:

https://unstorage.unjs.io/drivers

なお、ドライバーを手動で設定する必要があるのは、これがあくまでまだ実験的な機能であるためです。安定版としてリリースされる際には、アダプター側が適切なドライバーを自動的に選択するようになることが予定されています。機能に対するフィードバックも募集されているため、実際に使用してみて問題点や改善点などがあれば、ぜひ https://github.com/withastro/roadmap/pull/1055 などで報告してみてください。

Responsive Images

画像はユーザーへの印象を左右するとても重要な要素であり、サイト制作には欠かせないものであるにも関わらず、その扱いはとても難しいものです。スクリーンのサイズや解像度、画像フォーマットなど、開発者はさまざまな要素を考慮しながら画像を適切に画面に表示する必要があります。既存の <Image> コンポーネントは様々なオプションを提供し、こうした複雑な状況に対し柔軟に対応できるように設計されてはいますが、開発者の負担は小さくありません。

この提案では、新たに layout というプロパティを追加することにより、srcsetsizes などの値を自動生成し、画像の扱いに関するベストプラクティスを開発者が楽に享受できるようにすることを目指します。すでに v5 において実験的な機能として導入済みであり、ドキュメントも存在しているため、気になった方は手元で試してみるとよいでしょう:

https://docs.astro.build/en/reference/experimental-flags/responsive-images/

Fonts

ウェブサイトにおいてフォントは基本的な構成要素ですが、フォントを扱うための組み込みの方式が現在の Astro には存在していません。フォントの扱いに関するドキュメントはあるものの、依然として開発者は「どこから」あるいは「どのように」フォントを読み込むべきかについて自ら選択する必要があります。こうした選択の手間を排除し、フォントに関するベストプラクティスを Astro に組み込むことを目的とした提案がこの Fonts というシンプルなタイトルの提案です。

まだ不確定要素もあり、機能としての実装には至っていないようですが、RFC には設定例なども掲載されているため、興味がある方は詳細を確認してみてください。

Development & Production Databases for Astro DB

astro db push --remote は、現在 .env ファイルからのみ ASTRO_DB_URL を取得しますが、これを .env.development.env.production など環境ごとのファイルから取得できるようにするための提案のようです。

おわりに

以上、Astro 界隈で起こった機能追加や出来事について、本年も筆者なりの視点でまとめてみました。2024 年は Actions や Server Islands など、よりアプリケーション寄りの機能追加が目立った印象ですが、今後もこうした傾向が続いていくのかどうかはわかりません。Astro Studio の失敗などもあり、どちらの方向に舵を切るかについて慎重に検討されていると思われますが、次の一手がどのようなものとなるか、ワクワクさせてくれることを期待して待ちたいと思います。それではよいお年を!

脚注
  1. 設定ファイルが src/content/config.ts ではなく src/content.config.ts であることに注意してください。 ↩︎

  2. ただし、筆者がこの記事を書いている際に試してみたところ、Astro v5 においては Vitest が正常に動作していないようでした。関連する Issue として https://github.com/withastro/astro/issues/12849 がありますが、これが解決するまでは v4 系で このプロジェクトを確認するようにしてください。 ↩︎

  3. 公式サイトも Netlify にデプロイされているようです。 ↩︎

  4. なお、HTML を確認すればわかりますが、IDX のトップページも Astro により作成しているようです。 ↩︎

Discussion