November 11, 2020

Gatsby + Contentfulのブログ記事をMDXで書く方法

マークダウン記法は、簡単に文章構造を明示できる上、htmlも使えて非常に便利なんだけど、コンポーネントによってJSXも読み込めるMDXだとさらに便利。そこで今日は、Gatsby + Contentfulで構築したサイトのブログ記事を、MDXで書く方法をご紹介します。

Updated at December 24, 2020

皆さんご存知、マークダウン記法は、構文(#見出しなど)を簡単に書くことができる上、htmlも使えて非常に便利なんだけど、コンポーネントによってJSXも読み込めるMDXだとさらに便利。

そこで今日は、GatsbyJS + Contentfulで構築したサイトのブログ記事を、MDXで書く方法をご紹介します。

MDXとは?

MDXは、マークダウンのドキュメントにJSXを記述できるマークダウンの進化版です。

独自に用意したコンポーネントをインポートすることで、コンテンツ内にJSXを埋め込むことが出来るので、より簡単で便利に多様なコンテンツを作成することができます。

こんな感じで記述すると、

# Hello, *world*!

Below is an example of JSX embedded in Markdown. <br /> **Try and change the background color!**

<div style={{ padding: '20px', backgroundColor: 'tomato' }}>
  <h3>This is JSX</h3>
</div>

こんな感じで表示できる。

This is JSX

一度、MDXでブログを書き始めると、もうマークダウンには戻れません😉

Gatsby + Contentful のサイトを用意

まずは、Gatsbyで作られたサイトに、Contentfulのコンテンツが読み込まれた状態があることを前提とします。

これから作る方は、下記のリンクを参考にしてください。
プラグインがあるので簡単です。

参考:
GatsbyJS and Contentful in five minutes

では例として、Contentful上でブログ記事の本文を入力する Content Model を作成していきましょう。
Content Model の名前は Body として進めます。

ここが重要!
Content Model は、まず Text を選択。

Text

そして、ラジオボタンの Long Text を選択し、

Long Text

Markdown を選んでください。

Markdown

※ ContentfulにMDXはないけど、Markdown設定で大丈夫

そして、Contentful上で適当なコンテンツを入力しておきます。
ここでは Tomato というコンポーネントを追加する予定で進めます。

コンテンツの例:

Contentful
# MDXでブログを書くよ

<Tomato>Lorem ipsum dolor sit amet.</Tomato>

こんな感じ。

Content

MDX用のプラグインを追加

次にコマンドラインで、GatsbyでMDXを使うためのプラグインをインストールします。

npmでインストール:

コマンドライン
npm install gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react

yarnでインストール:

コマンドライン
yarn add gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react

gatsby-config.jsに追記

gatsby-config.js に、先ほどインストールした gatsby-plugin-mdx を定義します。

gatsby-config.js
{ 
  resolve: `gatsby-plugin-mdx`,
  options: {
    gatsbyRemarkPlugins: [
      // 他にRemarkプラグインがある場合はここに追加していく
    ],
  },
},

詳しくは下記のページを参考にしてください。

参考:
gatsby-plugin-mdx | Gatsby

GraphQLを確認

ここまでできたら、gatsby develop してみましょう。

GraphQLを見てみると、childMDX が追加されてるのが確認できます。

childMdx

つまり、こんな感じでデータを取得できます。

blog-post.js
export const query = graphql`
  query getPost($id: String!) {
    contentfulPost(contentful_id: { eq: $id }) {
      title
      description
      body {
        childMdx {
          body
        }
      }
    }
  }
`

独自のコンポーネントを作成

components フォルダに、shortcodes.js ファイルを追加します。

ここにContentfulの方で書いた <Tomato> コンポーネントを作ります。

shortcodes.js
import React from 'react'

const Tomato = ({ children }) => <div style={{ backgroundColor: `tomato` }}>{children}</div>

export { Tomato }

Markdownコンポーネントを作成

先ほど shortcodes.js で作った Tomato コンポーネントを、コンテンツ内で使えるように組み込みます。

まずは、components フォルダに、Markdown.js ファイルを追加。

Markdown.js
import React from 'react'
import { MDXRenderer } from 'gatsby-plugin-mdx'
import { MDXProvider } from '@mdx-js/react'

import { Tomato } from './shortcodes'

const shortcodes = { Tomato }

const Markdown = ({ children }) => (
  <div>
    {/* MDXProviderで独自に作成したコンポーネントをマークダウンに追加 */}
    <MDXProvider components={shortcodes}>
      {/* MDXRendererでコンテンツを表示 */}
      <MDXRenderer>{children}</MDXRenderer>
    </MDXProvider>
  </div>
)

export default Markdown

テンプレートにMarkdownコンポーネントを追加

最後に、ブログ記事のテンプレート内に、たった今作った Markdown コンポーネントを追加。

blog-post.js
const Post = ({ data }) => {
  const { title, description, body } = data.contentfulPost

  return <Markdown>{body.childMdx.body}</Markdown>
}

これで完成🙌

gatsby develop してみると…。

MDX blog

問題なく背景が赤くなってますね!

高橋あゆみ

高橋あゆみ
フリーランスのUI/UXデザイナー。英語圏のロマンス・ミステリー小説にハマり、一向に減らない積読が悩み。カナダのバンクーバー在住。