本記事ではAstroでページネーションを実装する方法をまとめました。
当サイトのブログ一覧ページは本記事のコードをベースに実装しています。
ページネーションの特徴は下記です。
- 1ページ目のURLは
~/blog/
と表示可能(~/blog/1/
とはならない) - 100件以上の記事にも対応
本記事は以下サイトの内容を参考に、microCMSで取得した記事に対応した内容を追加した記事になります。
参考にさせていただき、ありがとうございます。この場を借りてお礼申し上げます。
ファイル名
1ページ目が~/blog/1/
とならないように、ファイル名を[...page].astro
とします。
レストパラメータを利用することで任意の深さのファイルパスにマッチさせることが可能です。
これにより、1ページ目のパスは~/blog/1/
とならず、~/blog/
となります。
コード
次にコードです。
特に配慮した点としては、
export const postsPerPage
で1ページに記載する記事数を変更- 50件ずつ分割して記事を読み込み、100件以上の記事にも対応
- 取得するフィールド、並び順も指示可能
無駄な通信を避け、レスポンスと通信量の削減に配慮しています。
---
import Pagination from "@components/Pagination.astro";
//microCMS呼び出し
import { getNews } from "@library/microcms";
// 1ページに表示する件数
export const postsPerPage = 10;
// getStaticPaths()で動的なルートを設定
export async function getStaticPaths({ paginate }) {
// 総件数を取得
const initialResponse = await getNews({
limit: 0,
fields: ["id"],
});
const totalCount = initialResponse.totalCount;
// 50件ずつ分割して全記事を取得
const allContents = [];
const batchSize = 50; // 1回あたりの取得件数
const batchCount = Math.ceil(totalCount / batchSize);
for (let i = 0; i < batchCount; i++) {
const batchResponse = await getNews({
limit: batchSize,
offset: i * batchSize,
fields: ["title", "publishedAt"], //取得するフィールド
orders: "-publishedAt", //公開日順でソート
});
allContents.push(...batchResponse.contents);
}
// 取得した全記事に対してページネーションを適用
return paginate(allContents, {
pageSize: postsPerPage,
});
}
// propsからpageオブジェクトを取得(pageDataに現在のページの記事が含まれています)
const { page } = Astro.props;
---
{
page.data.map((post) => (
<div>
<h2>{post.title}</h2>
<p>公開日: {post.publishedAt)}</p>
</div>
))
}
<Pagination currentPage={page.currentPage} totalPages={page.lastPage} url="/news/" {/* 最初のページのパスを指定 */} />
ページネーションはコンポーネントとしてまとめています。
---
const { currentPage, totalPages, url } = Astro.props;
// ページ番号の配列を生成
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
// ページのURLを生成する関数
function getPageUrl(pageNum: number) {
return pageNum === 1 ? url : `${url}${pageNum}/`;
}
---
<nav class="pagination">
{
currentPage > 1 && (
<a href={getPageUrl(currentPage - 1)} class="pagination__prev">
前へ
</a>
)
}
<div class="pagination__numbers">
{
pages.map((num) => (
<a href={getPageUrl(num)} class:list={["pagination__link", { _active: num === currentPage }]}>
{num}
</a>
))
}
</div>
{
currentPage < totalPages && (
<a href={getPageUrl(currentPage + 1)} class="pagination__next">
次へ
</a>
)
}
</nav>
細かな点は環境に合わせて調整して下さい。
まとめ
今回はmicroCMSを使用したAstroサイトにおいて、記事一覧ページのページネーションを作成する方法をまとめました。
ページネーションはブログサイトであればほぼ必要であり、microCMSにおいては100件の制限もあるので作成しました。
もしこの記事が役に立ったと感じていただけた方は、ぜひX(旧Twitter)やブログなどでシェアしていただけると嬉しいです。
最後までお読みいただき、ありがとうございました!