Astro&WordPressで記事一覧(ページネーション)と記事詳細ページの実装
2025/03/14 (金) - 09:00 JavaScriptPHP&CMS
以前に副業でWordPressとAstroでヘッドレスCMSでブログを実装しましたのでそのメモです。取り急ぎ記事一覧と記事詳細のみでファイル構成は最低限のものだけ。
src
├─ components
│ └─ Pagination.astro
├─ layouts
│ └─ Layout.astro
└─ pages
├─ [slug].astro
├─ index.astro
└─ page
└─ [paged].astro
WordPressの記事の呼び出しは、WordPressのREST APIを使います。
REST APIのエンドポイントは.env
に記載しておきます。ついでにブログ名も設定しておくと一括で変更できます。
BLOG_TITLE=ひなちゃんの日記
API_JSON=https://example.com/wp-json/wp/v2/posts/
レイアウトを定義するにLayout.astro
に大枠のHTMLとブラウザに表示されるタイトルのtitle
要素の中身を取得するコードを記載します。必要最低限の記載のみです。
---
const {meta} = Astro.props;
---
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>{meta.title}</title>
</head>
<body>
<slot />
</body>
</html>
トップページの記事一覧をindex.astro
に実装します。ブラウザに表示されるタイトルは[トップページ – ブログ名]となります。
---
import { format } from 'date-fns';
import Layout from '../layouts/Layout.astro';
import Pagination from '../components/Pagination.astro';
const res = await fetch(`${import.meta.env.API_JSON}`);
const posts = await res.json();
const total = await fetch(import.meta.env.API_JSON).then((res) => {return res.headers.get('X-WP-TotalPages')});
const page: {
current: number,
total: number
} = {
current: 1,
total: Number(total)
}
const meta: {
title: string
} = {
title: `トップページ - ${import.meta.env.BLOG_TITLE}`
}
---
<Layout meta={meta}>
<main>
{posts.map((post: { slug: string; title: { rendered: string }; content: { rendered: string }; date: string }) => (
<article><a href={`/${post.slug}`}>
<h2>{post.title.rendered}</h2>
<p>{format(new Date(post.date), 'yyyy年MM月dd日')}</p>
</a></article>
))}
<Pagination page={page} />
</main>
</Layout>
ページネーションの記事一覧は/page/[paged].astro
で動的パスで取得し、getStaticPaths
で生成します。ブラウザに表示されるタイトルは[nページ目 – ブログ名]となります。
---
import { format } from 'date-fns';
import Layout from '../../layouts/Layout.astro';
import Pagination from '../../components/Pagination.astro';
export async function getStaticPaths(){
const total = await fetch(import.meta.env.API_JSON).
then((res) => {return Number(res.headers.get('X-WP-TotalPages'))});
return Array.from({ length: total }, (num,i) => ({
params: { paged: `${i + 1}` }
}))
}
const {paged} = Astro.params;
const res = await fetch(`${import.meta.env.API_JSON}?page=${paged}`);
const posts = await res.json();
const total = await fetch(import.meta.env.API_JSON).then((res) => {return res.headers.get('X-WP-TotalPages')});
const page: {
current: number,
total: number
} = {
current: Number(paged),
total: Number(total)
}
const meta: {
title: string
} = {
title: `${paged}ページ目 - ${import.meta.env.BLOG_TITLE}`
}
---
<Layout meta={meta}>
<main>
{posts.map((post: { slug: string; title: { rendered: string }; content: { rendered: string }; date: string }) => (
<article><a href={`/${post.slug}`}>
<h2>{post.title.rendered}</h2>
<p>{format(new Date(post.date), 'yyyy年MM月dd日')}</p>
</a></article>
))}
<Pagination page={page} />
</main>
</Layout>
ページネーション部分は別コンポーネントで管理しました。components/Pagination.astro
で実装し呼び出します。
---
const { page } = Astro.props;
const prev = page.current-1;
const next = page.current+1;
---
<p>{page.current} / {page.total}</p>
<p>
{page.current!=1 && (
<a href={`/page/${String(prev)}`}>前のページへ</a>
)}
{page.current!=page.total && (
<a href={`/page/${String(next)}`}>次のページへ</a>
)}
</p>
記事詳細は[slug].astro
で動的パスで取得し、getStaticPaths
で生成します。ブラウザに表示されるタイトルは[記事タイトル – ブログ名]となります。
---
import { format } from 'date-fns';
import Layout from '../layouts/Layout.astro';
export async function getStaticPaths(){
const res = await fetch(import.meta.env.API_JSON);
const posts = await res.json();
const paths = posts.map((post: { slug: string }) => ({
params: { slug: post.slug }
}));
return paths;
}
const {slug} = Astro.params;
const post_res = await fetch(`${import.meta.env.API_JSON}?slug=${slug}`);
const [post] = await post_res.json();
const meta: {
title: string
} = {
title: `${post.title.rendered} - ${import.meta.env.BLOG_TITLE}`
}
---
<Layout meta={meta}>
<main>
<h1>{post.title.rendered}</h1>
<p>{format(new Date(post.date), 'yyyy年MM月dd日')}</p>
<div set:html={post.content.rendered} />
</main>
</Layout>
実装し終わったらプレビューしてテストします。
$ npm run dev
CSSでのデザイン実装や、metaタグ、フロント周りのマークアップで整えれば出来上がり。
関連記事
おしまい♥
おすすめ記事
- Next.js App Routerによるhead要素内の設定(meta OGPとかfavicon)
- JavaScriptのFetchAPIでXMLファイルを読み込む
- microCMS&Astroで記事のページネーションを実装
- スクロール中だけ要素のスタイルを変える
- さくらのレンタルサーバーのPHPとSQLiteを使ってみた
トラックバック & ピンバック
- この記事へのトラックバックURI:
- https://weblog.walk-life.me/astro_wordpress_cms/trackback/