Next.jsとMDXで個人ブログを作ってみた

Next.js と MDX で個人ブログを作ってみた

この記事の目標

この記事を読むと誰でも自前の個人ブログを作れるようになることを目指します。(記事のボリュームが想像以上に大きくなったので分割する予定です。)

個人ブログや企業のエンジニアブログのようなものを簡単に作ることができます。

Markdown ファイルを、HTML に変換して Web 上に公開することになるので、実装コードと一緒に記事の Markdown ファイルを Git 管理することができます。

技術スタックと開発環境

  • Next.js 14 系
  • TypeScript 4.4 系
  • MDX(Markdown を HTML 化)
  • Vercel(デプロイサーバー)
  • MaxOS Big Sir 11.5.2

なんで作ったか?

最新技術で日々メンテナンスが出来るものが作りたかったのが大きいかなと思います。

個人ブログのメインユーザーは、自分自身でありブログを読んでくださる方なので、エンジニアが作る Web サービスの個人開発にも似たような感覚です。

Next.js を使って見たかったといえば、それまでですが、SSG な Web サイトは 2020 年代に入ってから特に注目されている分野ですし、試すなら今!みたいな所もありました。

Qiita や Zenn もありがたく利用していますが、どうしても"いいね"のような数字にとらわれる感じで胃もたれしがちなので、消化の良さそうな個人ブログで胃の中をスッキリさせていこうと思います。

普段は Vue.js を使うことがほとんどなので、React.js を使うのはどうなの?という点については、全然問題ないです。

ドキュメントや先駆者のブログに大体の答えは書いてあります。

なんで Next.js にしたのか?

流行りのフレームワークの勉強をしたかったのと、大きな理由は SSG(Static Site Generation)できるからです。

静的なブログサイトを作るだけのために SSR や SPA ですと、初回レンダリングや SEO に課題があるため(改善方法はありますが)、要件を素早く解消してくれる Next.js を選定しました。

また Vercel へのデプロイと組み合わせると、Vercel の自動キャッシュ機能を利用することができ、デプロイごとに静的ファイルを自動でキャッシュしてくれます。詳細 ↓

https://vercel.com/docs/edge-network/caching

SSG の場合、初回レンダリングやパフォーマンスの面でも優れています。

軽く、SSG について整理をします。

SSG の大きな特徴は、予め HTML をレンダリングしておき、ユーザーからのリクエスト(画面遷移等)に応じて用意しておいた HTML を返却するだけといったものです。

これが SSG で無い場合は、ユーザーからのリクエストの度に HTML を生成して、それを返却する形式になっています。

今回はその SSG で生成する HTML を一部、Markdown からの変換された HTML でレンダリングするようにしています。

ブログ記事は Markdown で記述し、所定のディレクトリに配置するだけでルーティングも良い感じにしてくれる実装を今回はしました。

watsuyo.dev のドメインはどうしたの?

domain.com で買いました。

欲しいドメイン名は初めから決めていたので、国内外のドメイン販売サービスを比較しながら一番安い所で買いました。

GitHub に main ブランチを Push すると、予め連携しておいた Vercel のプロジェクトに Deploy されます。

後は Vecel と domain.com に IP アドレスを設定するだけで、watsuyo.dev にアクセスできます。

本題

ローカルにプロジェクトを作成する

まずはローカルに Next.js のプロジェクトを作成します。

今回は TypeScript を使いたいので、TypeScript の option をつけます。

$ yarn create next-app --typescript

デフォルトでは pages ディレクトリが src ディレクトリに入っていないので、src ディレクトリに移動をし、tsconfig.js にあるエイリアスの設定も変更します。

"compilerOptions": {
	"baseUrl": "src"
}

src 以下は、現段階では以下のような構成になります。

src 配下に配置するかしないかの判断基準は、画面実装に直接関係があるかで判断しています。

src
├── pages
│   ├── \_app.tsx
│   ├── api
│   │   └── hello.ts
│   └── index.tsx
└── styles
├── Home.package.css
└── globals.css

今後、共通コンポーネント作成した時には componentsといったディレクトリ配下にコンポーネントを配置して、componentsも src 配下に配置するのが妥当かと思います。

