🍜

Astro ゆく年くる年

2023/12/31に公開

はじめに

Astro は、コンテンツが豊富なウェブサイトの作成に適したウェブフレームワークです。CMS や Markdown から得たデータを取得し静的サイトをビルドする Static Site Generator のように使うこともできますが、一方で Islands Architecture を背景に ReactSvelte など好みの UI フレームワークを使って動的な要素をページに追加することも可能です。また、SSRMiddlewareEndpoints などを活用し、サーバーサイドでも動作する本格的なアプリケーションの作成も可能です。Astro についてより詳しくは、公式ドキュメントの Why Astro? やその日本語訳などを参照してください。

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

いくつかの指標

バージョンの推移

年初には v1.9.0 であったバージョンは、年末には v4.0.8 となりました。また、数が多すぎるためその一覧は以下のアコーディオン内に隠しますが、beta 版も含めると、2023 年のリリースの総数は 175 でした。およそ 2 日に 1 回のペースでリリースされていたことになります。なお、これは astro パッケージのみの話であり、関連する @astrojs/react など他のインテグレーションを含めるとさらに多くなります。

2023 年に公開されたリリースタグと公開日時の一覧
リリースタグ 公開日時
astro@4.0.8 2023-12-27T18:36:11Z
astro@4.0.7 2023-12-20T17:41:03Z
astro@4.0.6 2023-12-15T21:27:42Z
astro@4.0.5 2023-12-14T14:02:44Z
astro@4.0.4 2023-12-11T11:59:07Z
astro@4.0.3 2023-12-06T20:11:04Z
astro@4.0.2 2023-12-06T00:48:55Z
astro@4.0.1 2023-12-05T14:46:28Z
astro@4.0.0 2023-12-05T13:40:58Z
astro@4.0.0-beta.7 2023-12-04T20:46:31Z
astro@4.0.0-beta.6 2023-12-04T20:21:26Z
astro@4.0.0-beta.5 2023-12-04T18:05:09Z
astro@4.0.0-beta.4 2023-12-01T21:31:34Z
astro@4.0.0-beta.3 2023-12-01T19:14:24Z
astro@3.6.4 2023-11-30T14:26:28Z
astro@4.0.0-beta.2 2023-11-29T18:52:10Z
astro@3.6.3 2023-11-28T21:32:29Z
astro@3.6.2 2023-11-28T16:09:43Z
astro@4.0.0-beta.1 2023-11-28T14:54:55Z
astro@3.6.1 2023-11-27T15:36:28Z
astro@4.0.0-beta.0 2023-11-27T18:01:44Z
astro@3.6.0 2023-11-22T14:15:42Z
astro@3.5.7 2023-11-21T21:45:50Z
astro@3.5.6 2023-11-21T14:53:43Z
astro@3.5.5 2023-11-16T13:52:31Z
astro@3.5.4 2023-11-14T15:22:31Z
astro@3.5.3 2023-11-12T04:41:01Z
astro@3.5.2 2023-11-10T16:40:05Z
astro@3.5.1 2023-11-10T14:11:38Z
astro@3.5.0 2023-11-09T17:51:28Z
astro@3.4.4 2023-11-08T07:53:16Z
astro@3.4.3 2023-11-02T18:15:32Z
astro@3.4.2 2023-11-01T17:24:45Z
astro@3.4.1 2023-11-01T13:25:56Z
astro@3.4.0 2023-10-26T15:37:12Z
astro@3.3.4 2023-10-24T16:28:53Z
astro@3.3.3 2023-10-23T09:24:45Z
astro@3.3.2 2023-10-18T12:33:22Z
astro@3.3.1 2023-10-16T22:00:37Z
astro@3.3.0 2023-10-12T14:46:08Z
astro@3.2.4 2023-10-10T14:33:22Z
astro@3.2.2 2023-10-02T15:58:27Z
astro@3.2.1 2023-10-02T08:37:13Z
astro@3.2.0 2023-09-28T18:14:50Z
astro@3.1.4 2023-09-25T19:57:21Z
astro@3.1.3 2023-09-25T10:31:05Z
astro@3.1.2 2023-09-21T18:34:21Z
astro@3.1.1 2023-09-19T09:23:28Z
astro@3.1.0 2023-09-14T16:46:28Z
astro@3.0.13 2023-09-12T18:31:40Z
astro@3.0.12 2023-09-08T14:09:49Z
astro@3.0.11 2023-09-08T11:57:51Z
astro@3.0.9 2023-09-06T14:00:02Z
astro@3.0.10 2023-09-06T21:38:11Z
astro@3.0.8 2023-09-04T09:12:34Z
astro@3.0.7 2023-09-01T23:28:28Z
astro@3.0.6 2023-09-01T14:21:56Z
astro@3.0.5 2023-08-31T17:44:36Z
astro@3.0.4 2023-08-31T15:38:30Z
astro@3.0.3 2023-08-30T20:32:36Z
astro@3.0.2 2023-08-30T16:15:43Z
astro@3.0.1 2023-08-30T14:37:22Z
astro@3.0.0 2023-08-30T11:40:55Z
astro@2.10.15 2023-08-29T17:29:47Z
astro@3.0.0-rc.9 2023-08-29T15:00:36Z
astro@3.0.0-rc.11 2023-08-29T19:52:25Z
astro@3.0.0-rc.10 2023-08-29T18:21:16Z
astro@3.0.0-rc.8 2023-08-28T16:25:28Z
astro@3.0.0-rc.7 2023-08-25T18:12:11Z
astro@3.0.0-rc.6 2023-08-25T16:55:02Z
astro@2.10.14 2023-08-24T14:06:52Z
astro@2.10.13 2023-08-23T14:14:52Z
astro@3.0.0-rc.5 2023-08-22T14:21:46Z
astro@2.10.12 2023-08-18T21:15:03Z
astro@2.10.11 2023-08-18T15:38:43Z
astro@2.10.10 2023-08-18T14:34:39Z
astro@3.0.0-beta.4 2023-08-18T16:51:52Z
astro@3.0.0-beta.3 2023-08-18T15:50:03Z
astro@2.10.9 2023-08-15T21:14:15Z
astro@2.10.8 2023-08-15T14:38:25Z
astro@3.0.0-beta.2 2023-08-14T13:48:50Z
astro@2.10.7 2023-08-11T18:04:09Z
astro@2.10.6 2023-08-11T15:25:07Z
astro@3.0.0-beta.1 2023-08-11T15:17:21Z
astro@2.10.5 2023-08-10T13:28:06Z
astro@2.10.4 2023-08-09T20:33:57Z
astro@2.10.3 2023-08-07T21:23:03Z
astro@2.10.2 2023-08-07T18:53:40Z
astro@2.10.1 2023-08-03T19:18:43Z
astro@2.10.0 2023-08-03T14:57:06Z
astro@3.0.0-beta.0 2023-08-03T15:20:51Z
astro@2.9.7 2023-08-01T15:41:07Z
astro@2.9.6 2023-07-28T16:36:44Z
astro@2.9.5 2023-07-28T13:15:00Z
astro@2.9.4 2023-07-27T19:36:00Z
astro@2.9.3 2023-07-25T19:18:42Z
astro@2.9.2 2023-07-24T09:11:33Z
astro@2.9.1 2023-07-21T20:39:57Z
astro@2.9.0 2023-07-20T16:12:57Z
astro@2.8.5 2023-07-19T07:34:53Z
astro@2.8.4 2023-07-18T08:17:05Z
astro@2.8.3 2023-07-14T14:47:10Z
astro@2.8.2 2023-07-13T13:45:34Z
astro@2.8.1 2023-07-11T14:29:25Z
astro@2.8.0 2023-07-06T15:18:34Z
astro@2.7.4 2023-07-05T06:49:32Z
astro@2.7.3 2023-07-03T12:56:09Z
astro@2.7.2 2023-06-29T09:16:39Z
astro@2.7.1 2023-06-27T12:45:28Z
astro@2.7.0 2023-06-22T14:09:03Z
astro@2.6.6 2023-06-20T14:35:22Z
astro@2.6.5 2023-06-19T15:39:15Z
astro@2.6.4 2023-06-13T20:58:58Z
astro@2.6.3 2023-06-10T17:56:44Z
astro@2.6.2 2023-06-09T05:42:42Z
astro@2.6.1 2023-06-06T21:27:33Z
astro@2.6.0 2023-06-06T15:34:44Z
astro@2.5.7 2023-06-02T14:53:25Z
astro@2.5.6 2023-05-30T20:56:29Z
astro@2.5.5 2023-05-23T20:26:15Z
astro@2.5.4 2023-05-23T15:09:19Z
astro@2.5.3 2023-05-22T19:18:35Z
astro@2.5.2 2023-05-22T13:50:34Z
astro@2.5.1 2023-05-20T16:02:47Z
astro@2.5.0 2023-05-18T16:34:39Z
astro@2.4.5 2023-05-11T19:16:10Z
astro@2.4.4 2023-05-09T21:39:31Z
astro@2.4.3 2023-05-08T17:19:11Z
astro@2.4.2 2023-05-05T17:25:10Z
astro@2.4.1 2023-05-04T20:20:03Z
astro@2.4.0 2023-05-04T16:52:18Z
astro@2.3.4 2023-05-02T19:15:42Z
astro@2.3.3 2023-05-01T15:00:53Z
astro@2.3.1 2023-04-25T14:51:18Z
astro@2.3.0 2023-04-13T18:44:29Z
astro@2.2.3 2023-04-12T12:54:31Z
astro@2.2.2 2023-04-11T17:12:26Z
astro@2.2.1 2023-04-07T21:27:28Z
astro@2.2.0 2023-04-05T17:41:37Z
astro@2.1.9 2023-03-31T14:35:18Z
astro@2.1.8 2023-03-28T17:22:06Z
astro@2.1.7 2023-03-24T17:19:50Z
astro@2.1.6 2023-03-24T05:51:53Z
astro@2.1.5 2023-03-22T12:55:43Z
astro@2.1.4 2023-03-21T12:05:22Z
astro@2.1.3 2023-03-13T20:08:31Z
astro@2.1.2 2023-03-08T22:40:45Z
astro@2.1.1 2023-03-08T21:12:12Z
astro@2.1.0 2023-03-07T19:52:37Z
astro@2.0.18 2023-03-06T16:33:06Z
astro@2.0.17 2023-03-02T20:37:19Z
astro@2.0.16 2023-02-27T13:58:04Z
astro@2.0.15 2023-02-23T20:52:43Z
astro@2.0.14 2023-02-17T18:46:51Z
astro@2.0.13 2023-02-16T19:38:51Z
astro@2.0.12 2023-02-15T13:08:01Z
astro@2.0.11 2023-02-13T20:28:34Z
astro@2.0.10 2023-02-09T19:30:14Z
astro@2.0.9 2023-02-08T19:13:53Z
astro@2.0.8 2023-02-07T22:09:41Z
astro@2.0.7 2023-02-07T18:47:32Z
astro@2.0.6 2023-02-02T20:40:29Z
astro@2.0.5 2023-02-01T14:01:20Z
astro@2.0.4 2023-01-30T20:31:29Z
astro@2.0.2 2023-01-26T18:56:17Z
astro@2.0.1 2023-01-25T02:21:53Z
astro@2.0.0 2023-01-24T16:39:43Z
astro@2.0.0-beta.4 2023-01-23T21:14:23Z
astro@2.0.0-beta.3 2023-01-19T16:02:38Z
astro@2.0.0-beta.2 2023-01-12T16:43:14Z
astro@1.9.2 2023-01-11T18:38:21Z
astro@2.0.0-beta.1 2023-01-06T18:02:41Z
astro@1.9.1 2023-01-05T14:44:22Z
astro@1.9.0 2023-01-03T15:47:42Z
astro@2.0.0-beta.0 2023-01-03T22:25:59Z

