Skip to content

Latest commit

 

History

History
633 lines (435 loc) · 24 KB

content-loader-reference.mdx

File metadata and controls

633 lines (435 loc) · 24 KB
title sidebar i18nReady
Astro Content Loader API
label
Content Loader API
true

import Since from '~/components/Since.astro';

AstroのContent Loader APIを使用することで、ローカルまたはリモートの任意のソースからデータをロードし、Astroのコンテンツレイヤーとやり取りしてコンテンツコレクションを管理できます。

ローダーとは?

{/* TODO: /ja/guides/content-collections/#built-in-loaders does not exist yet. #built-in-loaders will be added when the fragment link destination is specified. */} Astroのローダーを使用すると、コンテンツコレクションにデータをロードでき、ページやコンポーネントで使用できます。ビルトインのglob()およびfile()ローダーはファイルシステムからコンテンツをロードするために使用され、他のソースからコンテンツをロードするために独自のローダーを作成することもできます。

{/* TODO: /ja/guides/content-collections/#defining-the-collection-loader does not exist yet. #defining-the-collection-loader will be added when the fragment link destination is specified. */} 各コレクションにはスキーマで定義されたローダーが必要です。プロジェクトのsrc/content.config.tsファイルにインラインでローダーを定義したり、複数のコレクション間で1つのローダーを共有したり、他の人と共有するためにNPMにパッケージとしてローダーを公開して、統合ライブラリに含めることもできます。

ビルトインローダー

Astroには、コレクションを取得するための2つのビルトインローダーが用意されています。どちらも幅広いユースケースに対応するオプションを提供しています。

glob() ローダー

Type: (options: GlobOptions) => Loader

glob()ローダーは、ファイルシステム上の任意のディレクトリからファイルのエントリを作成します。サポートされているファイルタイプは、Markdown、MDX、Markdoc、JSON、およびYAMLファイルです。

このローダーは、patternbase(オプショナル)、およびgenerateId(オプショナル)のプロパティを持つをオブジェクトを受け入れます。

import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';

const pages = defineCollection({
  /* pagesディレクトリにあるすべてのマークダウンファイルを取得する。 */
  loader: glob({ pattern: "**/*.md", base: "./src/data/pages" }),
  schema: /* ... */
});
const blog = defineCollection({
  /* blogディレクトリにあるすべてのマークダウン、MDXファイルを取得する。 */
  loader: glob({ pattern: "**/*.(md|mdx)", base: "./src/data/blog" }),
  schema: /* ... */
});
const authors = defineCollection({
  /* 大文字のIDを保持したまま、authorsディレクトリ内のすべてのJSONファイルを取得する。 */
  loader: glob({
    pattern: '**/*.json',
    base: "./src/data/authors",
    generateId: ({ entry }) => entry.replace(/\.json$/, ''),
  }),
  schema: /* ... */
});

pattern

Type: string | string[]

patternプロパティは、グロブマッチング(ワイルドカードなど)を使用して文字列または文字列の配列を受け入れます。パターンは、エントリファイルのベースディレクトリに対して相対的である必要があります。

使用する構文の詳細については、micromatchのドキュメントを参照してください。また、DigitalOcean Glob Toolのようなオンラインツールを使用してパターンの有効性を確認することもできます。

base

Type: string | URL
Default: "."

patternを解決するためのディレクトリへの相対パスまたはURLを指定します。

generateId()

Type: (options: GenerateIdOptions) => string

エントリごとに一意の文字列を返すコールバック関数です。以下のプロパティを持つオブジェクトをパラメータとして受け取ります。

  • entry - ベースディレクトリに対するエントリファイルのパス
  • base - ベースディレクトリのURL
  • data - パースされた未検証のエントリデータ

デフォルトでは、github-sluggerを使用して、ケバブケースの単語でスラッグを生成します。

file() ローダー

Type: (fileName: string, options?: FileOptions) => Loader

file()ローダーは、ユニークなidフィールドを持つオブジェクトの配列、または文字列キーを持つオブジェクトを含む単一のファイルからエントリを作成します。JSONまたはYAMLをサポートしており、デフォルトでは解析できないデータファイルに対してカスタムparserを提供することができます。

このローダーは、fileNameプロパティとオプションのオブジェクトを第二引数として受け入れます。

import { defineCollection } from 'astro:content';
import { file } from 'astro/loaders';

