GatsbyJS + Netlify + MDXでブログ作ってみた

GatsbyJS + Netlify + MDXでブログ作ってみた
Photo by Yuka Yamazaki / Unsplash

以前から技術的なことはQiita、それ以外ははてなブログに書くようにしていたんですが、Qiitaは色々問題が出てきて投稿するのをためらうようになり、はてなもちょっと使うのを躊躇するようになってしまってどこにもアウトプットが出来なくなってしまいました。

まあなんとなく察して下さい。

ってことで何か良いサービスないかなと探したんですが良いものが見つからず結局自分で作るかということになりました。

ちなみに要件はこんな感じでした。

  • Markdownで書ける
  • エクスポートできる
  • OGPがいい感じになる
    • はてなブログとかQiitaとかのイメージ
  • 今どきの見た目
  • 技術的な記事以外もOK
  • メンテナンスコストなし(できれば)
  • 独自ドメイン設定できること(マストではない)

もし何か良いサービスあれば教えてください。

Qrunchは結構条件に当てはまったんですが、技術的な記事以外がNGだったので今回は見送りました。

技術スタック

  • Gatsby
  • Netlify
  • MDX(Markdownからコンポーネント呼べるMarkdown拡張版)

構成的には何番煎じか分からないくらいメジャーな構成かなと思います。

ホスティング場所は静的サイト作るならNetlify一択かなと。

MDXについては、ただのMarkdown(Remark版)にするか悩んだんですが外部リンクをいい感じに表示したりとか追々色々やりたくなるだろう思ったのでとりあえずでMDXにした感じです。GatsbyのブログテーマもMDXが標準なのでブログ作るならMDXで良いかなって感じはします。

ちなみに、WordPressじゃなくてGatsbyにしたのは、はてなブログの前はWordPressで一回作ったことがあったんですが管理辛いなってことではてなブログに移行したって経緯があるためです。

工夫したこと

OGP画像の自動生成

要件にも入れてた通りOGPの画像を毎回作るのはちょっと大変なので自動で生成するようにしました。

catchy-imageを使わせてもらっています。作者の方のブログ記事が参考になりました。

独自プラグインの読み込み部分だけはMDXだと上手くいかなかったので変更加えてます。

// 省略
{
  resolve: 'gatsby-plugin-mdx',
  options: {
    gatsbyRemarkPlugins: [
      {
        // highlight-start
        resolve: require.resolve('./plugins/gatsby-remark-og-image'),
        // highlight-end
        options: {
          output: {
            directory: '',
            fileName: 'og-image.png',
          },
          image: {
            width: 1200,
            height: 630,
            backgroundColor: '#164c7f',
          },
          style: {
            title: {
              fontFamily: 'Noto Sans CJK JP',
              fontColor: '#DDDDDD',
              fontWeight: 'bold',
              fontSize: 64,
              paddingTop: 100,
              paddingBottom: 200,
              paddingLeft: 150,
              paddingRight: 150,
            },
            author: {
              fontFamily: 'Noto Sans CJK JP',
              fontColor: '#DDDDDD',
              fontWeight: '400',
              fontSize: 42,
            },
          },
          meta: {
            title: '',
            author: 'deg84',
          },
          fontFile: [
            {
              path: require.resolve(
                './src/fonts/NotoSansCJKjp-Bold.otf'
              ),
              family: 'Noto Sans CJK JP',
              weight: 'bold',
            },
            {
              path: require.resolve(
                './src/fonts/NotoSansCJKjp-Regular.otf'
              ),
              family: 'Noto Sans CJK JP',
              weight: '400',
            },
          ],
          iconFile: require.resolve('./content/assets/icon.png'),
          timeout: 10000,
        },
      },
    ],
  },
},
// 省略

MDXファイルのディレクトリ構成

フラットにすると記事数が増えてくると辛くなってくるので年月毎にフォルダ分けするようにしました。

content
├── assets
│   └── icon.png
└── posts
    └── 2020
        └── 07
            ├── hello-gatsby
            │   └── index.mdx
            ├── hoge
            │   └── index.mdx
            └── hoge2
                └── index.mdx

URLに年月は入れたくなかったのでslugを作るところも正規表現で年月を除くようにしてあります。

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions

  if (node.internal.type === 'Mdx') {
    const value = createFilePath({ node, getNode }).replace(/^\/[0-9]{4}\/[0-9]{2}/, '') // highlight-line

    createNodeField({
      name: 'slug',
      node,
      value
    })
  }
}

シンタックスハイライト

prism-react-rendererを使って実現しました。

Remark版でよく使われるgatsby-remark-prismjsはMDXだとあまり推奨されていないみたいです。

行ハイライトの対応

Remark版の場合は、gatsby-remark-prismjsで対応されているので特別な対応は必要ないんですが、prism-react-rendererを使っているので自分で対応する必要がありました。

How to highlight lines · Issue #26 · FormidableLabs/prism-react-rendererにあるコードを参考に対応しました。

タイトルの対応

MDX版でもRemark版のプラグインが使えるのでgatsby-remark-code-titlesを使っています。

今後やっていきたいこと

  • 見た目の調整
  • TwitterとかYouTubeとかの埋め込み
  • 外部へのリンクをリッチにする
  • 目次を表示する

おわりに

ということで今後はこちらに色々書いていきたいと思います。よろしくおねがいします。

参考