8 月 30 日に v3.0 がリリースされ、それから約 3 ヶ月後の 12 月 5 日には v4.0 がリリースされており、メジャーアップデートのペースがやや早かったように感じますね。Astro の co-creator である Matthew Phillips によると、v4.0 における大きな変更の一つに Vite 5 へのアップデートがあり、これはもともと v3.0 に含まれる予定だったのが、Vite 5 のリリースが遅れてしまい、一方で v3.0 の目玉機能である View Transitions を早くリリースしたかったため、まず先に v3.0 をリリースし、その後に v4.0 で Vite 5 を含めるという流れとなり、結果的に v3.0 と v4.0 のリリースが短期間で連続してしまった、という事情があったようです。

GitHub スター数の推移

https://star-history.com によると、2023 年の年初の GitHub スター数は 23,000 程度ですが、年末には 38,000 程度にまで増加しました。約 6 割強の増加となっています。

Star History Chart

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

https://npmtrends.com によると、2023 年 1 月 1 日における週間のダウンロード数は 42,431 ですが、12 月 17 日には 189,603 にまで増加しました。約 4.5 倍の増加となっています。ほぼ SolidJS と同じように推移しているのが不思議ですね。

npm trends

https://npmtrends.com/astro

機能の追加・変更

ここでは、2023 年におこなわれた Astro への機能追加や変更点について、筆者が重要だと感じたものをいくつかピックアップして紹介していきます。

