WordPressのWP REST APIとNext.jsのSSGでサイトを作る

ReactとTypeScriptの学習も兼ねてWordPressのWP REST APIとNext.jsのSSGモードを利用した簡単な
当ブログの記事一覧を作成しました。CSSはTailwind.cssでホスティングはVercelで行なっています。

作った記事一覧サイト
https://next-blog-psi-self.vercel.app/

サイトを作るにあたって以下を参考にさせていただきました。
https://wp-kyoto.net/create-dynamic-posts-page-by-using-nest-js-ssg-and-wp-api-2/

WordPressのAPIを叩くライブラリを追加

yarn add wpapi
import WP from "wpapi";

export const wpClient = new WP({
    endpoint: `${process.env.API_URL}/wp-json`,
});

export default wpClient;

getStaticPropsで記事を取得

import { wpClient } from "@/lib/wpapi";

export const getStaticProps = async () => {
    const data = await wpClient.posts().perPage(10); // perPage()で表示ページ数指定
    
    return {
        props: {
            posts: data,
        },
    };
};

詰まったところ

getStaticPathsでの投稿数とページ数を取得

SSGにて動的ページを作る際、getStaticPaths関数でURLを動的に作っていきます。
WP REST APIでページネーションを実装する際、投稿数、ページ数を取得したかったのですが受け取れず。。。

他の参考サイトを見るとHTTPヘッダにX-WP-TotalとX-WP-TotalPagesが含まれているので以下のように書くと取れると書かれていますが、なぜか取れず。。。

response.headers.get('x-wp-totalpages') //これでは取れない

以下のようにデータを一度文字列のjsonにしてしまった後で再度jsonに戻すという方法でに書くことで投稿数、ページ数をgetStaticPathsで取得することができました。

import { wpClient } from "@/lib/wpapi";

const wpClient = new WP({
  endpoint: 'https://example.com/wp-json'
})

export const getStaticPaths = async () => {
    const pages = await wpClient
        .posts()
        .get()
        .then((response) => {
            return JSON.parse(JSON.stringify(response["_paging"]));
        });
    console.log(pages.total); //投稿数
    console.log(pages.totalPages); //ページ数
    const range = (start:number, end:number) => [...Array(end - start + 1)].map((_, i) => start + i);
    const paths = range(1, pages.totalPages).map((number) => String(`/page/${number}`));
    return {
        paths: paths,
        fallback: false,
    };
};

ページコンポーネント以外ではgetStaticPropsが使えない

最初ヘッダーやサイドバーのコンポーネントは直にgetStaticPropsを呼ぼうと考えていたのですが、getStaticPropsが呼ばれず。。。
どうやらページコンポーネントではないとgetStaticPropsは呼び出されないようです。

ですので子コンポーネントではuseState, useEffectでAPIを取得するようにしました。
※当初は以下のコードのようにして書いてみましたが、これではページを遷移するたびに毎回読みにいってしまうのでSSGの良さを引き出せないと思いやめました。
layout.tsxのコンポーネントをやめ、ヘッダーやサイドバーもpage層のファイルでgetStaticPropsを使う方がいいと思います。

import { ReactElement } from "react";
import { useState, useEffect } from "react";
import Footer from "@/components/footer";
import Header from "@/components/header";
import { wpClient } from "@/lib/wpapi";

type LayoutProps = Required<{
    readonly children: ReactElement;
}>;

export const Layout = ({ children }: LayoutProps) => {
    const [categories, setCategories] = useState([]);
    useEffect(() => {
        wpClient.categories().orderby('count').order('desc').then((response) => {
            setCategories(response);
        });
    }, []);
    return (
        <>
            <Header categories={categories} />
                {children}
            <Footer />
        </>
    );
};

開発環境では気づかなかったところ

開発環境ではWordPressの記事が更新された場合、記事一覧にちゃんと記事が表示されますが、
今回のようにVercelでデプロイした場合、vercelでビルドし直さない限り、記事が更新されることはありません。
SSGモードで静的出力した記事一覧なので普通に考えれば当たり前ですが、デプロイするまで全く気づきませんでした。。。

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。