はじめに
Live Content Collectionsとは?
これまでAstroのコンテンツCollectionsは、Markdownやjsonをもとにビルド時に静的なHTMLを生成するのが基本で、これはAstroの代名詞でもあるパフォーマンスに優れる一方、頻繁に更新されるデータを扱うには、都度々々サイトを再ビルドする必要があった。
しかし、Live Content Collectionsは、この常識を根底から覆すことができる。
- 実行タイミング: ビルド時ではなく、リクエスト時に
- データソース: ローカルファイルだけでなく、外部のCMS、API、データベースなども対象に
- 目的: 常にリアルタイムの情報(在庫、価格、ユーザーデータなど)をサイトに反映可能に
どう使い分けるべきか?
Live Collections
- リアルタイム情報: ユーザー固有のデータ、現在の在庫レベル、気象情報など。
- 頻繁なデータ更新: 数分おきに変わる商品価格やニュース速報など、再ビルドが追いつかないコンテンツ。
- 動的なフィルタリング: ユーザーの操作に応じて、APIへのクエリを動的に変更したい場合。
- CMSのプレビュー機能: 編集者が下書きコンテンツを保存後、即座にプレビューで確認したい場合。
従来(ビルド時)
- パフォーマンス最優先: ビルド時にレンダリングすることで、最速の表示速度を実現したい場合。
- 静的なコンテンツ: ブログ記事、ドキュメント、製品の基本情報など、頻繁には変更されないデータ。
- ビルド時の最適化: MDXの処理や画像の最適化を行いたい場合。
基本的な使い方
1. 機能を有効化
まず、astro.config.mjs
でexperimental
フラグを有効化。
astro.config.mjs
export default {
experimental: {
liveContentCollections: true,
},
}
2. Live Collectionsを定義
次に、src/live.config.ts
をsrc/content.config.ts
とは別に作成し、defineLiveCollection
でどのLoaderを使うかを定義。
src/live.config.ts
import { defineLiveCollection } from 'astro:content';
import { storeLoader } from '@mystore/astro-loader';
const products = defineLiveCollection({
type: 'live',
loader: storeLoader({
apiKey: process.env.STORE_API_KEY,
endpoint: 'https://api.mystore.com/v1',
}),
});
export const collections = { products };
3. ページでデータを取得・表示
あとは、Astroコンポーネント内で専用のgetLiveCollection()
やgetLiveEntry()
関数を使ってデータを取得するだけ。
src/pages/products/[id].astro
---
import { getLiveCollection, getLiveEntry } from 'astro:content';
// 単一の商品データをIDで取得
const { entry: product, error } = await getLiveEntry('products', Astro.params.id);
if (error) {
return Astro.redirect('/404');
}
const { entries: electronics } = await getLiveCollection('products', { category: 'electronics' }); // フィルタも可能
---
価格: {product.data.price}円
在庫: {product.data.stock > 0 ? 'あり' : 'なし'}
Live Loaderを作ってみる
Live Collectionsの心臓部となるのがLive Loaderで、これは実際に外部と通信してデータを取得する責務を担う。
従来のContent Loaderと同じく、コミュニティが作ったLoaderを使うこともできるし、自分で作ることも可。
-
loadCollection()
: 複数のエントリを取得 -
loadEntry()
: 単一のエントリを取得
src/lib/my-cms-loader.ts
import type { LiveLoader } from 'astro/loaders';
import { fetchFromCMS } from './cms-client';
interface Article {
id: string;
title: string;
content: string;
htmlContent: string;
}
export function articleLoader(config: { apiKey: string }): LiveLoaderArticle> {
return {
name: 'article-loader',
loadCollection: async ({ filter }) => {
try {
const articles = await fetchFromCMS({ ... });
return {
entries: articles.map((article) => ({
id: article.id,
data: article,
})),
};
} catch (e) {
return { error: new Error(${e.message}) };
}
},
loadEntry: async ({ filter }) => {
try {
const article = await fetchFromCMS({ id: filter.id, ... });
if (!article) {
return null;
}
return {
id: article.id,
data: article,
rendered: {
html: article.htmlContent,
},
};
} catch (e) {
return { error: new Error(${e.message}) };
}
},
};
}
でコンテンツをレンダリング
LoaderのloadEntry
がrendered
プロパティを返すことで、取得したコンテンツを
でレンダリング。
src/pages/articles/[id].astro
---
import { getLiveEntry, render } from 'astro:content';
const { entry, error } = await getLiveEntry('articles', Astro.params.id);
if (error) {
return Astro.redirect('/404');
}
// render()でContentコンポーネントを準備
const { Content } = await render(entry);
---
そのほか
Zodによるスキーマ定義
従来のCollectionsと同様に、zodを使ってデータのバリデーションや変換が可能。
これもsrc/live.config.ts
でschema
を定義。
src/live.config.ts
import { z, defineLiveCollection } from 'astro:content';
import { apiLoader } from './loaders/api-loader';
const products = defineLiveCollection({
type: 'live',
loader: apiLoader({ ... }),
schema: z.object({
id: z.string(),
name: z.string(),
price: z.number(),
createdAt: z.coerce.date(),
})
.transform((data) => ({
...data,
displayPrice: `${data.price.toLocaleString()}円`,
})),
});
export const collections = { products };
キャッシュヒント
LoaderがcacheHint
を返すことで、データがどれくらいの期間キャッシュ可能かを示す。
これにより、ページのレスポンスヘッダーにCache-Control
などを設定し、ホスティング先(Vercel, Netlifyなど)のCDNキャッシュを制御が可能になる。
return {
entries: [],
cacheHint: {
tags: ['products'],
maxAge: 300,
},
};
注意点
以下の要件が必要な場合は、Live Content Collectionsを使用できない。
-
MDXサポートなし: MDXのレンダリングはランタイムでは実行不可(
@astrojs/mdx
が必要)。 - 画像最適化なし: Astroによる画像の自動最適化は利用不可。
- パフォーマンス: データはリクエストごとに取得するため、キャッシュ戦略によって大幅にパフォーマンスが変化。
最後に
公式のRFCやPRで、この機能に関するディスカッションやフィードバックを受け付けているので、気になった方はぜひ
Live Content collections RFC
Add docs for experimental live collections
実際の動作例を見たい場合は、以下のYoutube配信のアーカイブから
Views: 0