2025-12-13

【ブログ構築】記事取得の効率化

 たまには技術的な話もしよう。

 本ブログ「のうらリリースノート」は CMS に Strapi、フロントエンドには Astro を利用している。このたびカテゴリ別の記事一覧ページを追加した。以下はホークスカテゴリの記事一覧ページだ。

 ページ自体は作ったものの、まだどこからもリンクしていないので現状は URL を手打ちする必要がある。ここは後で実装する予定。

 カテゴリページの実装にあたり、CMS からの記事取得方法を少し効率化した。

% tree src/pages
src/pages
├── category
│   └── [slug]
│       ├── index.astro
│       └── page
│           └── [page].astro
├── entry
│   └── [slug].astro
├── index.astro
└── page
    └── [page].astro

6 directories, 5 files

 現在の Astro のページ構成は上記のとおり。/page/[page].astro は記事一覧ページ用(例:/page/2//page/3/)のテンプレートで、entry/[slug].astro は記事詳細ページ(例:/entry/keiba-20251102-result/)のテンプレートだ。
 今回、新たに category/[slug]/page/[page].astro を追加してカテゴリー記事一覧ページを作ったわけだが、そこで問題が一つ。「カテゴリー一覧ページで表示する内容は、もともと /page/[page].astro で取得しているものとほぼ同じ」であり、Strapi に再度アクセスする必要がなかった。
 そこで、記事一覧取得が重複しないよう、Strapi から取得したデータをキャッシュして再利用する形にした。

const articlesListCache = new Map<number, Promise<Article[]>>();

export const getArticles = (pageSize: number) => {
  const cached = articlesListCache.get(pageSize)
  if (cached) return cached
  
  const promise = fetchArticles(pageSize)
  articlesListCache.set(pageSize, promise)
  
  return promise
}

 上のコードは論理的なイメージだ。このgetArticlesを複数のページテンプレートから呼び出している。ビルド時にどのページが最初に走るかわからないため、Promise をキャッシュする形にしている。



 今はまだ記事数が多くないので、API 負荷削減やビルド時間にどれほど効いているかは実感しづらい。ただ、やらないよりは確実に良いはず。
 次はカテゴリページへのリンク実装と、「全件取得 → ビルド」ではなく「一部取得 → ビルド」を繰り返す形への変更かな。