💻

GatsbyJSで作っているブログで gatsby-remark-component を使うのを止めて、 gatsby-plugin-mdx を導入した

2021-01-02

モチベーション

下記記事にある通り、Amazonのリンクなどをいい感じにするために gatsby-remark-component を使って、マークダウン内にスニペットを配置する方法を取っていた。

マークダウン内に下記のように記述すると、下記のような表示になる。ちなみに、 gatsby-remark-component の制約で <alink code="B01EJ7AK5O" /> とは記述できない。

sample.md
<alink code="B01EJ7AK5O"></alink>

しかし、記事の初回の読み込み時に上手く表示されなかったり、リンクを複数張るとリンク先のURLが別のURLになっていたり、スーパーリロードだと再現するけどリロードすると直ったり、と挙動が怪しい部分があった。調査してみたところ、どうやら、 gatsby-remark-component が原因だったようだ。

やったこと

やりたいこととしては、マークダウン内で、用意したReactコンポーネントを呼び出せれば良いので、MDXを使うアプローチに切り替えた。

gatsby-plugin-mdx | Gatsby

公式プラグインだし、安心感がある。ブログを作る際に gatsby-starter-blog のスターターなどを使っている場合、 gatsby-transformer-remark を使っているケースが多いと思うが、 gatsby-transformer-remark から移行する形で gatsby-plugin-mdx を導入する必要がある。移行用のドキュメントが用意されているので、こちらのドキュメントに従って、移行を行った。

Migrating Remark to MDX | Gatsby

gatsby-config.js で言うと、

gatsby-config.js
resolve: "gatsby-transformer-remark",
  options: {
    plugins: [
      {
        resolve: "gatsby-remark-component",	
        options: {
          components: ["rlink", "alink"],	
        },
      },
      ...

上記を下記に置き換える感じになる。 gatsby-transformer-remark に噛ましていたplugin達は gatsbyRemarkPlugins にそのまま渡してあげることで動作する。

gatsby-config.js
resolve: "gatsby-plugin-mdx",
  options: {
    extensions: [".md"],
    gatsbyRemarkPlugins: [
      ...

記事用のテンプレートファイルの中で、予めコンポーネントを読み込んでおくと、マークダウンファイル内で import せずともそのまま記述できる。

/src/templates/posts.js
const shortcodes = { AmazonLink, RichLink }
...
<MDXProvider components={shortcodes}>
  <MDXRenderer>{post.body}</MDXRenderer>
</MDXProvider>
sample.md
<AmazonLink code="B01EJ7AK5O" />

移行後に、動作確認をしてみたところ、上述していたバグが解消された。

その他

下記の置き換えをする際に、VSCodeの置換の正規表現が役に立った。便利。

sample.md
<alink code="B01EJ7AK5O"></alink>
sample.md
<AmazonLink code="B01EJ7AK5O" />
<alink code="(.+)"></alink>
<AmazonLink code="$1" />

おわりに

マークダウン内でReactコンポーネントを呼び出したいとなった場合に、 gatsby-remark-component を使う方法を紹介している記事がよく出てくるが、上述した通り、挙動が怪しい部分があるので、MDXを使うアプローチの方が良さそうに思う。

キクナントカ

キクナントカ

ソフトウェアエンジニアをしています。Flutter、Rails、GatsbyJSを主に触っています。趣味でボードゲームを制作したり、個人開発したりしています。詳しくはこちら