以下は、今回の最終目標的な構成になります。

src
├── Head.tsx
├── components
│   ├── Footer.tsx
│   ├── Header.tsx
│   └── styled
│   ├── PostContainer.ts
│   ├── StyledAnchorLink.ts
│   ├── StyledCard.ts
│   └── StyledLink.ts
├── global.ts
├── logic
│   ├── getAllPosts.ts
│   └── style.ts
├── pages
│   ├── \_app.tsx
│   ├── \_documents.tsx
│   ├── blog
│   │   ├── [title].tsx
│   │   └── sample-blog
│   │   └── index.mdx
│   ├── index.tsx
└── type.ts

プロジェクト作成ができたら

$ yarn dev

でローカルサーバーを立ち上げます。

立ち上がったらブラウザで確認してみると、以下のような画面が表示されると思います。

http://localhost:3000/

ひとまず、ブログを作る第一歩は完成しました。

適宜、commit をしておきましょう

次は package です。

初期の段階で以下のような package.json になっていると思うので

{
  略
  "dependencies": {
    "next": "11.1.2",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "17.0.21",
    "eslint": "7.32.0",
    "eslint-config-next": "11.1.2",
    "typescript": "4.4.3"
  }
}

今回の開発で必要になる yarn package をインストールします。

{
 略
  "dependencies": {
    + "@emotion/styled": "^11.3.0",
    + "@theme-ui/presets": "^0.11.2",
    + "gray-matter": "^4.0.3",
    "next": "11.1.2",
    + "next-mdx-enhanced": "^5.0.0",
    + "next-mdx-remote": "^3.0.4",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    + "react-icons": "^4.2.0",
    + "theme-ui": "^0.11.2"
  },
  "devDependencies": {
    "@types/react": "17.0.21",
    + "@typescript-eslint/eslint-plugin": "^4.30.0",
    + "@typescript-eslint/parser": "^4.30.0",
    + "babel-plugin-emotion": "^11.0.0",
    "eslint": "^7.32.0",
    "eslint-config-next": "11.1.2",
    + "eslint-config-prettier": "^8.3.0",
    + "eslint-plugin-react": "^7.25.1",
    + "eslint-plugin-react-hooks": "^4.2.0",
    + "prettier": "2.4.1",
    "typescript": "4.4.3"
  }
}

Markdown で書いたブログを HTML 化するために MDX 関係の package を追加します。 今回は Next が提供している @next/mdx ではなく、next-mdx-enhanced を使用します。 next-mdx-enhancedは、Next.js が MDX を読み込んで HTML 化してくれます。

gray-matterは、yaml 形式で記述したブログの情報を JS オブジェクト形式に変換してくれます。

以下のようにブログの情報を yml で記述できます。

---
title: 'Next.jsとMDXで個人ブログを作ってみた'
date: '2021/09/18'
description: 'コンテンツの内容'
img:
---

# 本文

next-mdx-remoteは、getServerProps や getStaticProps によって、Markdown を読み込むためのものです。

$ yarn next-mdx-enhanced next-mdx-remote gray-matter

今回は@emotion/styledを使用して、スタイルを当てたいと思います。

$ yarn add @emotion/styled

ダークモードを実装するのと Prism を使って、コードの syntax highlighting を利用したいので、theme-uiを追加します。

$ yarn add theme-ui @theme-ui/presets

React で icon を使いたいときは icon をコンポーネントとして import できる、react-iconsが便利です。

$ yarn add react-icons

今回、開発で必要な yarn package は以上ですが、お好みで ESLint や prettier の設定をすると、開発体験を向上できるかと思います。

package を入れ終わったら再度、yarn dev で正しく表示されているかを確認してみましょう。

画面を更新するようなことはしていないと思うので、先ほどと同じ画面が表示されるはずです。

1 つの記事で全て書き切ろうと思いましたが、ここまでかなりのボリュームになったので、続きは次回のブログにしようかなと思います。

次は早速、Markdown で書いたブログを HTML 化して表示させてみます。

参考

© 2022 watsuyo / This site uses Google Analytics.