Next.jsとヘッドレスWordPress運用における「サマリー」管理の課題
Next.jsによる高速なフロントエンドと、WordPressの柔軟な編集体験を組み合わせたヘッドレスCMS構成は、現代のWeb制作において非常に強力な選択肢です。しかし、この構成特有の「コンテンツ管理の悩み」に直面している方も少なくありません。
特に、「記事一覧ページに表示するサマリー(抜粋)」と「記事詳細ページの冒頭に置く要約リスト」の扱いは、多くの開発者が悩むポイントです。
課題1: 標準「抜粋」機能の限界と一覧ページでの表示問題
WordPressには標準で「抜粋(excerpt)」機能が備わっています。しかし、このフィールドはデフォルトでプレーンテキストしか受け付けず、HTMLタグが許可されていません。そのため、「サマリー内の一部を強調したい」「改行を入れたい」といったデザイン上の要求に応えにくいという問題があります。
かといって、抜粋欄が空の場合に適用される「本文の先頭から自動抜粋(`the_excerpt()`の挙動)」に頼ると、意図しない箇所で文章が途切れたり、本文冒頭の画像やコードブロックが中途半端に含まれてしまい、一覧ページのデザイン崩れを引き起こす原因となります。
課題2: 本文冒頭に「要約リスト」を含めることのデメリット
SEOやCRO(コンバージョン率最適化)の観点から、記事の冒頭に「この記事のポイント」や「要約リスト」を設置することは非常に有効です。読者は記事全体を読まずとも、概要を素早く把握できます。
しかし、この要約リストをWordPressの本文(`the_content` / Gutenbergエディタ)の先頭に直接書き込んでしまうと、前述の「本文の自動抜粋」機能が作動した際に、この要約リストがそのまま一覧ページのサマリーとして表示されてしまいます。
私たちが一覧ページで見せたいのは「記事全体を要約したサマリー」であり、「記事のポイントを箇条書きにしたリスト」ではありません。このように、本文(content)にメタ的な情報(サマリーや要約)が混在することは、コンテンツの再利用性を著しく低下させます。
解決策はACFカスタムフィールドによる「コンテンツの構造化」
これらの課題を根本的に解決するアプローチが、「コンテンツの構造化」です。
具体的には、WordPressの本文(content)エリアは純粋な「記事本文」だけを管理するものと割り切り、「サマリー」や「要約リスト」といったメタ的な情報は、専用の入力欄(カスタムフィールド)として分離・管理します。
なぜACF(Advanced Custom Fields)が最適なのか
この「カスタムフィールド」を直感的かつ柔軟に作成・管理できるのが、Advanced Custom Fields (ACF) プラグインです。
ACFを使えば、以下のような対応が容易になります。
- サマリー用フィールド: HTMLタグの使用を許可できる「テキストエリア」フィールドを作成できます。
- 要約リスト用フィールド: 「見出し」と「説明」のセットを動的に追加・削除・並べ替えできる「リピーター(繰り返し)フィールド」を作成できます。
このようにコンテンツを構造化することで、Next.js側(フロントエンド)は、必要なデータをAPI経由でピンポイントに取得し、デザイナーが意図した通りの場所に正確に配置できるようになります。
【手順1】WordPress (ACF) でカスタムフィールドを定義する
まず、WordPress側でACFプラグインをインストールし、有効化していることを前提とします(※リピーターフィールドはACF Pro版の機能ですが、必須級の投資です)。
「カスタムフィールド」メニューから新規フィールドグループを作成し、投稿タイプ「投稿」に関連付けます。
「サマリー(summary)」フィールドの作成(テキストエリア)
記事一覧ページで使いたい、HTMLを許容するサマリー用のフィールドを作成します。
フィールド ラベル:
サマリー
フィールド名:
summary
フィールドタイプ:
テキストエリア
改行:
自動的に <br> を追加する(または、WYSIWYGエディタを選択しても良いでしょう)
これで、投稿編集画面に「サマリー」という専用の入力欄が表示されます。
「要約リスト(point_list)」フィールドの作成(リピーター)
次に、記事詳細ページの冒頭に表示する「要約リスト」用のフィールドを作成します。これは、複数の「見出し」と「説明」のペアを管理できるリピーターフィールドとして定義します。
フィールド ラベル:
要約リスト
フィールド名:
point_list
フィールドタイプ:
リピーター
リピーターフィールドの内部構造(サブフィールド)
「要約リスト(point_list)」フィールドの中に、以下の2つのサブフィールドを作成します。
- ポイント見出し
- フィールド ラベル: ポイント見出し
- フィールド名:
point_title - フィールドタイプ: テキスト
- ポイント説明
- フィールド ラベル: ポイント説明
- フィールド名:
point_description - フィールドタイプ: テキストエリア(改行を許可)
これにより、編集者は「行を追加」ボタンを押すだけで、要約の項目を好きなだけ追加できるようになります。
【手順2】API (WPGraphQL / REST) へのフィールド登録
作成したACFフィールドをNext.jsから取得できるように、APIで公開(エクスポーズ)する必要があります。ヘッドレス構成では、WPGraphQLを使用する方法が最も推奨されます。
(推奨) WPGraphQL ACFアドオンを使ったGraphQLスキーマへの登録
WPGraphQL for Advanced Custom Fields というアドオン(無料プラグイン)をインストールして有効化します。
その後、先ほど作成したACFのフィールドグループ設定に戻り、「GraphQL で表示」という設定項目を「はい」に変更します。また、各フィールド(`summary`, point_list)の設定内にも「GraphQL で表示」のトグルがある場合は、それもオンにします。
WPGraphQL ACFアドオンでスキーマに登録
これだけで、WordPressのGraphQLスキーマ(GraphiQL IDEなどで確認可能)に、`summary` や pointList といったフィールドが自動的に追加されます。
(参考) REST API への登録方法
もしREST APIを使用している場合、ACF Pro版であればフィールドグループの設定で「REST API で表示」を「はい」にするだけで公開されます。無料版の場合は、`functions.php` などで register_rest_field を使った追加実装が必要になる場合があります。
【手順3】Next.js側でのデータ取得と表示(GraphQL例)
最後に、Next.js側(`getStaticProps` や getServerSideProps、またはApp Routerのfetch)で、WPGraphQLエンドポイントからデータを取得し、コンポーネントに渡して表示します。
記事一覧ページ(アーカイブ)での「サマリー」取得
一覧ページでは、各投稿のID、タイトル、スラッグなどに加えて、カスタムフィールドの summary を取得します。
クエリ例 (GraphQL)
query GetPostArchives {
posts(first: 10) {
nodes {
id
title
slug
# ACFで追加したフィールド(フィールドグループ名が 'postFields' の場合)
postFields {
summary
}
}
}
}
※フィールドグループ名(例: postFields)は、ACFのフィールドグループ設定で指定した「GraphQL フィールド名」に応じて変わります。
実装コード例 (React / JSX)
取得したデータを ArchivePage コンポーネントなどで展開します。`summary` フィールドはHTMLを含む可能性があるため、`dangerouslySetInnerHTML` を使用してレンダリングします。
// pages/blog/index.js (Pages Router例)
export default function ArchivePage({ posts }) {
return (
<div>
<h1>ブログ一覧</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
{/* ACFのサマリーフィールドを表示 */}
{post.postFields?.summary && (
<div
className="post-summary"
dangerouslySetInnerHTML={{ __html: post.postFields.summary }}
/>
)}
<a href={`/blog/${post.slug}`}>続きを読む</a>
</li>
))}
</ul>
</div>
);
}
セキュリティノート:
dangerouslySetInnerHTMLを使用する際は、入力ソースが信頼できること(CMS管理画面からの入力であること)を確認してください。ACFのテキストエリアはXSSのリスクを軽減するサニタイズ機能を持っていますが、万全を期す場合はdompurifyなどのライブラリを併用することも検討してください。
記事詳細ページでの「要約リスト」取得と表示
詳細ページでは、本文(`content`)に加えて、リピーターフィールドの pointList を取得します。`pointList` はオブジェクトの配列として返されます。
クエリ例 (GraphQL)
query GetPostDetails($slug: ID!) {
post(id: $slug, idType: SLUG) {
id
title
content # 本文
# ACFフィールド
postFields {
# リピーターフィールド(サブフィールドも指定)
pointList {
pointTitle
pointDescription
}
}
}
}
実装コード例 (React / JSX)
pointList は配列なので、`map()` メソッドでループ処理してリスト(`dl` タグや ul タグなど)としてレンダリングします。
// pages/blog/[slug].js (Pages Router例)
// (getStaticProps/Paths ... 省略)
export default function PostPage({ post }) {
const points = post.postFields?.pointList;
return (
<article>
<h1>{post.title}</h1>
{/* --- 要約リスト --- */}
{points && points.length > 0 && (
<div className="summary-box">
<h2>この記事のポイント</h2>
<dl>
{points.map((item, index) => (
<React.Fragment key={index}>
<dt>{item.pointTitle}</dt>
{/* 説明文(改行を <br> に変換する場合など) */}
<dd dangerouslySetInnerHTML={{ __html: item.pointDescription.replace(/\n/g, '<br />') }} />
</React.Fragment>
))}
</dl>
</div>
)}
{/* --- /要約リスト --- */}
{/* --- 本文 --- */}
<div
className="post-content"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
{/* --- /本文 --- */}
</article>
);
}
まとめ: ACFによる構造化でNext.jsとWordPressの連携を強化しよう
今回は、Next.jsとヘッドレスWordPressの構成において、ACF(Advanced Custom Fields)を活用して「サマリー」と「要約リスト」を管理・表示する方法を解説しました。
最大のポイントは、「本文(content)」と「メタ的な情報(summary, point_list)」を明確に分離することです。
- WordPress側で、ACFを使いコンテンツを構造化されたフィールドとして定義する。
- WPGraphQL(またはREST API)経由で、必要なデータをピンポイントで取得する。
- Next.js側で、取得したデータを意図したレイアウトに組み込む。
このアプローチにより、編集者は直感的にコンテンツを入稿でき、開発者はフロントエンドの柔軟性とパフォーマンスを最大限に高めることができます。ぜひ、貴社のヘッドレスCMS運用にお役立てください。
Next.jsでのヘッドレスCMS構築にお悩みですか?
「Next.jsとWordPressの連携がうまくいかない」
「パフォーマンスと編集体験を両立させたい」
「ACFのより高度な活用法を知りたい」
当社は、Next.jsとヘッドレスCMS(WordPress, microCMSなど)を用いた高パフォーマンスなWebサイト構築を得意としています。現状の課題ヒアリングから最適な構成のご提案まで、まずはお気軽にご相談ください。

