日曜日, 6月 15, 2025
- Advertisment -
ホームニューステックニュースAstro新時代! 再ビルド不要のLive Content Collections

Astro新時代! 再ビルド不要のLive Content Collections



はじめに

Live Content Collectionsとは?

これまでAstroのコンテンツCollectionsは、Markdownやjsonをもとにビルド時に静的なHTMLを生成するのが基本で、これはAstroの代名詞でもあるパフォーマンスに優れる一方、頻繁に更新されるデータを扱うには、都度々々サイトを再ビルドする必要があった。

しかし、Live Content Collectionsは、この常識を根底から覆すことができる。

  • 実行タイミング: ビルド時ではなく、リクエスト時
  • データソース: ローカルファイルだけでなく、外部のCMS、API、データベースなども対象に
  • 目的: 常にリアルタイムの情報(在庫、価格、ユーザーデータなど)をサイトに反映可能に

どう使い分けるべきか?

Live Collections

  • リアルタイム情報: ユーザー固有のデータ、現在の在庫レベル、気象情報など。
  • 頻繁なデータ更新: 数分おきに変わる商品価格やニュース速報など、再ビルドが追いつかないコンテンツ。
  • 動的なフィルタリング: ユーザーの操作に応じて、APIへのクエリを動的に変更したい場合。
  • CMSのプレビュー機能: 編集者が下書きコンテンツを保存後、即座にプレビューで確認したい場合。

従来(ビルド時)

  • パフォーマンス最優先: ビルド時にレンダリングすることで、最速の表示速度を実現したい場合。
  • 静的なコンテンツ: ブログ記事、ドキュメント、製品の基本情報など、頻繁には変更されないデータ。
  • ビルド時の最適化: MDXの処理や画像の最適化を行いたい場合。

基本的な使い方

1. 機能を有効化

まず、astro.config.mjsexperimentalフラグを有効化。

astro.config.mjs

export default {
  experimental: {
    liveContentCollections: true,
  },
}

2. Live Collectionsを定義

次に、src/live.config.tssrc/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のloadEntryrenderedプロパティを返すことで、取得したコンテンツをでレンダリング。

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.tsschemaを定義。

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配信のアーカイブから

https://www.youtube.com/live/2Skg7wo_dTk?si=AkL4hNRQbdJqK3JI



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -