Next.js + Netlify CMS でブログを作る

ブログ作りました!🎉🎉🎉 自分で作ったブログは機能こそ少ないですが、とても愛着が湧いていいです。せっかく作ったので、備忘録がてら今回作ったブログの作り方を書いておきます。

目次

- 構成
  - Next.js
  - Netlify CMS
- やったこと
- これから作りたいもの

構成

Next.js

React のフレームワーク。SSR や、ビルド時レンダリング(SSR っぽい略し方を知らない)を簡単にすることができる。ルーティングもフォルダ構成で簡単にすることができて便利。自分は今まで Next.js を全く使ったことがなかったので、チュートリアルを一通りやってなんとなく使い方を理解した。

Netlify CMS

静的ホスティングサービスNetlifyが提供している Git ワークフロー用 CMS。サイトに CMS 機能を追加することができる。

Scale & Ship Faster with a Composable Web Architecture | Netlify

Realize the speed, agility and performance of a scalable, composable web architecture with Netlify. Explore the composable web pla

やったこと

  • Next.js のセットアップ
  • Netlify CMS の設定
  • デプロイ

Next.js のセットアップ

自分はNetlify CMS の Next.js セットアップフローを進めて Netlify CMS with Next.js をセットアップしましたが、ブログを作りたいならこれはあまりおすすめしません。このフローでは markdown を react コンポーネントに変換する際に、frontmatter-markdown-loaderを使用していますが、これを使うとファイル名を指定して直接インポートする必要があるため、ファイル名を利用した dynamic routing ができませんでした。(できる方法があったら教えてほしい)

より良い方法として、Creating a Markdown Blog with Next.jsを見ながらすすめることをおすすめします。これに沿ってセットアップすればとりあえず Next.js でブログを作るところまで進められます。

Netlify CMS の設定

Next.js をつかった Markdown Blog を作ることはできたので、次はそれを Netlify CMS で管理できるようにしたいです。Netlify CMS の Next.js セットアップフローの Adding Netlify CMSより後を参考にするといいです。ここでは、admin/index.htmladmin/config.ymlの作成をして Netlify にデプロイしています。admin/index.htmlはコピペで済むのですが、admin/config.ymlは若干設定を変える必要があるので今自分が使っている設定を参考に、config.yml の設定をしてください。

backend:
  name: git-gateway
  branch: master
media_folder: public/img
public_folder: img
publish_mode: editorial_workflow
collections:
  - name: "blogs"
    label: "Blogs"
    folder: "posts/blogs"
    create: true
    slug: "{{fields.slug}}"
    fields: # The fields for each document, usually in front matter
      - { label: "Layout", name: "layout", widget: "hidden", default: "blog" }
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Slug", name: "slug", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Featured Image", name: "thumbnail", widget: "image" }
      - { label: "Body", name: "body", widget: "markdown" }

backend: backend のプロトコル設定。git-gateway をよくわかってないけど、レポジトリとサイトの間の通信を担っています。デプロイする branch を指定できますが、基本 master でいいと思います。

media_folder: 画像など、メディアファイルを格納する場所。Next.js は public 以下が静的アセットを格納する場所なので public 以下を指定します。

public_folder: 画像を公開するパス。Next.js であれば media_folder の public を抜いたものになるはずです。

publish_mode: このオプションは指定しなくてもいいですが、指定すると下書き機能が有効になります。便利。下書き中の記事はブランチ切って PR として保存されています。

collections: 記事のフォーマットを指定します。複数指定できるので、ブログ記事と作品一覧みたいな使い方もできそう。

collections の中のパラメータとして一番大事なのはcreate: trueです。これを指定しないと Admin の画面で編集ができません。あと、日本語の記事タイトルにするのであれば、slug: "{{fields.slug}}"は大事です。デフォルトでは、タイトルがファイル名になるので、日本語のタイトルを付けていると url が日本語になってダサいし長いです。fields に slag を追加して、slag を指定できるようにするとそれぞれファイル名を指定することができるようになります。fields は編集できる変数を追加できます。今自分が指定しているパラメータだと編集画面はこのように表示されます

Netlify cms 上での表示

デプロイ

Publishing to GitHub and Netlifyのとおりに進めればデプロイできるはずです!これでブログの完成!やったね!

つまづいたとこ

date の取得

Creating a Markdown Blog with Next.jsに従ってセットアップをしていましたが、markdown を取得するところでエラーになりました。

export async function getStaticProps({ ...ctx }) {
  const { slug } = ctx.params;
  const content = await import(`../../posts/${slug}.md`);
  const config = await import(`../../data/config.json`);
  const data = matter(content.default);

  return {
    props: {
      siteTitle: config.title,
      frontmatter: data.data,
      markdownBody: data.content,
    },
  };
}
SerializableError: Error serializing `.frontMatter.date` returned from `getStaticProps` in "/blogs/[slug]".
Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.

Next.js の SSG で AMP-only のブログを作った を参考に直しました。

Next.js の SSG で AMP-only のブログを作った

Next.js の SSG で AMP-only のブログを作ったのでそのメモ。

return するときに JSON.parse(JSON.stringify(returnData)) をすると治ります。(対症療法感がすごい)

これから作りたいもの

一旦はブログを作ることができました。ただ、一般的なブログに備わってる機能でまだ足りないものがいくらかあるのでこれから実装したいです。

  • OGP 設定
  • ブログカードなど、OGP の埋め込み設定
  • 関連記事など、回遊対策
  • SEO
  • 画像サイズの自動調節
  • sitemap.xml の設定
  • コード埋め込み時の言語に応じたコードハイライト

OGP 埋め込みと画像サイズは実装が悩ましい…… またいい感じの実装ができたらブログにします。ではでは

シェアする