Astro v5以降のContent collections 前編 Content collectionsの変更点とローダーの導入
従来、ローカルファイルを柔軟に読み込んでコンテンツとして使用できたAstroが、v5ではヘッドレスCMSやDBaaSなどリモートストレージのデータも扱えるようになりました。この機能の詳細を紹介します。
- カテゴリー
- Webフレームワーク >
- Astro
発行
はじめに
2024年12月にリリースされたAstroのバージョン5(v5)では、コンテンツを柔軟に扱う仕組みであるContent collectionsのアップデートが行われました。
従来のContent collectionsでは、Markdownをはじめとした各種ローカルファイルをコンテンツとして読み込みます。読み込まれたコンテンツは、ファイルタイプに依存しない、統一されたインターフェースで呼び出すことができる、というものでした。
補足:v4以前のContent collections
v4以前のContent collectionsについては以下の記事で解説しています。
この、コンテンツを柔軟に扱う特徴的な仕組みは、Astroがコンテンツベースのフレームワークと呼ばれる所以とも言えます。
今回のアップデートでは、コンテンツとして読み込むデータに、ヘッドレスCMSやDBaaSなど、リモートのストレージに置かれたものを使用することができるようになりました。もちろんこれまで通り、ローカルファイルを元データとすることもできます。元データを管理する幅が広がり、より柔軟にコンテンツを扱えるようになっています。
この記事では、v5以降のContent collectionsの変更点と、その仕組みについて、前後編で解説していきます。
アップデートされたContent collections
アップデートのポイントごとに紹介します。
定義ファイルの場所
すでにContent collectionsを使っている場合、定義ファイルの変更が必要です。
v4以前のContent collectionsでは、src/content/config.jsというファイルでした。このファイルが存在する場合、src/content.config.jsへのリネームが必要です。
また、以前のバージョンでは、定義ファイルは省略することができました。省略した場合は、src/content/内のディレクトリが、コレクションとして自動的に定義・生成されるという仕様でした。v5以降この自動生成の機能は廃止され、src/content.config.jsは省略不可となっています。
定義ファイルの後方互換
執筆現在(2025/3/27)では、後方互換性を保つため、src/content/config.jsでも動作するようになっています。また、自動生成機能もオプトインすることができます。以下は、src/content/articles/をコレクションとして自動生成する例です。
src/content.config.js
import { defineCollection } from "astro:content";
const articles = defineCollection({});
export const collections = { articles };コレクションを生成したいディレクトリと同名の変数を定義し、その変数をコレクションとしてexportします。するとAstroは、その変数名とマッチするディレクトリをsrc/content/内から探し出し、中身のファイルをコンテンツとして読み込みます。
上記の例では、src/content/articles/を対象のディレクトリとしたいので、articlesという変数をコレクションとして定義している、というわけです。
新しいコレクション定義へ移行するまでのつなぎとして使うことはできますが、今後のバージョンで廃止される可能性があります。ですので、なるべく早めに移行することをお勧めします。
定義ファイルの内容
定義ファイルの内容についても変更が入っています。
例として、src/content/entries/に置かれたMarkdownファイルを、次のような定義ファイルで読み込む場合を見てみましょう。
v4以前の定義ファイルでは、以下のようにコレクションを定義していました。
v4以前の定義ファイル(src/content/config.js)
import { defineCollection, z } from "astro:content";
const entries = defineCollection({
type: "content",
schema: z.object({
slug: z.string(),
title: z.string(),
body: z.string(),
})
});
export const collections = { entries };v5以降では、次のようになります。
v5以降の定義ファイル(src/content.config.js)
import { defineCollection, z } from "astro:content";
+ import { glob } from 'astro/loaders';
const entries = defineCollection({
- type: "content",
+ loader: glob({ pattern: '**/*.md', base: "./src/content/entries" }),
schema: z.object({
slug: z.string(),
title: z.string(),
body: z.string(),
})
});
export const collections = { entries };コレクションの種類を決めていたtypeプロパティが廃止され、代わりにloaderプロパティが追加されました。loaderプロパティには、コンテンツデータを読み込むためのローダーと呼ばれる関数を指定します。
ここで指定しているglob(...)は、globローダーというもので、Astro組み込みのローダーのひとつです。globローダーを使うことで、任意のディレクトリにあるMarkdownファイルを読み込むことができます。
こうして読み込まれたMarkdownファイルのデータが、コンテンツとして利用可能になります。
呼び出したコンテンツのデータにも、少しだけ変更が入っています。v4以前は、呼び出したコンテンツデータには、一律でslugプロパティが付与されていました。
v4以前のコンテンツ呼び出し
---
import { getCollection } from "astro:content";
const entries = getCollection("entries");
---
{entries.map((entry) => (
<a href={`/entries/${entry.slug}`}>{entry.data.title}</a>
))}v5以降は、slugではなくidというプロパティに変更されています。
v5以降のコンテンツ呼び出し
---
import { getCollection } from "astro:content";
const entries = getCollection("entries");
---
{entries.map((entry) => (
<a href={`/entries/${entry.id}`}>{entry.data.title}</a>
))}これらの変更を加えることで、v5以降のContent collectionsを利用することができます。
後方互換フラグ
Astroの設定ファイルには、Content collections関連のアップデートされた機能を無効にし、v4以前の挙動で使うためのフラグが用意されています。
v4以前の挙動のまま使いたい場合は、astro.config.mjsでlegacy.collectionsフラグを有効にします。
astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
legacy: {
collections: true,
}
});こちらも、今後のアップデートで廃止される可能性があります。なるべく早めに新しい仕様に移行しましょう。
さまざまなローダーとContent Loader API
前節では、ローカルに置いたMarkdownファイルを、globローダーを使って読み込む方法を紹介しました。
globローダーは、指定したglobパターンにマッチするファイルを読み込むためのローダーです。
globローダーを使った定義ファイルは、先ほど示したとおりです。
globローダーを使った定義ファイル
import { defineCollection, z } from "astro:content";
import { glob } from 'astro/loaders';
const entries = defineCollection({
loader: glob({ pattern: '**/*.md', base: "./src/content/entries" }),
schema: /* 省略 */
});
export const collections = { entries };patternプロパティには、ファイルパスのglobパターンを指定します。'**/*.md'と指定すると、ディレクトリ直下とそのサブディレクトリにあるすべてのMarkdownファイル(.md)を読み込むことができます。指定するパターンを変更することで、MDXやYAML、JSONなどのファイルも読み込むことができます。
baseプロパティには、ファイルパスの基準となるディレクトリパスを指定します。v4以前では、コンテンツの元データはsrc/content/にしか置くことができませんでしたが、v5以降はbaseでパスを指定することができるため、任意のディレクトリに置くことが可能となりました。
Astroが提供する組み込みローダーには、globローダー以外に、fileローダーというものもあります。
fileローダーを使った定義ファイル
import { defineCollection, z } from "astro:content";
import { file } from 'astro/loaders';
const entries = defineCollection({
loader: file("src/data/entries.json"),
schema: /* 省略 */
});
export const collections = { entries };fileローダーは、CSVやJSONなど、データを内包する単一のファイルをパースし、コンテンツとして読み込むためのローダーです。v4以前にtype: "data"として読み込んでいたデータは、fileローダーを使って読み込むというイメージです。
globローダーは、複数のファイルからコレクションを生成するのに対して、fileローダーは単一のファイルからコレクションを生成するという違いがあります。
このように、v5以降のContent collectionsでは、読み込む元データの特性に応じて適切なローダーを選択する、という仕様になりました。
さらに、このローダーの仕組みが実装されたことで、リモートのストレージに置かれたデータを、コンテンツとして利用することもできるようになりました。
組み込みローダー以外にも、サードパーティ製のローダーが公開されています。リモートのデータを読み込みたい場合は、サービスから公式に提供されているローダーか、あるいは有志が作成したローダーを使って読み込みます。
サードパーティ製ローダーは、Google検索やGitHubで探すほか、Astro公式サイトの検索で探すこともできます。
読み込みたいデータに対応したローダーを探してインストールすると、定義ファイルの中でそのローダーを使うことができます。
ファーストパーティ/サードパーティ製のローダーは、Content Loader APIというAstroの仕様に準拠するように作られています。
もし、元データに対応したローダーが見つからない場合は、Content Loader APIに沿って自分でローダーを作成することもできます。
この仕様に準拠したインターフェースを持たせた上で、ローダー内部の処理として、どこかにあるコンテンツのデータを読み込む処理を実装します。
たとえば、Node.jsのfs.read()などを使って、ローカルファイルからデータを読み込むような処理を実装すれば、ローカルファイルからコレクションを生成するローダーになりますし、fetch()などを使って、どこかのサーバーから配信されているデータを読み込むような処理を実装すれば、リモートのデータからコレクションを生成するローダーになる、というわけです。
Content Loader APIの詳細については、本記事では割愛します。深く知りたい方は、Astroの公式ドキュメントを参照してください。
ここまでのまとめ
今回はコンテンツを扱うContent collectionsが、Astro v4からv5でどのように変化したのかを解説しました。
ポイントとしては、以下の2点が挙げられます。
- コンテンツを読み込む「ローダー」という仕組みが整備され、ローカルに限らず、リモートのストレージなど、さまざまな場所の、さまざまな形式のコンテンツを扱えるようになった
- ローダーは「Content Loader API」という仕様に沿って開発することが可能
次回は、実際にローダーを使って、CodeGridのフィードを読み込んだページを作成し、ローダーの扱いを体感してみます。また、まとめとして、ローダーの仕組みを含めたコンテンツの扱いの全体像を押さえます。