Next.js + react-markdownでローカルのmarkdownをSSG

1 min read読了の目安(約1400字

TL;DR

  • fsgetStaticProps()の中で使うだけならブラウザで落ちたりしないので大丈夫
  • process.cwd()を上手く使ってファイルパス指定しましょう
  • react-markdownは便利

やりたいこと

よくあるサイトの規約ページなんかで、規約の内容をMarkdown管理したいときなんかに使います。

/
 ┣ docs/
 ┃ ┗ terms.md ← これをビルド時に取り込んで
 ┗ pages/
   ┗ terms.tsx ← このページに表示する

使ったもの

    "next": "^9.4.4",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "react-markdown": "^5.0.3"

ソースコード

terms.tsx

import fs from 'fs'
import { NextPage, GetStaticProps } from 'next'
import ReactMarkdwon from 'react-markdown'

type StaticProps = {
  terms: string
}

const Terms: NextPage<StaticProps> = (props) => {
  const { terms } = { ...props }
  return (
    <>
      <main>
        <ReactMarkdwon skipHtml={true}>{terms}</ReactMarkdwon>
      </main>
    </>
  )
}

export const getStaticProps: GetStaticProps = async () => {
  const terms = fs.readFileSync(process.cwd() + '/docs/terms.md', 'utf8')
  return {
    props: {
      terms: terms,
    }
  }
}

export default Terms

補足

  • process.cwd()がビルド時のワーキングディレクトリを返してくれるので、それにルートからのパスを結合するといい感じに取得できます。
  • 私の環境ではfs.readFileSync()の第二引数'utf8'を指定しないとビルド失敗しました。
  • skipHtml={true}ReactMarkdwonに渡してやると、HTMLタグを削除してくれます。例えば、規約の更新日をコメントで残したりする場合(<!-- 2020.12.15更新 -->)なんかに便利です。(するか?)
  • getStaticProps()はビルド時に一度呼び出されるだけですが、next devでdev serverを起動した際にはリクエストごとに呼び出されるそうです。