Content Collections

Astro 2.0 で導入された Content Collections は、Markdown などで記述されたコンテンツを型安全に取り扱うための仕組みです。Zod を利用してコンテンツのフロントマターなどのスキーマを定義してそれをコレクションとして登録することで、プログラムからコンテンツのデータを取り扱う際にエディター上で補完を効かせたり、スキーマによりコンテンツをバリデーションすることでデータが型に合致することを保証したりできます。

具体的には、たとえば

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

というディレクトリ構造によりブログ記事のデータを管理しているとします。さらに、以下のように各ブログ記事のフロントマターの内容をスキーマにより定義しているとします:

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,
};

このとき、.astro ファイル内で以下のようにコンテンツを取得できるようになります:

src/pages/index.astro
---
import { getCollection } from 'astro:content';
const blogEntries = await getCollection('blog');
---

...

ここで、blogEntries 内の各値は、スキーマで定義された titletagsimage というプロパティをもつオブジェクトを含んだデータの配列となります。getCollection の返り値は TS の型によって表現されているため、エディター上でのホバーによる内容の確認や、コード補完なども問題なく可能です。また、個別のデータを取得するための getEntry など、getCollection 以外のクエリの方法も存在します。

さらに、たとえば post-1.md に必須のタイトルが設定されていない場合は、以下のようなわかりやすいエラーが表示されます:

InvalidContentEntryFrontmatterError

以上のようにして、Content Collections により、Markdown コンテンツなどを扱う際の諸々の手間が解消されます。筆者は以前、Next.js において同様の仕組みが欲しいと思い、その際は Contentlayer などを駆使して実現していたため、その後 Astro に Content Collections が実装された際にはとても嬉しく感じたことを覚えています。

Content Collections について、詳しくは以下のドキュメントも参照してください:

https://docs.astro.build/en/guides/content-collections/

Hybrid Rendering

