Gatsby でブログ作成

2024/11/28

Gatsby (v5) でブログで作成しました。

このブログも Gatsby で作成しています。(2024 年 11 月現在)

公式の gatsby-starter-blog などもありますが TypeScript で作成したかったので、これと公式 Tutorial を参考にしつつ新規でブログを作成しました。

Gatsby とは

  • React ベースの静的サイトジェネレータ
  • GraphQL を使用してコンポーネントへのデータの受け渡し
  • プラグインが豊富
  • etc...

使用技術

  • TypeScript
    • graphql-typegenにより、GraphQL で取得したデータの型定義が自動生成され、補完などが効くようになり便利です。
  • Tailwind CSS
    • ユーティリティファーストな CSS フレームワークで、容易にスタイリングができます。

プロジェクト作成までの手順

  • gatsby new でプロジェクト作成する。
  • 新規プロジェクト作成時に、質問が尋ねられるので、TypeScript と Tailwind CSS を選択する。
  • yarn develop でローカルサーバーを起動し、http://localhost:8000 で確認することができます。

ディレクトリ構成

  • content/blog 以下に記事を配置することで、ブログ記事を作成できます。
.
├── content
│   └── blog
│       ├── sample-01
│       │   └── index.md
│       └── sample-02
│           └── index.md
...
  • マークダウンファイルの先頭には以下のようにメタデータを記述し、記事の情報を付与します。
---
title: sample
date: "YYYY-MM-DD"
description: "sample description"
---
...

ブログ記事一覧ページ

  • gatsby-source-filesystem により、ローカルファイルシステムからファイルノードが作成されます。
  • ファイルノードから MarkdownRemark ノードへの変換は gatsby-transformer-remark により行われます。これにより、マークダウンファイルの内容が GraphQL で取得できるようになります。
  • 次の GraphQL クエリを使用して、gatsby-config.ts で設定したサイトのメタデータや、MarkdownRemark ノードの情報を取得することができます。
...

export const pageQuery = graphql`
  query IndexPage {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(sort: { frontmatter: { date: DESC } }) {
      nodes {
        frontmatter {
          date(formatString: "YYYY/MM/DD")
          title
          description
          thumbnailUrl
        }
        fields {
          slug
        }
      }
    }
  }
`;
  • コンポーネント側では次のようにして GraphQL クエリで取得したデータを使用することができます。
const IndexPage: React.FC<PageProps<Queries.IndexPageQuery>> = ({ data }) => {
  const posts = data.allMarkdownRemark.nodes;
...
                  <div>
                    <h2 className="text-xl font-bold">
                      {post.frontmatter?.title}
                    </h2>
                    <p>{post.frontmatter?.description}</p>
                    <p>{post.frontmatter?.date}</p>
                  </div>
...

ブログ記事ページ

  • テンプレートを使用して自動的にページを作成するための準備として、gatsby-node.ts で次のようにして markdownRemark ノードのフィールドに slug (URL の末尾の部分の文字列)を追加します。
import type { GatsbyNode } from "gatsby";
import { createFilePath } from "gatsby-source-filesystem";

export const onCreateNode: GatsbyNode["onCreateNode"] = ({
  node,
  actions,
  getNode,
}) => {
  const { createNodeField } = actions;

  if (node.internal.type === "MarkdownRemark") {
    const value = createFilePath({ node, getNode }).replace(/^\/|\/$/g, "");

    createNodeField({
      name: "slug",
      node,
      value,
    });
  }
};
  • /src/pages/posts/{markdownRemark.fields__slug}.tsx に記事ページのテンプレートとなるページコンポーネントを作成します。
    • markdownRemark ノードのフィールドの slug に設定された文字列を使用して、新規にページを作成します。
  • GraphQL クエリでは次にょうにしてブログ本体の HTML、記事のメタデータを取得します。
export const pageQuery = graphql`
  query PostPage($id: String) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        date(formatString: "YYYY/MM/DD")
        title
        description
      }
    }
  }
`;
  • コンポーネント側では次のようにすることで、 GraphQL クエリで取得したマークダウンの HTML を表示することができます。
...
        <div
          dangerouslySetInnerHTML={{
            __html: data.markdownRemark?.html || "",
          }}
          className="markdown-body"
        />
...
  • マークダウン部分のスタイルには github-markdown-css を使用しています。

その他

  • マークダウン部分以外のフォントには Google FontsNoto Sans JP を使用しています。

GitHub Pages にデプロイ

  • GitHub Pages にデプロイする場合、gh-pages パッケージを使用すると簡単です。
  • gatsby build --prefix-paths && gh-pages -d publicgh-pages ブランチにビルドされます。
    • example.com/blog のような URL で公開する場合、gatsby-config.tspathPrefix/blog を設定する必要があります。
  • リポジトリの Settings の Pages から、GitHub Pages で公開するブランチとして gh-pages を選択することで公開できます。

まとめ

実際に Gatsby を使用してブログを作成してみて、GraphQL によるデータの取得ができたり、プラグインが豊富であったりと、開発体験はとても良いなと感じました。

@seelx3/blog-gatsby-template ではブログとして機能させるための最低限の機能を実装したテンプレートを公開しています。 ページネーションなどは実装していませんが、必要に応じて容易に拡張できると思います。

© 2024 seelx3