PR
PR

【Astro入門】トップページに新着記事一覧を表示!getCollectionを使ったデータ取得と並び替え

記事内に広告が含まれています。

前回からの続きです。
【Astro入門】ブログ記事と画像の最適なディレクトリ構成!「1記事1フォルダ」管理とslug設定

今回はブログのトップページに、新着記事を最新のものから10件取得して一覧表示させてみます。

src/pages/index.astroの編集

トップページである「src/pages/index.astro」の編集を行います。

コンポーネントスクリプト部分の編集

ページの上部にある「---」(コンポーネントスクリプト)の中に、記事のデータを取得して「日付の新しい順」に並び替え、最新の10件を取得するJavaScriptのコードを追加します。

// Astroが用意している「astro:content」ライブラリから「getCollection」の機能をインポートします。
import { getCollection } from 'astro:content';

// blogディレクトリの中身を全て取得する
const allPosts = await getCollection('blog');

// 取得した記事を「日付の新しい順(降順)」に並び替える
allPosts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

// 新着記事を最新から10件だけを切り取って、recentPostsに入れる
const recentPosts = allPosts.slice(0, 10);

JavaScriptの解説

import { getCollection } from 'astro:content';

Astroが用意している「astro:content」ライブラリから「getCollection」の機能をインポートします。

const allPosts = await getCollection('blog');
await
記事を取得する処理が終わるまで待機(一時停止)します。
getCollection('blog')
この一行を書くだけで、blogディレクトリ内にある全てのMarkdownファイルの情報(タイトルや日付、そして slug など)が取得され、リストとして allPosts に格納されます。
allPosts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

allPostsに格納されている記事の、フロントマター部分に設定している「pubDate」(現在は年月日を設定中)の値を比較して、新しい順に並び替えます。

const recentPosts = allPosts.slice(0, 10);

並び替えられた全記事の中から、「0番目(一番上)から10個分」だけを切り取り、recentPosts という新しい配列に格納します。

HTML部分の編集(一覧の表示)

index.astro の下半分(<BaseLayout>の中)に、取得した記事を表示するための以下のコードを追加します。

<section style="margin-top: 40px;">
  <h3>新着記事</h3>
  <ul>
    {
      recentPosts.map((post) => {
        // URLを短くする
        const cleanSlug = post.slug.split('/').pop();
            
        return (
          <li style="margin-bottom: 10px;">
            <a href={`/blog/${cleanSlug}/`}>{post.data.title}</a>
            <span style="color: #666; font-size: 0.9em; margin-left: 10px;">
              {post.data.pubDate.toLocaleDateString('ja-JP')}
            </span>
          </li>
        );
      })
    }
  </ul>
</section>

コードの解説

HTML部分の中に { } (波括弧)を書くことで、その中でJavaScriptを動かすことができます。

recentPosts.map((post) => { ... }):

recentPosts の中に入っている記事の数だけ、{}内の処理を繰り返して<li> タグを作成してくれます。

const cleanSlug = post.slug.split('/').pop();

これはURLをきれいに整えるための処理です。

post.slug
記事のデータがあるディレクトリをslugとして認識します。
「src/content/blog/2026/03/09-blog」ディレクトリに記事を書いている場合は、「2026/03/09-blog」をslugとして認識します。
split('/')
「/」(スラッシュ)を区切り文字として文字列を切り離します。
例:["2026", "03", "09-blog"]
pop()
分割したリストの中から一番最後(右端)のデータを取り出します。これにより、09-blog だけが cleanSlug に格納されます。

この結果がcleanSlugに格納されます。

※記事のフロントマターでslugが設定されている場合

記事のフロントマターで「slug: 2026-3-13」と行ったように直接設定している場合は、最初から「/」が含まれていないため、そのままの文字列が格納されます。

<a href={/blog/${cleanSlug}/}>{post.data.title}</a>

cleanSlugには記事のURL文字列が入っているので、正しい記事ページへ飛ぶリンクが完成します。

post.data.title は記事のフロントマターに書いたタイトル(title)です。

post.data.pubDate.toLocaleDateString('ja-JP')

フロントマターに記述した「pubDate」(日付のDateオブジェクト)を、私たちが見慣れた「日本の形式(ja-JP)」の文字列に変換します。

  • 変換前: Fri Mar 13 2026 09:00:00 GMT+0900
  • 変換後: 2026/3/13

完成した「src/pages/index.astro」

最終的なコードは以下のようになります。

---
import BaseLayout from '../layouts/BaseLayout.astro';

// Astroのastro:contentからgetCollectiionツールをインポート
import { getCollection } from 'astro:content';

// blogディレクトリの中身を全て取得する
const allPosts = await getCollection('blog');

// 取得した記事を「日付の新しい順(降順)」に並び替える
allPosts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

// 新着記事を最新から10件だけを切り取って、recentPostsに入れる
const recentPosts = allPosts.slice(0, 10);
---

<BaseLayout>
  <main>
    <h2>こんにちは!</h2>
    <p>何も渡さなくても、自動で「Game Life」とデフォルト説明文が適用されます!</p>

    <section style="margin-top: 40px;">
      <h3>新着記事</h3>
      <ul>
        {
          recentPosts.map((post) => {
            // URLを短くする魔法(前回と同じ!)
            const cleanSlug = post.slug.split('/').pop();
            
            return (
              <li style="margin-bottom: 10px;">
                <a href={`/blog/${cleanSlug}/`}>{post.data.title}</a>
                <span style="color: #666; font-size: 0.9em; margin-left: 10px;">
                  {post.data.pubDate.toLocaleDateString('ja-JP')}
                </span>
              </li>
            );
          })
        }
      </ul>
    </section>
  </main>
</BaseLayout>

このようにトップページに新着記事が表示されるようになりました。

コメント

タイトルとURLをコピーしました