Astro では以前から SSR がサポートされていましたが、v2.0 で Hybrid Rendering という、一部のページを SSR でレンダリングし、一部のページを SSG でレンダリングするという機能が追加されました。これにより、たとえばランディングページのみ静的に事前レンダリングしておくなど、サイト内の各ページに適したレンダリング方法を選択することができるようになりました。

v2.0 の時点では、「デフォルトを SSR とし、特定のページにおいてそれをオプトアウトする」という方式のみ存在していました。すなわち、astro.config.mjs にて

astro.config.mjs
export default defineConfig({
  output: 'server',
  ...
});

とすると SSR がデフォルトとなり、事前レンダリングしたい特定のページにて

---
export const prerender = true;
---

...

と記述することで、ページを事前レンダリングできました。

一方、「SSG をデフォルトとし、特定のページにおいてそれをオプトアウトする」という方式が存在しないのは、Astro の出自が静的サイトジェネレーターであることを考えると奇妙である、という声がユーザーから多く挙がったため、v2.6 にて

astro.config.mjs
export default defineConfig({
  output: 'hybrid',
  ...
});

とし、

---
export const prerender = false;
---

...

とする逆の挙動もサポートされるようになりました。

Astro のレンダリングモードについて、詳しくは以下のドキュメントも参照してください:

https://docs.astro.build/en/core-concepts/rendering-modes/

Middleware

v2.6 で Middleware がサポートされました。Middleware は、リクエストやレスポンスをインターセプトし、何らかの処理を動的に差し込むための機能です。

Middleware を定義するには、src/middleware.js を作成し、そこから onRequest 関数を export します。以下は、Middleware でセットした値をページ側で参照する簡単な例です:

src/middleware.js
export function onRequest ({ locals, request }, next) {
    locals.title = "New title";
    return next();
};
src/pages/index.astro
---
const data = Astro.locals;
---

<h1>{data.title}</h1>

上からわかるように、リクエスト固有のデータは locals を経由して Astro コンポーネントやエンドポイントに渡すことができます。

「リクエストをバリデーションし、auth 処理をおこない、...」などのように、複数の Middleware を連続して呼び出すための sequence 関数なども用意されています。

Middleware に関するドキュメントは以下となります:

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

Custom Client Directives

Astro では、React などの UI ライブラリで作られたコンポーネントを Astro コンポーネントの中に埋め込むことができますが、デフォルトでは JS はすべて消去され、コンポーネントはインタラクティビティを失います。クライアントサイドでコンポーネントをインタラクティブにするためには、client:loadclient:visible などの Client Directives を付加する必要があります:

<MyReactComponent client:load >

このように、ディレクティブによりコンポーネントがインタラクティブになる、つまりハイドレーションされるタイミングをコントロールするのですが、すでに用意されているディレクティブの中から選択することしか以前はできませんでした。しかし、ディレクティブを追加したいという要望がコミュニティから多く挙がったため、v2.6 において Custom Client Directives がサポートされるようになりました (v2.5 では experimental でした)。これにより、ユーザーは独自のクライアントディレクティブを定義できるようになりました。

例として、「クリックされた際に JS をロードしハイドレートする」ようなディレクティブは以下のようになります:

astro.config.mjs
import { defineConfig } from 'astro/config';
import clickDirective from './astro-click-directive/register.js'

export default defineConfig({
  integrations: [
    clickDirective()
  ],
});

ここではまず astro-click-directive/register.js に定義された clickDirective というインテグレーションを設定ファイルに追加しています。このインテグレーションは以下のように定義されています:

astro-click-directive/register.js
/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "client:click",
  hooks: {
    "astro:config:setup": ({ addClientDirective }) => {
      addClientDirective({
        name: "click",
        entrypoint: "./astro-click-directive/click.js",
      });
    },
  },
});

インテグレーションでは、サーバーの起動時やビルドの終了時など、様々なタイミングにおいて処理を差し込むことができるのですが、ここではアプリケーションの初期化時に呼ばれる astro:config:setup フックにおいて addClientDirective を呼び出し、ディレクティブをアプリケーションに登録しています。ここでは名前とその実体の場所を指定していることがわかると思います。ディレクティブの具体的な定義は以下のようになります:

astro-click-directive/click.js
/**
 * Hydrate on first click on the window
 * @type {import('astro').ClientDirective}
 */
export default (load, opts, el) => {
  window.addEventListener('click', async () => {
    const hydrate = await load()
    await hydrate()
  }, { once: true })
}

このようにして、Custom Client Directives により、開発者が独自のディレクティブを定義することができるようになりました。

Redirects

v2.9 で、Astro の設定ファイルにリダイレクトのルールを記述できるようになりました。以前はデプロイ先のプラットフォームに応じてリダイレクトの設定をおこなう必要がありましたが、これにより統一的にリダイレクトの設定を書けるようになりました。

たとえば以下の設定により、/old-page にアクセスしたユーザーをステータスコード 302 で /new-page にリダイレクトすることができます:

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

export default defineConfig({
  redirects: {
    '/old-page': {
      status: 302,
      destination: '/new-page'
    }
  }
});

Redirects に関するドキュメントは以下を参照してください:

https://docs.astro.build/en/core-concepts/routing/#redirects

