2026年10月16日
2026年10月16日
WordPressとAstroでサイトを作る方法:REST APIで記事を表示する基本構成
Astro は、ビルド時に HTML を生成する静的サイトを得意とする JavaScript のフレームワークです。WordPress と組み合わせる場合、Astro を WordPress のテーマとして wp-content/themes に置くのではなく、WordPress を記事の管理だけに使い(ヘッドレス CMS)、Astro のサイトが WordPress の REST API から記事を読み込んでページを作る、という構成になります。
この記事では、Astro のプロジェクトを作り、WordPress の記事一覧と記事ページを静的に生成して公開するまでの基本の手順を説明します。
この構成の仕組みと向き・不向き
役割は次のように分かれます。
| 役割 | 担当 | 内容 |
|---|---|---|
| 記事の作成・管理 | WordPress | 管理画面で記事を書き、REST API で記事を返す |
| ページの生成 | Astro | ビルド時に REST API から記事を取得し、HTML を書き出す |
| 配信 | 静的ホスティング | Astro が書き出した HTML・CSS・画像を配信する |
訪問者が見るのは Astro が書き出した静的なファイルなので、表示は軽く、WordPress 本体を公開サーバーに置かない構成も取れます。
その代わり、次の点が WordPress のテーマで作るサイトと変わります。
- 記事を公開・更新しても、Astro のサイトをビルドし直すまで表示は変わらない
- WordPress のテーマ、ウィジェット、テーマの見た目を変えるプラグインは使われない。デザインは Astro 側で作る
- コメント、問い合わせフォーム、サイト内検索など、サーバーで処理する機能は別の方法で用意する必要がある
更新が1日に数回程度のブログやコーポレートサイトに向いています。会員ごとに表示が変わるサイトや、数分おきに更新するサイトには、WordPress のテーマのままか、Astro でサーバー側描画を使う構成のほうが合います。
WordPress側の準備
REST API で記事を取得できるか確認します。ブラウザで次の URL を開き、JSON が表示されれば準備はできています(cms.example.com は自分の WordPress のドメインに置き換えます)。
https://cms.example.com/wp-json/wp/v2/posts?_fields=id,slug,title
表示されない場合は、次の点を確認します。
- 管理画面の「設定」→「パーマリンク」が「基本」になっていると、
/wp-json/の URL は使えません。「投稿名」など別の形式にします。 - セキュリティ系のプラグインやサーバーの設定で REST API を止めていないか確認します。
あわせて、投稿のスラッグは英数字とハイフンで付ける運用にしておきます。日本語のスラッグは REST API で URL エンコードされた文字列として返るため、Astro 側のページの URL が読みにくくなります。
Astroのプロジェクトを作る
Node.js をインストールした環境で、次のコマンドを実行します。対応する Node.js のバージョンは Astro の公式インストールガイドで確認してください。
npm create astro@latest -- --template minimal
質問に答えるとプロジェクトのフォルダーができます。作成したフォルダーに移動し、開発サーバーを起動します。
cd プロジェクト名
npm run dev
ターミナルに表示される URL(既定では http://localhost:4321/)を開くと、Astro の初期ページが表示されます。
続いて、プロジェクトの直下に .env ファイルを作り、WordPress の URL を書きます。
WP_URL=https://cms.example.com
PUBLIC_ で始まらない環境変数は、ビルド時のサーバー側の処理だけで読み込まれ、ブラウザに送られる JavaScript には含まれません。
記事を取得する関数を作る
src/lib/wp.ts を作り、記事を取得する処理をまとめます。
// src/lib/wp.ts
const WP_URL = import.meta.env.WP_URL;
export type WPPost = {
id: number;
slug: string;
date: string;
title: { rendered: string };
excerpt: { rendered: string };
content: { rendered: string };
};
export async function getPosts(): Promise<WPPost[]> {
const res = await fetch(
`${WP_URL}/wp-json/wp/v2/posts?per_page=100&_fields=id,slug,date,title,excerpt,content`
);
if (!res.ok) {
throw new Error(`WordPress API error: ${res.status}`);
}
return res.json();
}
_fields で必要な項目だけを指定すると、レスポンスが小さくなります。per_page の上限は100なので、記事が100件を超える場合は、レスポンスヘッダー X-WP-TotalPages を見ながら page を増やして全件を取得します(全件取得の書き方は関連記事で説明しています)。
取得に失敗したときに例外を投げているのは、WordPress に接続できないときに記事が0件のサイトをビルドして公開してしまうのを防ぐためです。
記事一覧ページを作る
src/pages/index.astro を次の内容に書き換えます。
---
// src/pages/index.astro
import { getPosts } from '../lib/wp';
const posts = await getPosts();
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>ブログ</title>
</head>
<body>
<h1>記事一覧</h1>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.slug}/`} set:html={post.title.rendered} />
</li>
))}
</ul>
</body>
</html>
WordPress の題名は ’ のような文字参照を含むことがあるため、set:html で HTML として出力しています。
記事ページを作る
記事ごとのページは、src/pages/blog/[slug].astro に getStaticPaths() を書いて生成します。静的サイトとしてビルドする場合、動的なルートにはこの関数が必要です。
---
// src/pages/blog/[slug].astro
import { getPosts } from '../../lib/wp';
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title set:html={post.title.rendered} />
</head>
<body>
<article>
<h1 set:html={post.title.rendered} />
<time datetime={post.date}>{new Date(post.date).toLocaleDateString('ja-JP')}</time>
<Fragment set:html={post.content.rendered} />
</article>
<p><a href="/">記事一覧へ戻る</a></p>
</body>
</html>
set:html は HTML をエスケープせずに挿入します。WordPress の本文は HTML なのでこの方法で表示しますが、記事を投稿できるのが信頼できるユーザーだけであることを確認してください。
開発サーバーで一覧のリンクをたどり、記事ページが表示されれば取得の設定は完了です。
ビルドして公開する
次のコマンドで静的ファイルを書き出します。既定では dist フォルダーに出力されます。
npm run build
npm run preview
npm run preview で、書き出したファイルを手元で確認できます。問題がなければ dist フォルダーの中身を静的ホスティング(Netlify、Cloudflare Pages、GitHub Pages など)で公開します。多くのホスティングは Git のリポジトリと連携でき、ビルドコマンドに npm run build、公開するフォルダーに dist を指定すれば、push のたびにビルドされます。その場合は .env をリポジトリに含めず、ホスティングの管理画面で環境変数 WP_URL を設定します。
運用で気をつけること
記事の更新とビルド:WordPress で記事を公開しても、ビルドし直すまでサイトには反映されません。ホスティングのデプロイフック(特定の URL に POST するとビルドが始まる機能)を、WordPress の記事公開時に呼ぶ仕組みを作ると自動化できます。
下書きとプレビュー:REST API で認証なしに取得できるのは公開済みの記事だけです。WordPress のプレビューボタンは WordPress のテーマで表示する仕組みなので、Astro での見た目は公開前には確認できません。
ブロックの見た目:本文の HTML にはブロックエディターのクラス名が付いていますが、そのスタイルは Astro 側にはありません。使っているブロックのスタイルを Astro 側の CSS で用意します。
プラグインの機能:ショートコードは展開済みの HTML として content.rendered に入りますが、プラグインが読み込む CSS や JavaScript は付いてきません。フォームやコメントは外部のサービスか Astro 側の実装に置き換えます。
画像:本文中の画像は WordPress のメディアの URL のまま表示されます。WordPress を非公開にする場合は、画像の配信方法も決めておく必要があります。
まとめ
- Astro は WordPress のテーマではなく、REST API から記事を読み込んでページを作る別のサイトとして構成する
- WordPress 側はパーマリンクを「基本」以外にし、
/wp-json/wp/v2/postsが JSON を返すことを確認する - 記事の取得処理をまとめ、取得に失敗したときはビルドを止める
- 記事ページは
getStaticPaths()で生成し、本文はset:htmlで出力する - 記事を更新したらビルドし直す必要があり、プレビュー、ブロックのスタイル、フォームなどの扱いを事前に決めておく