const authors = defineCollection({
  /* JSONファイルからすべてのエントリーを取得する。 */
  loader: file("src/data/authors.json"),
  schema: /* ... */
});
const products = defineCollection({
  /* カスタムのパーサーを使って、CSVファイルからすべてのエントリーを取得する。 */
  loader: file("src/data/products.csv", {
    parser: (fileContent) => { /* パーサーのロジックを記述 */ },
  }),
  schema: /* ... */
});

fileName

Type: string

ファイルをロードするためのパスを、ルートディレクトリからの相対パスで設定します。

Options

Type: FileOptions

オプションのオブジェクトとして、次のプロパティを持ちます。

parser()

Type: (text: string) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>>

{/* TODO: /ja/guides/content-collections/#nested-json-documents does not exist yet. #nested-json-documents will be added when the fragment link destination is specified. */} ファイルの内容からコレクションを作成するためのコールバック関数です。デフォルトでサポートされていないファイル(例:.csv)を処理する必要がある場合や、ネストされた.jsonドキュメントを使用する場合に使用します。

ローダータイプ

ローダーは、エントリの配列を返す単純な関数として定義することも、より強力なオブジェクトContent Loader APIを使用してロードプロセスをより詳細に制御することもできます。

インラインローダー

インラインローダーは、エントリを含む配列またはオブジェクトを返す非同期関数です。これは、特にsrc/content.config.tsファイルにインラインで定義されるシンプルなローダーに使用します。

この関数は非同期であり、各エントリが一意のidフィールドを含む配列、または各キーが一意のIDで各値がエントリであるオブジェクトを返す必要があります。ローダーが呼び出されるたびに、ストアをクリアしてすべてのエントリを再ロードします。

const countries = defineCollection({
  loader: async () => {
    const response = await fetch("https://restcountries.com/v3.1/all");
    const data = await response.json();
    // エントリの配列を返す必要があります(各エントリにはidプロパティが必要)
    // またはIDをキー、エントリを値とするオブジェクトを返す必要があります
    return data.map((country) => ({
      id: country.cca3,
      ...country,
    }));
  },
  schema: /* ... */
});

オブジェクトローダー

ローダーは、ビルド時にデータを取得してデータストアを更新するために呼び出されるload()メソッドを持つオブジェクトです。これにより、エントリを段階的に更新したり、必要に応じてストアをクリアすることができます。また、エントリのスキーマを定義してデータを検証し、静的な型を生成することもできます。

推奨されるパターンは、構成オプションを受け取り、ローダーオブジェクトを返す関数を定義することです。これは、通常AstroインテグレーションやViteプラグインを定義する方法と同じです。

import type { Loader, LoaderContext } from 'astro/loaders';
import { z } from 'astro:content';
import { loadFeedData } from "./feed.js";

// ローダーが必要とするオプションを定義
export function myLoader(options: { url: string, apiKey: string }): Loader {
  // ローダーの設定
  const feedUrl = new URL(options.url);
  // Loaderオブジェクトを返す
  return {
    name: "my-loader",
    // コレクションを更新する際に呼び出されます
    load: async (context: LoaderContext): Promise<void> => {
      // データをロードしてストアを更新
      const response = await loadFeedData(feedUrl, options.apiKey);
    },
    // オプションで、エントリのスキーマを定義します
    // ユーザー定義のスキーマによって上書きされます
    schema: async () => z.object({
      // ...
    })
  };
}

これらの構成オプションは、コレクションを定義する際に設定できます。

import { defineCollection, z } from 'astro:content';  
import myLoader from '../../loader.ts';  

const blog = defineCollection({  
  loader: myLoader({
    url: "https://api.example.com/posts",
    apiKey: "my-secret",
  }),  
  schema: /* ... */  
});  

オブジェクトローダーAPI

インラインローダーのAPIは、上述の通り非常にシンプルです。このセクションでは、オブジェクトローダーを定義するためのAPIを示します。

Loaderオブジェクト

Loaderオブジェクトは、以下のプロパティを持ちます。

name

Type: string

一意なローダーの名前を示します。ログや条件付きロードに使用されます。

load

Type: (context: LoaderContext) => Promise<void>

ビルド時にデータをロードしてストアを更新するために呼び出される非同期関数です。詳細はLoaderContextを参照してください。

schema

Type: ZodSchema | Promise<ZodSchema> | (() => ZodSchema | Promise<ZodSchema>)