Astro View Transitions

Astro では、MPA としてサイトをビルドするというその性質上、ページ遷移の際にページ全体のリロードが発生します。SPA のようにページの一部分を切り替えるスムーズな遷移に慣れている一部のユーザーがこうした挙動に対して不満をもっていたため、Astro チームはこうした MPA サイトとページ遷移のスムーズさの両立という難問を解決する術を以前から検討していたようです。そして、これを解決するために目をつけた仕組みが View Transitions API です。View Transitions API を使えば、ブラウザのネイティブな機能を利用しながら、MPA であっても画面遷移におけるスムーズで連続性のある視覚効果を実現できます。

View Transitions API が Chrome 111 などにおいて搭載され始められると、Astro はいち早く View Transitions API への対応を始め、v3.0 における目玉機能として正式にサポートを開始しました。Astro の View Transitions へのサポートによりどういった表現が可能となるかについては、Maxi Ferreira による以下のデモなどが参考になると思います (Chrome など View Transitions に対応しているブラウザで挙動を確認してみてください):

https://astro-records.pages.dev/
https://astro-movies.pages.dev/
https://live-transitions.pages.dev/
https://astro-3d-view-transitions.pages.dev/

Astro で View Transitions を利用する最も簡単な方法は、以下のように各ページの <head>ViewTransitions コンポーネントを追加することです。これだけで、Astro は遷移元のページと遷移先のページの類似度からアニメーションを自動的に設定し、また非対応ブラウザへのフォールバックも自動的におこなってくれます:

src/components/CommonHead.astro
---
// 各ページ共通の head
import { ViewTransitions } from 'astro:transitions';
---

<!-- その他の title や meta、link など -->
<ViewTransitions />

これは最もベーシックな使用法ですが、もちろん様々なカスタマイズも可能です。詳しくは公式ドキュメントを確認してください:

https://docs.astro.build/en/guides/view-transitions/

また、Chrome チームと Astro チームの View Transitions に関するコラボレーションに関する以下の文章も、個人的に興味深いものでした:

https://developer.chrome.com/blog/astro-view-transitions/

<Image /> コンポーネント

v2.1 で experimental として導入されていた、画像をレンダリングするための <Image /> コンポーネントが、v3.0 で正式に追加されました。この機能は、画像自体の最適化と、適切な属性の設定を自動的におこなうことを責務とします。

たとえば、

src/components/MyComponent.astro
---
import { Image } from 'astro:assets';
import myImage from '../assets/my_image.png'; // 1600x900 の画像
---

<Image src={myImage} alt="A description of my image." />

というコンポーネントは、以下のような HTML に変換され、最適化された画像がレンダリングされます:

<img
  src="/_astro/my_image.hash.webp"
  width="1600"
  height="900"
  decoding="async"
  loading="lazy"
  alt="A description of my image."
/>

CLS を防止するために幅や高さが自動的に検出され、遅延読み込みのための loading="lazy" なども自動的に設定されていることがわかります。

その他のプロパティや、リモート画像の扱いなどについては、公式ドキュメントを確認してください:

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

<Picture /> コンポーネント

複数の画像フォーマットやサイズを扱うための <Picture /> コンポーネントが v3.3 で追加されました。これにより、たとえば以下のように、複数の画像フォーマットを指定し、ブラウザが適切な画像をレスポンシブに選択できるようになります:

src/components/MyComponent.astro
---
import { Picture } from 'astro:assets';
import myImage from '../assets/my_image.png'; // 1600x900 の画像
---

<Picture src={myImage} formats={['avif', 'webp']} alt="A description of my image." />

上のコンポーネントは、以下のような HTML に変換されます:

<picture>
  <source srcset="/_astro/my_image.hash.avif" type="image/avif" />
  <source srcset="/_astro/my_image.hash.webp" type="image/webp" />
  <img
    src="/_astro/my_image.hash.png"
    width="1600"
    height="900"
    decoding="async"
    loading="lazy"
    alt="A description of my image."
  />
</picture>

<Picture /> コンポーネントについて詳しくは、ドキュメントを確認してください:

https://docs.astro.build/en/guides/images/#picture-

Page Partials

v3.4 で、ページから <!DOCTYPE html><head> を除いた内容をレンダリングするための仕組みである Page Partials が追加されました。

使い方はシンプルで、partial という変数をページから export するだけです:

---
export const partial = true;
---

<div>This is a partial!</div>

これにより、以下の HTML が出力されます:

<div>This is a partial!</div>

変数を export 可能なファイル形式、たとえば .mdx などでもこの機能は利用可能です。

Prefetch

v3.5 で、従来は @astrojs/prefetch インテグレーションとして提供されていた、リンク先を事前に取得しておく Prefetch 機能が Astro コアに組み込まれました。

以下のように設定ファイルを記述すると、Prefetch が有効化されます:

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

export default defineConfig({
  prefetch: true
})

Prefetch はデフォルトではオプトイン方式です。つまり、事前に取得しておきたい <a> タグに対し、data-astro-prefetch 属性を付与すると、ホバーに応じて Prefetch が実行されます:

<a href="/about" data-astro-prefetch>About</a>

