astro-strapi-loader
@sensinum/astro-strapi-loaderをAstro Content Layerと併用して、Strapi REST クエリオブジェクトを構築できます。オブジェクトおよびオブジェクト配列のpopulateをREST パラメータごとに設定し、qs.stringifyでシリアライズします。クエリ文字列はインライン化せず、合成可能なクエリフラグメント、dynamic zoneの「on」、ロケール戦略、generateCollections、getCollection / getEntryの各機能に対応しています。Strapi 5、Astro 6以上で動作します。
description の原文を見る
Use @sensinum/astro-strapi-loader with Astro Content Layer: build Strapi REST query objects (object and object-array populate per REST parameters), let qs.stringify serialize—never inline query strings. Composable query fragments, dynamic zone "on", locale strategies, generateCollections, getCollection / getEntry. Strapi 5, Astro 6+.
SKILL.md 本文
Astro Strapi Loader — エージェントスキル
スコープ
- パッケージ:
@sensinum/astro-strapi-loader(Astro 6+ ピア、Strapi 5)。 - 目的: Strapi を build 時に Astro コンテンツコレクションに正しい
populateグラフ、ダイナミックゾーン、多言語対応で読み込みます。
インストールと基本設定
@sensinum/astro-strapi-loaderをインストールします(ピアzod/astroはプロジェクトに応じて)。src/content.config.tsでawait generateCollections(config, definitions)を実行し、返されたレコードをcollectionsにスプレッドします(または複数呼び出しをマージ—下記参照)。- 環境変数: API が保護されている場合は
STRAPI_URL、STRAPI_TOKEN。 - トークン: Content API の読み取りと、Content-Type Builder の
GETコンテンツタイプ(生成された Zod スキーマのソース)を許可する必要があります。
設定オブジェクト(generateCollections の第 1 引数)
| フィールド | 説明 |
|---|---|
url | Strapi ベース URL(/api サフィックスなし、パッケージが /api/... をリクエスト)。 |
token | オプション Bearer トークン。 |
strict | オプション;スキーマビルダーからより厳密な Zod を生成。 |
headers | オプション追加リクエストヘッダ。 |
エントリの定義(第 2 引数)
各項目は 1 つの Strapi コレクション → 1 つの Astro defineCollection、collectionName または Strapi タイプ名でキー付けされます。
| フィールド | 用途 |
|---|---|
name | API id / ルートセグメント(例:homepage、case-studies)。 |
query | REST オブジェクト:populate、filters、sort、fields、pagination。 |
collectionName | 同じ name を再利用するときの Astro コレクションキー(例:ロケール別分割)。 |
locale | string または string[] — 多言語対応 を参照。 |
idGenerator | (data) => string — そうでなければ documentId。 |
短縮形: ['homepage', 'layout'] は、これらのタイプに対してデフォルト query を意味します。
複数の generateCollections 結果をマージ: この関数はコレクション設定のフラットオブジェクトを返します。長い定義リストで 1 回 await するか、ループ 内で呼び出し(例:定義ごと 1 回)して単一のオブジェクトに スプレッド できます:strapiCollections = { ...strapiCollections, ...result }。ループパターンは、build 時に一部のエンドポイントがエラーになった場合、失敗を分離 するのに役立ちます(定義ごとにログ出力、続行)。
大規模な query 値の整理
content.config.ts を保守性高く保つテクニック:
- 共有フラグメント — 小さい
constオブジェクト(例:heroPopulate、seoPopulate)を使い、スプレッドで最終的なqueryを コンポーズ すれば、hero/SEO がページタイプ全体で一貫性を保ちます。 - 1 つのダイナミックゾーンマップ —
{ [dzFieldName]: { on: { 'component.api.id': { populate: ... } } } }形の単一constを作成し、populateにスプレッド(例:populate: { hero, seo, ...dynamicZoneFragment })。コンポーネントを 1 か所 で追加・削除します。 - ドットパス
populate配列 — 幅広いが平坦なグラフの場合、populate: ['a', 'a.b', 'a.b.c']をネストされたオブジェクトと同じpopulate内に必要に応じて並べます。 - 中央クエリモジュール — エクスポートされた
constクエリオブジェクトを例えばsrc/globals/queries.ts(またはlib/strapi-queries.ts)に移動し、content.config.tsに インポート します。同じ オブジェクトをローダーに渡し、ランタイム取得ではqsで文字列化できます—単一の情報源。 - 単一タイプ + コレクションタイプ — 単一タイプとコレクションタイプの定義を別々にリストアップし、統合された
collectionDefs(例:各エントリ{ name, query, collectionName?, locale? })を build してからgenerateCollectionsをループ処理します。
query オブジェクトの構築(Strapi REST)
URL ではなく データ を作成してください。REST API パラメータに準じています:filters、locale、status、populate、fields、sort、pagination。クエリ文字列内のブラケットエンコーディングは、そのオブジェクトから qs で生成されます。
オブジェクト形式(深い populate)
リレーション、コンポーネント、ダイナミックゾーン用のネストされたオブジェクト(例:populate: { seo: { populate: ['ogImage'] } })。
オブジェクト-配列(混合)populate
パラメータは populate を文字列またはオブジェクトとして許可します。ドットパスの配列 はより平坦なツリーに便利です:
populate: ['logo', 'seo', 'seo.ogImage', 'customer.logo_light']
パスの配列とネストされた on / オブジェクトを 1 つの populate で混在させることができます。
その他のパラメータ
sort:文字列または文字列配列。fields:名前の配列。filters:オブジェクト — フィルタ。pagination:{ page, pageSize }または現在の Strapi ドキュメント参照。
アンチパターン
- 手作業で作成した
?a=b&...文字列、テンプレートリテラル、手動ブラケットセグメント。 - 深くネストされた
populateにURLSearchParamsを使用。 content.config.ts内で事前に文字列化(ローダーは プレーンオブジェクト を受け取るべき)。
手動 HTTP
import qs from "qs";
const queryParams = qs.stringify(
{ populate: { /* ... */ }, locale: "en" },
{ encodeValuesOnly: true }
);
URL に代わって、クエリ全体に JSON.stringify を使用しないでください。
シリアライゼーション境界
- ローダー: 1 つの
queryオブジェクトを渡します;strapiLoaderは内部でqs.stringifyを使用。 - 生
fetch/fetchContent: 同じオブジェクトを build してからqs.stringify(..., { encodeValuesOnly: true })を実行。
ダイナミックゾーンと on
ダイナミックゾーンフィールド(例:sections、blocks)は on で入力されます:コンポーネント API ids(Content-Type Builder に表示)のみが展開され、それぞれ独自の populate を持ちます。
{
blocks: {
on: {
"blocks.rich_text": { populate: { body: true, cta: true } },
"blocks.media_row": { populate: { items: { populate: ["media"] } } },
},
},
}
これをトップレベル populate の下に hero、seo などの隣に配置します。on 内の深いツリー(ネストされたコンポーネント、メディア)は他の populate オブジェクトと同じルールを使用します。
コレクションタイプ vs 単一タイプ
- コレクション:
dataは 配列 — ストア内の各項目が 1 つのコンテンツエントリ。 - 単一タイプ:
dataは 単一オブジェクト — ストア内の 1 つのエントリ。
同じ StrapiCollection 形状が適用されます;ルーティングは Strapi のコンテンツタイプで定義されます。
多言語 / locale
locale: 'en'(単一): 1 つのリクエスト;Strapi がその言語を返す。- 同じ Strapi タイプ → 複数の Astro コレクション: 同じ
nameでエントリを繰り返し、異なるlocaleと異なるcollectionName(例:pages-pl、pages-en)を指定すると、getCollection('pages-pl')とgetCollection('pages-en')は別になります。 locale: ['en', 'de', 'pl']: ローダーはロケール単位で取得し、id をlocale:documentIdとして保存し、各項目のデータに_localeを追加します。パブリック id がスラッグの場合、idGeneratorとよく組み合わせられます:en:about-us。- ローダーはリクエストクエリに
localeをマージします;生クエリ文字列ではなく、オブジェクト内でlocaleをモデル化 することもできます。
Astro でのデータ使用
getCollection('key')— すべてのエントリ;マルチロケール単一コレクションの場合、data._localeでフィルタ。getEntry('key', 'locale:documentId' | 'locale:slug')(プレフィックス付き id を使用する場合)。- ランタイム Strapi 呼び出し:
qs.stringify処理された パラメータを使用fetchContent、できれば build 時と同じqueryオブジェクト を再利用。
トラブルシューティング
- 空またはデータ不完全:
populateの深さ、間違ったlocale、下書き/未公開、またはfiltersが厳しすぎる。 - REST で 400 エラー: オブジェクト形状を パラメータ と実際のシリアライゼーション(
qs経由)と比較。 - Build スキーマエラー:
STRAPI_URL/ トークンが Content-Type Builder に到達できないか、コンテンツタイプをリストできない。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- VirtusLab-Open-Source
- ライセンス
- MIT
- 最終更新
- 2026/5/7
Source: https://github.com/VirtusLab-Open-Source/astro-strapi-loader / ライセンス: MIT