オプションで、Zodスキーマでエントリの型を定義します。データの検証と、コレクションのTypeScriptの型の生成に使用されます。

関数が提供された場合、ビルド時にload()の前に呼び出されてスキーマを生成します。これを使用して、構成オプションに基づいてスキーマを動的に生成したり、APIを検証してスキーマを生成したりできます。

LoaderContext

このオブジェクトはローダーのload()メソッドの引数に渡されるもので、以下のプロパティを持ちます。

collection

Type: string

一意なコレクションの名前を示します。これは、src/content.config.tsファイルのcollectionsオブジェクトのキーです。

store

Type: DataStore

実際のデータを保持するデータベースです。これを使用して、新しいエントリでストアを更新します。詳細はDataStoreを参照してください。

meta

Type: MetaStore

コレクションにスコープされたキーと値のストアで、同期トークンや最終更新時刻などに使用されます。このメタデータはビルド間でコレクションデータと共に保持されますが、ローダー内でのみ利用可能です。

const lastModified = meta.get("lastModified");
// ...
meta.set("lastModified", new Date().toISOString());

logger

Type: AstroIntegrationLogger

コンソールにメッセージを出力するために使用できるロガーです。console.logの代わりにこれを使用すると、ローダー名を含むより有用なログが得られます。詳細はAstroIntegrationLoggerを参照してください。

config

Type: AstroConfig

すべてのデフォルト値が適用された完全な解決済みAstro構成オブジェクトです。詳細は設定方法を参照してください。

parseData

Type: (props: ParseDataOptions<TData>) => Promise<TData>

コレクションスキーマに従って、データを検証および解析します。この関数にデータを渡して、データストアに保存する前に検証および解析します。

import type { Loader } from "astro/loaders";
import { loadFeed } from "./feed.js";

export function feedLoader({ url }): Loader {
  const feedUrl = new URL(url);
  return {
    name: "feed-loader",
    load: async ({ store, logger, parseData, meta, generateDigest }) => {
      logger.info("Loading posts");
      const feed = loadFeed(feedUrl);
      store.clear();

      for (const item of feed.items) {
        const data = await parseData({
          id: item.guid,
          data: item,
        });
        store.set({
          id,
          data,
        });
      }
    },
  };
}

generateDigest

Type: (data: Record<string, unknown> | string) => string

オブジェクトや文字列の暗号化を伴わないコンテンツダイジェストを生成します。これは、エントリのdigestフィールドを設定してデータが変更されたかどうかを追跡するために使用できます。

import type { Loader } from "astro/loaders";
import { loadFeed } from "./feed.js";

export function feedLoader({ url }): Loader {
  const feedUrl = new URL(url);
  return {
    name: "feed-loader",
    load: async ({ store, logger, parseData, meta, generateDigest }) => {
      logger.info("Loading posts");
      const feed = loadFeed(feedUrl);
      store.clear();

      for (const item of feed.items) {
        const data = await parseData({
          id: item.guid,
          data: item,
        });

        const digest = generateDigest(data);

        store.set({
          id,
          data,
          digest,
        });
      }
    },
  };
}

watcher

Type: FSWatcher

開発モードで実行している場合に、これは更新をトリガーするために使用できるファイルシステムウォッチャーです。詳細はViteDevServerを参照してください。

return {
  name: 'file-loader',
  load: async ({ config, store, watcher }) => {
    const url = new URL(fileName, config.root);
    const filePath = fileURLToPath(url);
    await syncData(filePath, store);

    watcher?.on('change', async (changedPath) => {
      if (changedPath === filePath) {
        logger.info(`Reloading data from ${fileName}`);
        await syncData(filePath, store);
      }
    });
  },
};

refreshContextData

Type: Record<string, unknown>

ローダーがインテグレーションでトリガーされた場合、オプションでインテグレーションによって設定された追加データを含むことがあります。これはローダーがインテグレーションによってトリガーされた場合にのみ設定されます。詳細はastro:server:setupフックリファレンスを参照してください。

export function myLoader(options: { url: string }): Loader {
  return {
    name: "my-loader",
    load: async ({ refreshContextData, store, logger }) => {
      if(refreshContextData?.webhookBody) {
        logger.info("Webhook triggered with body");
        processWebhook(store, refreshContextData.webhookBody);
      }
      // ...
    },
  };
}