デフォルトではホバーが Prefetch のトリガーとなりますが、その他にも tapviewport などをトリガーとすることも可能です。たとえば、ビューポートに入った際に Prefetch するように上の例を変更したい場合は、以下のように記述します:

<a href="/about" data-astro-prefetch="viewport">About</a>

Prefetch をトリガーするデフォルトのイベントをホバー以外に設定することも可能です:

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

export default defineConfig({
  prefetch: {
    defaultStrategy: 'viewport'
  }
})

また、すべてのリンクを Prefetch するように設定することなども可能です:

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

export default defineConfig({
  prefetch: {
    prefetchAll: true
  }
})

Prefetch について詳しくは、以下のドキュメントを確認してください:

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

Qwik インテグレーション

11 月に Qwik インテグレーションが追加されました。これにより、Astro コンポーネント内で Qwik コンポーネントを使用できるようになりました。

以下のコマンドにより、設定ファイルの更新も含めてインテグレーションの追加をおこなうことができます:

npx astro add @qwikdev/astro

詳細については buider.io のブログも参照してください:

https://www.builder.io/blog/astro-qwik

@astrojs/upgrade コマンド

Astro プロジェクトの依存関係やインテグレーションなどをまとめてアップグレードするための @astrojs/upgrade コマンドが 11 月に追加されました。以前は各パッケージを個別に更新する必要がありましたが、これにより一括で更新できるようになりました。

npx @astrojs/upgrade

ドキュメントもこのコマンドを使うように書き換えられています:

https://docs.astro.build/en/guides/upgrade-to/v4/

Dev Toolbar

v4.0 にて、開発者向けの機能として Dev Toolbar が追加されました。Vercel ToolbarNuxt DevTools などに影響を受けて作成されたものと思われます。

Dev Toolbar は、最新版の Astro であればデフォルトで有効化されています。npx astro dev を実行してブラウザからサイトにアクセスすると、画面下部に Dev Toolbar が表示されるはずです:

The Astro Dev Toolbar

デフォルトでは、以下の機能がツールバーに組み込まれています:

  • Inspect: ページ内の UI コンポーネントアイランドをハイライトする。
  • Audit: ページ内の a11y に関する問題点を検出する。

この他にも現時点で、Sentry と Storyblok がそれぞれ公式のツールバー向けアプリを提供しています:

また、開発者が自らツールバー向けアプリを作成・公開することも可能です:

https://docs.astro.build/en/reference/dev-toolbar-app-reference/

大まかな実装の流れとしては、ツールバー向けのビューの準備やイベントハンドリングの設定などをまずおこない、また Vite サーバー側とも通信が可能なため、ツールバー側か開発サーバー側で何らかのタイミングにおいて必要な処理を実行しツールバー内に反映する、といったものになるかと思います。筆者も、Cloudflare の Quick Tunnels を介してローカルの開発サーバーをインターネットに公開するためのアプリを作成してみましたが、他のアプリを参考にすることで簡単に作成できました:

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

i18n Routing

v3.5 において experimental な機能として追加された i18n Routing が、v4.0 において正式に追加されました。設定ファイルにおいて

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

export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'ja']
  }
})

のようにデフォルト言語やサポート対象の言語などを設定し、pages 以下の構造をこれに合わせることで、各言語に対応するページの相対 URL を取得したり、未翻訳の場合などのフォールバックを設定したりできます。詳しくは、公式ドキュメントの i18n のページを確認してください:

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

関連プロジェクト

2023 年に登場した、Astro に関連するプロジェクトを一部紹介します。

Starlight

https://starlight.astro.build/

Starlight は、Astro の上に構築された、ドキュメントサイト向けのテーマです。5 月 9 日に v0.0.1 がリリースされ、現在の最新版は v0.15.1 となっています。

Starlight を使っているサイトをいくつか紹介します。まず、Astro v4 のリリースに合わせて Astro のドキュメントサイトが刷新されましたが、その際に全面的に Starlight へと移行されました。あるいは、Biome のドキュメントも Starlight で作られています (プロジェクトをリードしている Emanuele Stoppa が Astro チームに属しているため、これは当然かもしれません)。その他にも、たとえば以下のドキュメントなどで使用されています:

  • Class Variance Authority の beta 版: shadcn/ui においてもバリアント管理のために使用されている cva の次期ドキュメント。
  • PartyKit: 複数のユーザーがコラボレーションする、マルチプレイヤーのアプリケーションを作成するためのライブラリ。tldrawStately などでも使われている。
  • Knip: プロジェクト内の不要なファイルや dependencies、exports を見つけるためのツール。

Starlight を使用しているサイトについて詳しくは、GitHub 上の Used by などを確認してください。

基本的には、src/content/docs/.md.mdx などを追加していくだけで、簡単にドキュメントサイトを作成できるようになっています。デフォルトで PageFind によるクライアントサイドで動く全文検索機能が組み込まれている点が特徴的かもしれません。もちろん、様々なカスタマイズi18n もサポートされており (なお、Starlight の UI 文字列の各言語版はデフォルトで組み込まれています)、個別のコンポーネントのオーバーライドなども可能です。個人的には、サイトテーマを Starlight のドキュメントサイト上でプレビューできるテーマカラーエディタが触っていて楽しいため、ぜひ試してみてください。

