microCMS + Next.jsで、記事ページ内に投稿済み記事ページのリンクをリッチに埋め込む
先日、趣味で作成したブログをアップデートしてタイトルのような機能を実装しました。
具体的には以下の画像の赤枠で囲んだ部分です。記事へのリンクを単なるaタグで実装するよりもずいぶん見た目がよくなりました。
対象の記事は以下から確認可能です。
この実装を行うと、microCMS側では記事へのURLをリッチエディタにベタ張りするようなことをせず、もっとスマートに入稿できるようになります。今回はどのように実装を行ったかについて簡単にまとめます。
microCMSのカスタムフィールドと繰り返しフィールドを使う
今回の実装に当たっては、microCMSに用意されている「カスタムフィールド」と「繰り返しフィールド」の合わせ技を使います。これらについては公式ブログに詳しい説明がありますので、事前に一読することをおすすめします。
具体的に私のブログの該当箇所がどのように入稿されているかというと、microCMS側の入稿画面は以下のようになっています。
リッチエディタとリッチエディタの間に、記事を選択するフォームが挟まっているのが確認できると思います。このように、カスタムフィールドと繰り返しフィールドを使うことで、基本的にはリッチエディタで入稿しつつ、一部分だけを別の形で入稿するということが可能になります。
そしてこのように入稿した記事をapiで取得すると、記事の本文は以下のようなjsonで返ってきます。(一部抜粋)
"contents": [
{
"fieldId": "richEditor",
"body": "<h3 id=\"h2f76e39300\">日本語に完全対応している</h3><p>Wiggleはすべてのページが日本語に対応しており、わざわざ英語を翻訳する煩わしさがありません。.....</p>"
},
{
"fieldId": "articleLink",
"article": {
"id": "hunt-wheel",
"createdAt": "2022-03-10T10:30:02.444Z",
"updatedAt": "2022-03-13T07:58:06.793Z",
"publishedAt": "2022-03-11T14:44:34.430Z",
"revisedAt": "2022-03-13T07:58:06.793Z",
"title": "初めてのホイールアップグレードにもおすすめ。ホイールメーカー「HUNT」の紹介",
"description": "ロードバイクを始めてしばらく経過すると交換したくなるパーツがホイールです。ホイールは高価なパーツのため購入しづらいですが、コスパに優れたホイールを取り扱う「HUNT」は初心者にもおすすめできるメーカーです。\n\n今回はHUNTの紹介と、実際に商品を注文してから到着するまでの流れについて紹介します。",
"contents": [
{
// id: hunt-wheel の記事本文
}
],
}
},
{
"fieldId": "richEditor",
"body": "<h3 id=\"haae3a20c4d\">サポートが割としっかりしている</h3><p>海外通販というと何かトラブルがあったときに問い合わせが対応がしづらい印象があると思います。 ....."
},
]
記事の本文を表すcontents
が配列で定義されており、その中に複数のobjectが設定されているのが確認できます。これは記事の本文を「繰り返しフィールド」で定義しており、繰り返しフィールドがカスタムフィールドで構成されているためにこのようになっています。
Next.js側ではfieldId
の文字列をもとに処理を分岐させます。今回の場合、fieldId
が記事リンク(articleLink
)の場合はcomponentを組み立てて結果を返し、それ以外ならhtmlをそのまま返す実装にする、というのが今回の概要です。
※私のブログではリッチエディタの入稿にも少し手を加えていますがここでは割愛します
microCMS側の設定
ここから前述の通りに記事を入稿できるようにするための設定をmicroCMS側に行っていきます。前提として、記事の一覧/詳細を表すAPIはすでに作成済みであることとします。
カスタムフィールドを作る(リッチエディタ)
まずは繰り返しフィールドの構成要素であるカスタムフィールドから作ります。記事の本文はリッチエディタと記事リンクの2つで構成されるという前提で進めるので、カスタムフィールドも2つ分作ります。
まずはリッチエディタ用のカスタムフィールドから説明します。
作成画面に移動する
今回は記事の一覧/詳細APIにカスタムフィールドを作りたいので、対象のコンテンツAPIを選択した後、画面右上にある「カスタムフィールド」をクリックします。
カスタムフィールド未作成の場合は以下のような画面になるので、「追加する」を押して作成画面に移ります。
基本情報入力
以下のような画面に遷移するので、リッチエディタ用のカスタムフィールドに必要な基本情報を入力します。
内容は任意ですが、今回は以下のようにします。
- カスタムフィールド名: リッチエディタ
- カスタムフィールドID: richEditor
ここで入力したカスタムフィールドIDはNext.js側でも使うことになるので、それを踏まえた文字列を設定しましょう。
APIスキーマを定義
次にリッチエディタのカスタムフィールドのAPIスキーマを定義します。
今回はリッチエディタが1つあればいいので、以下のようにします。
- フィールドID: body
- 表示名: リッチエディタ
- 種類: リッチエディタ
レイアウト
最後にカスタムフィールドを使った入稿をする際にどのようなレイアウトにするかを決める画面に移ります。
今回はリッチエディタが1つだけなのでこの設定はあまり意味がないです。
例えば1つのカスタムフィールドが複数の入力フォームで構成されるような場合はここで設定しておくと入稿しやすくなります。(アフィリエイトのリンクを入稿する場合など)
これでリッチエディタ用のカスタムフィールドは作成完了です。
カスタムフィールドを作る(記事リンク)
次に記事リンク用のカスタムフィールドを作成します。内容はリッチエディタとほぼ同じです。
基本情報入力
今回は以下のようにしておきます。
- カスタムフィールド名: 記事リンク
- カスタムフィールドID: articleLink
APIスキーマを定義
リッチエディタと異なり、記事を選択する項目としたいので、以下のように設定します。重要なのは「種類」の部分です。
- フィールドID: article
- 表示名: 記事選択
- 種類: コンテンツ参照
種類に「コンテンツ参照」を選択すると、どのAPIを参照するかを選択するモーダルが表示されるので、記事の一覧と詳細を表すAPIを選択します。
後はレイアウト選択ですが、リッチエディタと同様あまり意味がないので適当に設定します。
これでカスタムフィールドの作成は完了です。
繰り返しフィールドの設定
カスタムフィールドの設定が終わりましたが、繰り返しフィールドの構成要素となるものを定義しただけなのでまだ入稿できる状態にはなっていません。次に本文を入稿するための繰り返しフィールドを設定します。
記事の一覧と詳細を表すコンテンツAPIを選択し、APIスキーマの設定画面を開きます。
本文を入稿するためのフィールドを追加していきます。内容は以下のようにしておきます。
- フィールドID: contents
- 表示名: 本文
- 種類: 繰り返し
カスタムフィールドが正しく作られていれば、「繰り返し」を選択した際にカスタムフィールドの選択モーダルが表示されるので、両方にチェックを入れて決定をクリックします。
これで繰り返しフィールドが作成されました。
記事を入稿する
入稿する準備が整ったので、microCMSの入稿画面から記事を入稿します。
ここまでの設定が正しくできていれば、入稿画面の本文の箇所は次のように表示されているはずです。
ここで「フィールドを追加」ボタンをクリックすると、どのカスタムフィールドを使って入稿するかを選択できます。
ここで「記事リンク」を選択した場合は以下のようになり、入稿画面上で任意の記事を選択できるようになりました。
また追加した「記事リンク」の上下に+のアイコンがありますが、これをクリックすることでさらにカスタムフィールドを追加できます。「記事リンク」の上側の+アイコンをクリックし、リッチエディタを選択すれば図のようになります。
あとは必要な情報を入力して記事を公開すれば入稿側の設定は完了です。
Next.js側でカスタムフィールドに応じて処理を分岐させる
次にNext.jsの記事詳細画面で、取得した繰り返しフィールドのカスタムフィールドごとに処理を分岐させるという実装を加えていきます。
typescriptの型定義
今回は記事に対して以下のような型定義を設定しておきます。fieldId
はmicroCMS側で定義したfieldIdと一致させる必要があります。
※MicroCMSListContent
はmicrocmsのsdkをinstallすると利用可能な型です
export type Article = {
contents: (
RichEditorContent | ArticleLinkContent
)[];
} & MicroCMSListContent;
export type RichEditorContent = {
fieldId: "richEditor";
body: string;
};
export type ArticleLinkContent = {
fieldId: "articleLink";
article: Article;
};
繰り返しフィールドに応じて本文の表示を分岐
詳細ページの本文を表示するロジックは以下のようになります。getStaticProps等で記事の詳細情報をarticle
という名称で渡している場合の例です。
{article.contents.map((content, i) =>
content.fieldId === "richEditor" ? (
<div key={i} dangerouslySetInnerHTML={{ __html: `${content.body}` }}></div>
) : content.fieldId === "articleLink" ? (
<ArticleLink key={i} {...content} />
) : (
""
)
)}
カスタムフィールドがリッチエディタの場合は入稿されたhtmlをそのまま表示し、記事リンクの場合は任意の形でcomponentを組み立てた上で表示する、ということをしています。
これでカスタムフィールドに応じた本文の出し分けが可能になりました。
まとめ
microCMSの公式にもある通り、カスタムフィールドと繰り返しフィールドを組み合わせることで表現の自由度が格段に向上しました。チームでmicroCMSを利用するような場合は、こういった仕組みを使うとデザイナーとエンジニアでうまいこと分業ができそうだなと感じました。
この記事が参考になれば幸いです。
Discussion