Astro からヘッドレスCMSとしてWordPressを使う
前回までで、Astroを使ってWebサイトを構築しましたが、ニュース部分についてはWordPressを使いたいと思いました。
WordPressにはREST APIがあらかじめ存在しますので、ちょっと試してみたくなりました。
WordPress側の準備
適当にWordPressをローカルPCにインストールし、投稿を4つほど作成しました。

(公開日が日本時間になっていませんでした。。。)
また、カテゴリー名を表示させたかった為、functions.phpにも必要なコードを追記しています。
WordPressのデフォルトのREST API ではカテゴリーIDしか取得出来ないようです。
add_action( 'rest_api_init', 'registerCategoryName' );
function registerCategoryName() {
register_rest_field( 'post', 'category_name', array('get_callback' => 'getCategoryName'));
}
function getCategoryName( $object ) {
$category = get_the_category($object['id']);
$cat_name = $category[0]->cat_name;
return $cat_name;
}これにより、取得した投稿の中に、「category_name」を追加出来ます。
そして、APIで取得できる情報には多数の不要な項目も含まれるため、今回必要な項目のみに絞ります。
add_action('rest_prepare_post', 'remove_post_links', 10, 3);
function remove_post_links($response, $post, $request) {
foreach($response->data as $key => $value) {
if($key == 'id' || $key == 'category_name' || $key == 'date') {
} else if($key == 'title' || $key == 'content') {
$response->data[$key] = $response->data[$key]['rendered'];
} else {
unset($response->data[$key]);
}
}
$links = $response->get_links();
foreach ( $links as $key => $value) {
$response->remove_link($key);
}
return $response;
}これにより、ID, date, title, content, category_name のみ取得するように出来ました。
Astro側の改修
インターフェースをAPIから取得する項目に合わせました。
export interface News {
id: number;
date: string;
title: string;
content: string;
category_name: string;
}ニュースを、WordPressのREST APIから取得するようにしました。
import type {News} from "@/interfaces";
// WordPressから投稿を取得
const res = await fetch("http://test.local/wp-json/wp/v2/posts/");
export const newsList: Array<News> = await res.json();
// idを指定してニュース1件を取得
export function getNews(id: number): News {
const result: News = newsList.find((news) => news.id == id);
return result;
}
// 日付文字列の整形
export function getDate(dateString: string): string {
const date = new Date(dateString);
const yy = date.getFullYear();
const mm = date.getMonth() + 1;
const dd = date.getDate();
return yy + "年" + mm + "月" + dd + "日";
}
// URLを取得
export function getUrl(id: number): string {
const url = `/news/news-${id}`;
return url;
}ニュースの一覧表示を変更しました。
---
import type {News} from "@/interfaces";
import { getDate, getUrl } from "@/newsList";
interface Props {
news: News;
}
const {news} = Astro.props;
---
<li class="item">
<span class="date">{getDate(news.date)}</span>
<span class="category">{news.category_name}</span>
<span class="newsTitle"><a href={getUrl(news.id)}>{news.title}</a></span>
</li>
<style>
li {
line-height: 2.5em;
border-bottom: 1px dashed;
}
li span:not(:last-child) {
margin-right: 20px;
}
.category {
width: 3em;
display: inline-block;
}
</style>出来上がり

まとめ
フロントエンドには、モダンなJSフレームワークであるAstroを利用し、コンテンツ管理には利用者の多く使い慣れたWordPressを使うという組み合わせを試してみました。
Astroの部分は他のフレームワークでも良いのですが、スピードが売り、という事で利用しています。
コンテンツ制作という意味では、現状でWordPressが使われなくなる未来はなかなか考えられない為、使い続けるのかなと思っています。
今回は大した変更なく対応出来たのでこの組み合わせは、ありな気がしています。