DataStore

DataStoreは、ローダーがコンテンツコレクションデータにアクセスするためのインターフェースです。これはキーと値のストアで、コレクションにスコープされているため、ローダーは自分のコレクションのデータにのみアクセスできます。

get

Type: (key: string) => DataEntry | undefined

ストアから指定したIDのエントリを取得します。エントリが存在しない場合はundefinedを返却します。

const existingEntry = store.get("my-entry");

返却されるオブジェクトはDataEntryオブジェクトです。

set

Type: (entry: DataEntry) => boolean

データが検証および解析された後にエントリをストアに追加するために使用され、エントリが設定された場合はtrueを返却します。エントリが変更されておらず更新する必要がないとdigestプロパティが判断した場合はfalseを返却します。

    for (const item of feed.items) {
      const data = await parseData({
        id: item.guid,
        data: item,
      });
      const digest = generateDigest(data);
      store.set({
        id,
        data,
        rendered: {
          html: data.description ?? "",
        },
        digest,
      });
    }

entries

Type: () => Array<[id: string, DataEntry]>

コレクション内のすべてのエントリをキーと値のペアの配列で取得します。

keys

Type: () => Array<string>

コレクション内のすべてのエントリのキーを取得します。

values

Type: () => Array<DataEntry>

コレクション内のすべてのエントリを配列で取得します。

delete

Type: (key: string) => void

ストアから指定したIDのエントリを削除します。

clear

Type: () => void

コレクションからすべてのエントリを削除します。

has

Type: (key: string) => boolean

ストアに指定したIDのエントリが存在するかどうかを確認します。

DataEntry

これはデータストアに保存されるオブジェクトの型です。以下のプロパティを持ちます。

id

Type: string

エントリの識別子で、コレクション内で一意である必要があります。これはストア内でエントリを検索するために使用され、getEntryでそのコレクションに使用されるキーです。

data

Type: Record<string, unknown>

エントリの実際のデータです。ユーザーがコレクションにアクセスする際、これはコレクションスキーマに従って生成されたTypeScriptの型を持ちます。

データストアに保存する前にデータを検証および解析するためにparseDataを使用するのはローダーの責任です。データの取得や設定時には検証は行われません。

filePath

Type: string | undefined

このエントリのソースとなるファイルへのパスです。サイトのルートからの相対パスです。これはファイルベースのローダーにのみ適用され、画像やその他のアセットのパスを解決するために使用されます。

設定されていない場合、スキーマ内でimage()ヘルパーを使用するフィールドはpublicパスとして扱われ、変換されません。

body

Type: string | undefined

エントリの生のボディです(該当する場合)。エントリにレンダリングされたコンテンツが含まれている場合、このフィールドを使用して生のソースを保存できます。これはオプションであり、内部的には使用されません。

digest

Type: string | undefined

任意のエントリのコンテンツダイジェストです。これを使用してデータが変更されたかどうかを確認できます。

エントリを設定する際、同じIDの既存エントリとダイジェストが一致しない場合にのみエントリが更新されます。

ダイジェストの形式はローダー次第ですが、データが変更されたときに変わる文字列でなければなりません。これはgenerateDigest関数を使用して行えます。

rendered

Type: RenderedContent | undefined

エントリがHTMLにレンダリングされている場合、そのレンダリングされたコンテンツとメタデータを含むオブジェクトを保存します。例えば、Markdownエントリのレンダリングされたコンテンツや、CMSからのHTMLを保存するために使用できます。

このフィールドが提供されている場合、render()関数と<Content />コンポーネントを使用してページ内でエントリをレンダリングできます。

RenderedContentオブジェクトの形式は次の通りです。

{
	/** レンダリングされたHTML文字列。これが存在する場合、`render(entry)`はこのHTMLをレンダリングするコンポーネントを返します。 */
	html: string;
	metadata?: {
		/** このエントリに含まれる画像。{@link DataEntry}のfilePathに対して相対的です。 */
		imagePaths?: Array<string>;
		/** このファイルに含まれる見出し。`render()`から`headings`として返されます。 */
		headings?: MarkdownHeading[];
		/** ファイルから解析された生のフロントマター。これにはremarkプラグインからのデータが含まれる場合があります。 */
		frontmatter?: Record<string, any>;
		/** このファイルに含まれるその他のメタデータ。 */
		[key: string]: unknown;
	};
}