本ブログを WordPress から WordPress + Next.js の Jamstack 構成にアップデートしました。色々と学びがあったので、アウトプットしておきます。WordPress との連携については、こちらのブログ記事がかなり参考になりました。
Next.jsを使った静的なHeadless WordPressサイトの作り方
今回はその中でも Rest API の URL を作るクラスを掘り下げてみようと思います。ソースコードの全容はこちらになります。
v3.katsushi-ougi.com/UrlBuilder.ts at main · ANTON072/v3.katsushi-ougi.com
使い方は以下のようになります。
const urlBuilder = WPAPIURLFactory.init(process.env.WORDPRESS_URL)
.postType("posts")
.startAt(1);
`urlBuilder.getURL()` 実行すると、 `https://hoge.com/posts&startAt=1` のような URL を得ることができます。jQuery 的なメソッドチェーンが美しいです。中身を掘り下げていきます。
クラス名の WPAPIURLFactroy からわかるようにデザインパターンの一種の Factory パターン ですね。
僕の言葉で置き換えると、”同じ「作る」という動作をするにしても、何を作るかは変わるよね(下記のサンプルコードだと「製品」でも、車とバイクがあったり。で、その「製品」を作る人は「作る」しか意識したくないし(=再利用製を高める)、作る対象もフレキシブルに増やしたりしたいから、その「作る」と「製品の具体的な内容」を疎結合にしたいパターンだよ、ですかね)”
https://mame0112.hatenablog.com/entry/2015/07/26/195821
「REST API の URL を作る」という行為は共通だが、どういう URL を作るかは変わる。「URL を作る」と「URL 具体的な内容」を疎結合にした、ということでしょうか。init で 独自のオブジェクト と 共通メソッド群をもったオブジェクトを返却しています。new してインスタンスを生成する、というのは定番でよくやるのですが、ファクトリーパターンを使うとシンプルで見栄えもよいですね。
const api = {
path: "",
queryString: { ... }
}
return {
path(path: string) {
api.path = path
return this
}
}
各メソッドで this を return することにより、チェーンメソッドが可能となっています。
最終的に getURL メソッドを実行すると、api オブジェクトを文字列化したものが return されます。
getURL(): string {
const url = [endpoint, namespace, api.path].join("/");
const queryStringList = Object.entries(api.queryString);
const queryString = queryStringList
.reduce((prevQueries, [key, value]) => {
if (key === "embed" && value === true) prevQueries.push("_embed");
if (key === "search" && !!value)
prevQueries.push(`search=${value}`);
if (key === "slug" && !!value) prevQueries.push(`slug=${value}`);
if (key === "tags" && !!value) prevQueries.push(`tags=${value}`);
if (key === "after" && !!value) prevQueries.push(`after=${value}`);
if (key === "before" && !!value)
prevQueries.push(`before=${value}`);
if (key === "perPage") prevQueries.push(`per_page=${value}`);
if (key === "startAt") prevQueries.push(`page=${value}`);
if (key === "custom" && !!value) prevQueries.push(value);
if (key === "nextjs") prevQueries.push(`nextjs=true`);
return prevQueries;
}, [] as (string | number | boolean)[])
.join("&");
return [url, queryString].join("?");
},
reduce で文字列を生成するのがクールですね。TypeScriptの場合、初期化時の配列を型で定義する必要がありました。`[] as (string | number | boolean)[]`
REST API を実行する際に、あらゆる個所でこのクラスを利用しています。とても勉強になりました。