WordPressヘッドレス化(next.js)
前回までのあらすじ
WP GraphQLをインストールし、queryと吐き出されるデータを確認しました。
今回は以下を参考にして進めていきます。
ただし、こちらのサイトはREST APIなのでgraphQLに変更します。
https://kinsta.com/blog/headless-wordpress-next-js/
Next.jsのインストール
フロントをnext.jsを使って表示させるためインストールします。
上記の参考サイトを参考にインストール作業を行っています。
※最終的には、現行サイトに合わせてCSSを導入していきますが、今回はテスト的にnext.jsでgraphQL のデータを取得して表示させることを目的として進めていきます。
npx create-next-app@latest nextjs-wp-demo(お好きな名前で)
各設定は以下で行いました。
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
✔ What import alias would you like configured? … @/*
※Tailwind CSSは最終的には使いませんが、簡易的に表示させるためにインストールしておきます。
参考サイトに書いているとおりにgitのリポジトリからデータを落として、npm run devでローカルで確認します。
http://localhost:3000/ で以下のようなページが表示されるはずです。
このままでは、データを読み込んで表示はされないので、graphQLを使ってデータを読み込むためのコードを追加修正していきます。
まず、Appディレクトリー内に.env.localファイルを作成し、以下を記述
WORDPRESS_API_URL=‘wordpressで設定したgraphqlのURL’
続いて、app>page.js(これがトップページになります)を開きます。先にコードを記します。
1行目の「import Link from ‘next/link’;」
の下に、以下を追加
async function getPosts() {
const query = `
query MyQuery2 {
blogs(first: 3) {
edges {
node {
blogId
date
title
categories {
edges {
node {
name
}
}
}
writer {
nodes {
name
}
}
featuredImage {
node {
sourceUrl(size: LARGE)
}
}
}
}
}
}
`;
const response = await fetch(process.env.WORDPRESS_API_URL, {
body: JSON.stringify({ query }),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
next: { revalidate: 10 },
})
.then((res) => {
if (!res.ok) {
throw new Error('HTTPエラー ' + res.status);
}
return res.json();
})
.then((json) => {
return json.data.blogs.edges;
})
.catch((error) => {
console.error('エラー: ' + error.message);
});
return response;
}
</Link>の下に以下を追加
<h2>ブログ読み込み</h2>
<div className="posts">
{posts.map((post) => {
let writer;
let category;
let imageUrl;
if (post.node.featuredImage) {
imageUrl = post.node.featuredImage.node.sourceUrl;
} else {
imageUrl = '/img/common/noimg.png';
}
post.node.writer.nodes.map((writerData) => {
writer = writerData.name;
});
post.node.categories.edges.map((cat) => {
category = cat.node.name;
});
return (
<Link href={`/blog/${post.node.blogId}`} className="post" key={post.node.blogId}>
<div>{post.node.title}</div>
<div>{post.node.date}</div>
<div>{category}</div>
<div>{writer}</div>
<img src={imageUrl} width={200} />
</Link>
);
})}
</div>
最後にスタイルを修正します。
global.cssの110行目~147行あたりの以下のclassの「.blog-page 」を削除
以下の「.blog-page 」を削除
.blog-page .posts
.blog-page .post
.blog-page .post .post-img
.blog-page .post h3
.blog-page .post p
「.blog-page 」を削除後がこちら
.posts
.post
.post .post-img
.post h3
.post p
これで、最新のブログ記事3件が以下のようになったと思います。
http://localhost:3000/ で以下のようなページが表示されるはずです。
では、ざっくり説明します。
query MyQuery2
はじめのquery MyQuery2 はwprdpessで作ったgraphQLのqueryをそのまま貼ります。
blogs(first: 3)のfirst: 3ははじめの3件取得になります。
const response
次のconst response = await fetch(process.env.WORDPRESS_API_URL, {
は、fetchを使ってAPIからデータを読み込んでjsonを返しています。
process.env.WORDPRESS_API_URLは、.env.localで設定したものになります。
ブログ読み込み
</Link>の下に追加した部分は、console.logで、出力すると以下のJSONデータを持っています。
[
{
node: {
blogId: 1798,
date: '2023-11-01T11:55:00',
title: 'ナナサンホームページリニューアルの裏側',
categories: [Object],
writer: [Object],
featuredImage: [Object]
}
},
{
node: {
blogId: 1784,
date: '2023-10-24T16:30:36',
title: 'APNGでアニメーション画像を作ろう!',
categories: [Object],
writer: [Object],
featuredImage: null
}
},
{
node: {
blogId: 1773,
date: '2023-10-19T09:00:56',
title: '「確認漏れ」の減らし方',
categories: [Object],
writer: [Object],
featuredImage: [Object]
}
}
]
このJSONデータをmap関数で各記事データ毎にを表示する部分が以下です。
return (
<Link href={`/blog/${post.node.blogId}`} className="post" key={post.node.blogId}>
<div>{post.node.title}</div>
<div>{post.node.date}</div>
<div>{category}</div>
<div>{writer}</div>
<img src={imageUrl} width={200} />
</Link>
);
writer、category、imageUrlは、取得したデータ内で更に階層が深かったり、配列だったりするのでそれを取り出すためのmapなど使って取得しています。
if (post.node.featuredImage) {
imageUrl = post.node.featuredImage.node.sourceUrl;
} else {
imageUrl = '/img/common/noimg.png';
}
上記は、アイキャッチ画像がない場合は、準備している共通画像を表示するように指定しています。
今回は以上になります。
とりあえず、ブログ記事を指定数表示するようにしてみました。
弊社のトップページには、制作実績、お知らせなど複数投稿記事がありますので、次回は複数表示する場合を試してみたいと思います。