Astro Docs Docs (AD²)

https://contribute.docs.astro.build/

Astro ドキュメントへの貢献の仕方に関するドキュメントです。一般に、ある程度規模の大きな OSS プロジェクトには、プロジェクトへの貢献の仕方をまとめた Contributing Guideline が (多くの場合 CONTRIBUTING.md という名前で) コードベース内に置かれており、Astro の各プロジェクトにも同様のファイルが置かれています:

Astro ドキュメントも例外ではなく、https://github.com/withastro/docs/blob/main/CONTRIBUTING.md というファイルにプロジェクトに参加するための最低限の記述が存在するのですが、より広範かつ詳細な情報をまとめる場所として AD² が作られたようです。

内容としては、ドキュメントの意義の確認、コントリビューションにおける作法、ドキュメントの書き方や翻訳の仕方など各種のコントリビューションに関する具体的な方法、コントリビューターの役割、レビューの方法、などが記載されています。

なお、少し脱線すると、AD² を主に執筆しているのは Astro の Docs Lead である Sarah Rainsberger という方で、Astro コミュニティの雰囲気の良さは彼女の人柄によるところが大きいと筆者は考えています (もちろん他のメンテナーの方も皆素晴らしい人格者なのですが、彼女は特に、という意味です)。Astro ドキュメントに貢献する場合、レビュアーとして彼女が登場することも多いのですが、どんな PR に対してもユーモアを交えて丁寧に接してくれるので、ドキュメントへの貢献に興味がある方は、ぜひ AD² を読んで PR を送ってみてください。

Lunaria

https://lunaria.dev/

Astro ドキュメントでは、Translation Tracker というシステムにより各言語の翻訳状況をトラッキングしています。このシステムは、以前は独自のスクリプトにより管理されていましたが、コアメンテナーの Yan Thomas による Lunaria というプロジェクトに最近置き換えられました。背景はわからないのですが、想像するに、Starlight などのドキュメントでも同じような仕組みで同じように翻訳状況を管理しており、こうした多重化を避けるために Lunaria が導入されたのではないかと思います。まだアルファ版という雰囲気ですが、今後も Astro ドキュメントの翻訳に関わるプロジェクトとして個人的に注目していきたいです。

その他

公式ホスティングパートナーとしての Vercel

Vercel が Astro の公式ホスティングパートナーとなりました。

https://astro.build/blog/vercel-official-hosting-partner/

これにより、毎月 $5,000 が Astro の開発に寄付されることになりました。

Vercel の VP of Developer Experience である Lee Robinson と Astro の共同創業者である Fred K. Schott による動画も存在します:

https://www.youtube.com/watch?v=9196iQJtK4s

Vercel がホスティングパートナーとなることで開発者にもたらされる恩恵は以下の通りです:

  1. Astro のミドルウェアを Vercel の Edge Middleware として実行できるようになる。
  2. Serverless で実行されるコードを Code Split できるようになる。
  3. Vercel の画像最適化サービスが使用可能となる。

公式モニタリングパートナーとしての Sentry

Senrty が Astro の公式モニタリングパートナーとなりました。

https://astro.build/blog/sentry-official-monitoring-partner/

これにより、毎月 $5,000 が Astro の開発に寄付されることになりました。

また、Astro 4.0 で追加された Dev Toolbar のアプリとして、開発環境向けのモニタリングツールである Spotlight もリリースされています。

https://github.com/getsentry/spotlight

Astro Swag Store

6 月に Astro 公式の Swag Store (グッズのストア) がオープンしました:

https://shop.astro.build/

パーカーや Houston のキーキャップ、帽子など、Astro 好きにはたまらないアイテムが揃っています。

https://shop.astro.build/products/astro-icon-unisex-shirt
https://shop.astro.build/products/key-caps-pack-of-2
https://shop.astro.build/products/astro-logo-curve-bill-snapback-cap

なお、個人的な話を少し書くと、Astro ドキュメントへの貢献に対する報酬として、自分は無料で帽子などを送ってもらえました (日本人では、自分以外にも @kyosuke さんが選ばれています👏)。下でも触れますが、Astro はコントリビューターに対する金銭面も含めたこうしたサポートを定期的におこなっており、モチベーションも高まるため非常にありがたいです。

https://twitter.com/ondemocracy/status/1694985482327986377

Astro Community Showcase

Astro には Community Award という制度があり、Astro に対して重要な貢献をしたコントリビューターが選ばれ、金銭的な報酬を得られるようになっています。以前はブログなどで発表していたのですが、受賞者を紹介するための専用ページができました (なお、一番下にいるのは自分です!!):

https://community.astro.build/

Astro Ecosystem Fund

Astro Ecosystem Fund という、Astro エコシステムのプロジェクトのメンテナーに対して金銭的な支援をおこなうための制度ができました:

https://astro.build/blog/astro-ecosystem-fund/

今後 1 年間で、10 人の開発者に $10000、合計 $100000 が支援される予定です。最初の受賞者は以下の 3 名でした:

Astro だけでなく、多くの企業がこうした OSS 活動へのサポートを拡大しているため、今後こうした支援がますます増えていくのかもしれません。

2024 年の展望

Astro Studio

12 月 9 日、Astro Studio というデータプラットフォームが近々ローンチされることが公式にアナウンスされました。

https://twitter.com/astrodotbuild/status/1733199595231199584

サービスの概要については

https://studio.astro.build/

に記載されており、それによると

Astro Studio is a globally-distributed edge data platform, built for Astro.

とあります。日本語に訳すと「Astro のために作られた、グローバルに分散したエッジデータプラットフォーム」といった意味となりますが、その詳細についてハッキリとは書かれていません。Astro としては初めてのマネージドサービスの提供となり、かなり気合を入れてくることが予想されるため、どのようなサービスとなるか非常に楽しみなところです。

リリース予定は early 2024 とのことです。また、無料枠も用意されているようです。上のリンク先からウェイトリストに登録しておけば、リリース後すぐに使えるようになるはずですので、気になる方は登録しておくと良いでしょう。

Public Roadmap

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

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

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

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

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

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

Container API: render components in isolation

Astro が構造的に抱える問題点として、react-dom/serverpreact-render-to-string などのような、コンポーネントをプログラムから個別にレンダリングするための仕組みが存在しないという点があります。各コンポーネントのレンダリングにおいて Astro.* などの各種 API を利用可能とするために、外部環境であるサイト全体に関するコンテクストを必要とするため、こうした個別のコンポーネントをレンダリングする仕組みが存在しない、というのが筆者の理解です。その結果、コンポーネントを個別に扱うためにはこうしたコンテクストを外部からつなぎ込む必要があり、サードパーティーのライブラリなどがこれをサポートすることは実質的に難しい状況となってしまっています。たとえば Storybook で Astro コンポーネントを表示することなどはできず、2022 年 5 月 30 日に開かれた Issue はいまだ解決しないままとなっています:

https://github.com/storybookjs/storybook/issues/18356

あるいは、Astro コンポーネントをユニットテストすることも現状だとできません。ドキュメントの Testing のページも、Cypress や Playwright でのテスト方法が書かれているのみとなっており、Testing Library などで React コンポーネントをテストするのと同じことは現状できません。

こうした状況を改善するための提案が Container API です。Container API により、プログラムから個別の Astro コンポーネントをレンダリングできるようになります。コード例として示されているのは以下です:

import { AstroContainer } from 'astro/container';
import Component from './components/Component.astro';

const astro = new AstroContainer();
console.log(await astro.renderToString(Component, { props, slots }))

AstroContainer インスタンスの作成時に以下のようなオプションを渡すことも予定されています:

const astro = new AstroContainer({
  mode?: 'development' | 'production';
  site?: string;
  renderers?: Renderer[]
});

renderToString の第二引数には以下のような Astro グローバルが必要とするデータを渡せるようです:

await astro.renderToString(Component, { props, slots, request, params })

まだ正式な RFC が作成されていないため詳細は不明ですが、このような API が作成されることで、Astro コンポーネントを他のフレームワークやライブラリのコンポーネントとある程度同等に扱えるようになるため、夢が膨らみますね。2024 年中に必ずリリースされるとは限りませんが、早期にリリースされることを期待したいです。

Built-in SVG components

SVG を Astro コンポーネントとしてインポートして使えるようにするための提案です。パフォーマンス向上などを目指しつつ、後方互換性を保ちながら SVG の扱いを用意にすることが狙いのようです。

Incremental Builds

v3.5 から experimental として利用可能となっていた、astro build コマンドによる静的サイト生成時においてキャッシュを活用し、ビルド速度を高速化させるための取り組みです。こちらは Stage 3 の提案であり、RFC も作成されています。ビルド速度の問題は Static Generation における典型的な課題であるため、多くのユーザーが待ち望んでいた機能なのではないでしょうか。

上に書いた通り、すでに Astro に機能自体は組み込まれているため、Astro の設定ファイルにおいて experimental.contentCollectionCache を有効化すれば手元で動作確認できます (RFC を読む限り、設定項目の名前は今後変更されそうです)。ただし、筆者が簡単に動作確認した限りでは、まだまだ動作が不安定であり、たとえば数ページのサイトでもビルド時にエラーが発生したりしなかったりという状態であったため、実験的に使ってみるのにとどめておくのが良いかもしれません。

おわりに

以上、2023 年に Astro 界隈で起こった機能追加や出来事について、筆者なりの視点でまとめてみました。View Transitions や Image コンポーネント、Prefetch などにより従来の静的サイトとしての完成度を高めると同時に、Hybrid Rendering や Middleware などを追加してアプリケーション寄りの機能強化も進められており、フレームワークとして充実していく様子が目に見えてわかる一年であったなと思います。それと同時に、ドキュメントサイトを作成するためのサイドプロジェクトである Starlight なども登場し、求められているプロダクトを確実に提供している印象も受けました。年が明けてしばらくすれば Astro Studio についての詳細も明らかにされるでしょうし、とてもワクワクしますね。2024 年も Astro の進化に注目していきたいと思います。

Discussion