MENU

Gatsby.jsでブログを作るための手順


2020年の夏から、ブログをWordPressからGatsbyに変えて一年ほど運用していました。

2021年9月現在は、ブログ自体はWordPressに戻しましたが、ポートフォリオはGatsbyJSで制作しています。

この記事では、はじめてGatsbyJSをブログを完成させるまでの手順をまとめておきます。

更新履歴

 2021/09/30 Gatsby v3の変更点をふまえて、全体的にリバイスしました。

この記事はこんな方にオススメ!
  • GatsbyJSってそもそもなんなのか知りたい
  • GatsbyJSとWordPressの違いを知りたい
  • GatsbyJSでブログを作ってみたい
目次

GatsbyJSとは?

GatsbyJSは、Reactベースの静的サイトジェネレーター。Reactで作られたフレームワークで、WebサイトのHTMLファイルを生成してくれるツールです。

WordPressなどのCMSは、データベースで記事を管理しています。
これは、ユーザーがURLにアクセスしたときに、データベースから必要な記事を取得して、HTMLファイルを生成して表示させる仕組みで動いています。

一方で、静的ジェネレーターは、コンパイル時に全てのHTMLファイルをあらかじめ生成していきます。URLにアクセスされた時には、生成済みのHTMLファイルを表示するだけなので、表示速度が早くなります。
また、サーバーやデータベースの管理も不要になるので、運営費用が安くすむ&セキュリティリスクが低くなるというメリットもあります。

GatsbyJSでブログを作るメリット

Gatsbyのメリット
  • サーバーが必要ないので、サーバー代が0円になる
  • ブログ記事をバージョン管理できる
  • ホームページの表示が早くなる

特にGatsbyは画像のプラグインが優秀で、画像を早く最適化して表示してくれます。

  • 画像の圧縮
  • 画面サイズに応じた表示
  • 遅延読み込み
Gatsbyのデメリット
  • 大量の記事を扱うメディアには向かない
  • gitやReact、GraphQLの知識が必要
  • 記事の装飾やレイアウトなどは自分でプログラムを書く必要がある

私は2020年の夏から、一年ほど、Gatsbyでブログを運営していました。
マークダウンで記事を管理できるのはとても便利でした。
ただ、吹き出しをいれる、飾り枠を入れるなど、HTML/CSSを書いて都度組み込む必要があるのが大変でした。

シンプルに文章を書く、画像を掲載するだけなら、問題ありません。
しかし、記事のレイアウトにこだわる場合は、WordPressのブロックエディターの方が使いやすいです。

一方で、画像の表示は早いですし、コンテンツの管理楽。
ポートフォリオの作品など、決まった項目を好きなレイアウトで表示させる系のウェブサイトには向いていると思います。

GatsbyJSのインストールとプロジェクト作成

更新情報

2021/09/30 Gatsby v3の変更点を反映しました。

ここからは、GatsbyJSでブログの作り方を紹介していきます。

基本は、Gatsbyのチュートリアルに沿って作っていくと間違いがないと思います。

今回作成したGatsbyJSブログの特徴
  • Gatsby v3で作成
  • CMSは使用せず、プロジェクト内で記事を保管
  • Markdownで記事を管理
  • 固定ページ/ブログ記事一覧/個別記事を作成

Githubでプログラムを公開しているので、ご参照ください。公開しているプロジェクトはポートフォリオサイトですが、この記事では、ブログ作成用に必要なプラグインや手順を解説していきます。

1. Gatsbyをインストール

Gatsbyをインストールします。

npm install -g gatsby-cli

2. スターターテーマのインストール

スターターテーマをインストールします。

npx gatsby new gatsby-starter-default https://github.com/gatsbyjs/gatsby-starter-default

gatsby-starter-defaultはプロジェクト名で、好きな名前に変えてOK。
そのディレクトリの中に初期ファイルが作成されます。

gatsby-starter-defaultディレクトリ内に移動し、開発サーバーを起動します。

cd gatsby-starter-default
gatsby develop

起動したら、Webブラウザで下記URLにアクセスします

http://localhost:8000/

画面上にGatsby Default Starterのレイアウトが表示されればOK!

ctrl+Cでサーバーを終了できます。

コマンド説明
gatsby buildビルド
gatsby develop開発用サーバーの起動
gatsby clean.cache とpublicを空にする

GatsbyJSでブログを作るまでにやったこと

プロジェクトの中身はこのようになっています。

gatsby-browser.js  // グローバルCSSやフォントのパッケージをここで読み込む
gatsby-config.js // 基本情報、プラグインの設定
gatsby-node.js // 特に使わない
gatsby-ssr.js // 特に使わない
src/
 ├ components/
   // ページ内で利用するパーツを入れる
   ├ header.js
   ├ layout.css
   ├ layout.js
   └ seo.js
 ├ images/
   // 画像を格納する場所
   └ gatsby-astronaut.png
 └ pages/
   // ページのレイアウト
   ├ 404.js // 404ページ
   ├ index.js // indexページ
   ├ page-2.js
   └ using-typescript.tsx  //使わないので削除

1 gatsby-config.jsの設定

gatsby-config.jsには、サイトの情報や、サイトに使うプラグインなどの設定を記載します。

サイトの基本情報を設定

  siteMetadata: {
    title: `Zero Forest`,
    description: `フリーランスエンジニアのブログ`,
    author: `@emmie0works`,
    siteUrl: `https://0forest.com/`,
  },

siteMetadata内のtitle, description, author, siteURLを自分のサイト用に書き換えます。

Faviconを設定

plugin内のgatsby-plugin-manifestのoptionに、自分のサイト用に変更します。


  plugins: [
    // 中略
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `Zero Forest`,
        short_name: `0forest`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, 
      },
    },
  ],
}

アイコンはsrc/images内に保管して、相対パスを記載します。

入力したら、ターミナルで「gatsby build」コマンドを実行すると、public/icons内が指定したアイコンになります。

2. ページの作成

ページの基本レイアウト

src/components/layout.jsで、ページのレイアウトを構成しています。

layout.js内で、ヘッダー部分(src/components/header.js)、フッター部分(src/components/footer.js)をインポートしています。

import * as React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"

import Header from "./header"
import Footer from "./footer"

const Layout = ({ children }) => {
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  return (
    <>
      <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
        <main>{children}</main>
      <Footer />
    </>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

ヘッダー

import * as React from "react"
import PropTypes from "prop-types"
import { Link } from "gatsby"
import logo from "../images/logo.png"
import * as styles from "../styles/_header.module.scss"

const Header = ({ siteTitle }) => (
  <header>
    <h1><Link to ="/"><img src={logo} alt={siteTitle} className={styles.logo} /></Link></h1>
    <nav>
      <ul>
        <li><Link to ="/">Top</Link></li>
        <li><Link to ="/blog">Blog</Link></li>
        <li><Link to ="/about/">About</Link></li>
        <li><Link to ="/contact/">Contact</a></li>
      </ul>
    </nav>
  </header>
)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header
画像の表示方法
//画像のインポート
import logo from "../images/logo.png"

//画像の表示
<img src={logo} alt={siteTitle} className={styles.logo} />

フッター

import * as React from "react"
import { Link } from "gatsby"
import * as styles from "../styles/_footer.module.scss"

const Footer = () => (
  <footer>
    <nav>
      <ul>
        <li><Link to ="/">Top</Link></li>
        <li><Link to ="/blog/">Gallery</Link></li>
        <li><Link to ="/about/">About</Link></li>
        <li><Link to ="/contact/">Contact</Link></li>
      </ul>
    </nav>
    <div className={styles.copyright}>© <a href="https://0forest.com">{siteTitle}</a></div>
  </footer>
)
export default Footer
リンク

内部リンクについては、<Link>タグを使います。(import { Link } from “gatsby”を忘れずに。)

外部リンクは<a>タグを使います。

各ページ

src/pages内のjsファイルが各ページのコンテンツになります。

  • index.js → /
  • about.js → /about/
  • 404.js → /404/

3. 画像の表示

GatsbyJSには2種類の画像コンポーネントがあります。

1.StaticImage
ヒーローイメージなど、テンプレート内で毎回同じ画像を表示させるときはStatic Imageコンポーネントを使う。

2.GatsbyImage
ブログ記事のアイキャッチ画像など、同じテンプレート内でもページによって表示する画像が変わるときにはDynamic Imageコンポーネントを使います。

GatsbyImageはブログページを作成するときに説明するので、ここではStaticImageコンポーネントの使い方を説明します。

使用するプラグイン
  • gatsby-plugin-image
  • gatsby-transformer-sharp
  • gatsby-plugin-sharp
  • gatsby-source-filesystem

画像表示には、上記のプラグインを利用します。(今回のスターターテーマには、すでにインストールされているので、改めてプラグインをインストールする必要はありません。)

インストールされていないテーマの場合は下記コマンドでプラグインをインストールします。
※gatsby-config.js内に上記プラグイン名が記載されていれば、インストール済みです。

npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp

続いて、gatsby-config.jsにプラグインの情報を追記します。

source-file-system内のpathは画像フォルダへの相対パスになります。

  plugins: [
    // 中略
    `gatsby-plugin-image`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
  ],

画像の表示方法

① gatsby-plugin-imageをインポートし、
② StaticImageタグで画像を表示させます。

index.js内に見本として、宇宙飛行士の画像が掲載されています。

import * as React from "react"
import { Link } from "gatsby"
import { StaticImage } from "gatsby-plugin-image" // ①gatsby-plugin-imageをインポート

import Layout from "../components/layout"
import Seo from "../components/seo"

const IndexPage = () => (
  <Layout>
    <Seo title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <StaticImage
      src="../images/gatsby-astronaut.png"
      width={300}
      quality={95}
      formats={["auto", "webp", "avif"]}
      alt="A Gatsby astronaut"
      style={{ marginBottom: `1.45rem` }}
    /> // ②StaticImageタグで画像を表示
    <p>
      <Link to="/page-2/">Go to page 2</Link> <br />
    </p>
  </Layout>
)

export default IndexPage

StaticImageにはいろんなオプションを指定できます。

OPTION説明
src画像への相対パスをいれる。外部の画像であればURLでもOK。
placeholder画像ロード中の表示方法を指定
dominantColor: デフォルト。元画像の主色を計算して表示
blurred: ぼやけた状態(低解像度)で表示
layout画像のサイズ方法を指定
constrained: デフォルト。画像の元サイズまたはwidth/heightのサイズで表示。比率を保持してコンテナ幅にフィットするようにリサイズされる。
fixed: 固定サイズでの表示。リサイズされない。
FullWidth: 常にコンテナ幅最大で表示。ヒーローイメージなどに最適。
width / height高さ、幅を指定

4 GatsbyJSでSassとCSS Moduleを使う

GatsbyJSni

CSSを扱う方法はいろいろとありますが、今回はSassとCSS Moduleを導入します。

Sassの導入

Sass用のプラグインをインストールします。

npm install --save node-sass gatsby-plugin-sass

gatsby-config.jsにプラグインを追記します。

module.exports = {
  siteMetadata: {
    // ...
  },
  plugins: [
    // ↓ここを追加
    `gatsby-plugin-sass`,
    // ...
  ]
}

プロジェクトの構成はこのとおり。stylesフォルダを作って、そこにscssファイルを入れていきます。

src/
 └ styles/
   ├ _global.scss
   ├ _setting.scss
   └ _button.module.scss

「_XXXX.module.scss」ファイルに、Sass形式でスタイルを記述していきます。

@charset "UTF-8";
@import 'setting';

.btn{
  margin-top: 2rem;
  margin-right: 1rem;
  border:1px solid $main_color;
  padding: 8px 30px;
  display: inline-block;
  color: $main_color;
  text-align: center;
  text-decoration: none;
  font-size: 0.9rem;
  position: relative;
  &:hover{
    background: $main_color;
    color: $white_color;
  }
  transition: all .2s linear;
}

jsファイル内でSCSSファイルをインポートして使います。

import React from "react"
import Layout from "../components/layout"
import * as styles from '../styles/_button.module.scss' // 追加

const Index = ({ data }) => {
  return (
    <Layout>
      <div style={{textAlign:`center`, margin:`2rem auto`}}>
        <Link to ="/service/" className={styles.btn}>ボタン</Link>
      </div>
      {/* その他省略 */}
    </Layout>
  )
}
export default Index
クラス名を複数つける場合
<div className={`aaa ${styles.bbb} ${styles.ccc}`}></div>

5 GatsbyJSでGoogle Fontを使う

fontsourceを使うと、GatsbyJSでもGoogle Fontが使えます。

フォントパッケージから、使いたいGoogle fontを選びます。

例えば、Open-Sansというgoogle fontを使う場合には下記のようになります。

npm install @fontsource/open-sans

続いて、gatsby-browser.jsにインポートします。

import "@fontsource/open-sans"

CSSにフォントファミリーを追記します。

body{ font-family: 'Open Sans', sans-serif; }

6 GatbyJSでFontAweseomeなどのアイコンを利用する

こちらの記事を参考にさせていただきました。

react-iconsのプラグインをインストール。

npm install react-icons –save

アイコンを使いたい時はreact-icons/xxからアイコンコンポーネントに名前をつけてインポートして、アイコンの表示箇所にタグを記載します。

パッケージ名やアイコンの名前は、React Icons の公式サイトから探します。

import * as React from 'react'
import {FaPinterest, FaGithub, FaTwitter, FaInstagram } from "react-icons/fa"

const Sns = () => {
  return (
    <div>
        <a
          style={{marginRight:10}}
          href={`https://twitter.com/@emmie0works`}
          target="_blank"
          rel="noopener noreferrer"
          >
          <FaTwitter />
        </a>
    </div>
  )
}
export default Sns

7 ブログ記事を表示する

記事を用意する

プロジェクトディレクトリの直下にブログ記事を格納するフォルダを用意します。

その中に、1記事1フォルダで記事を入れていきます。

プロジェクトディレクトリ/
├ blog/
  ├ post01/
  ├ ├ icatch.png // アイキャッチ
  │ ├ image.jpg // 記事内で使う画像
  │ └ index.md // 記事
  ├ post02/
  │ ├ icatch.png // アイキャッチ
  │ └ index.md // 記事
  ├ ...
├ src/

記事はこんな感じで記載します。

---
title: 記事タイトル
date: 2021-09-24
category: diary
featured: icatch.png
slug: hello-world
---
ここに本文を入れる。

↓このように、マークダウン形式で画像も表示できます。
[記事内で使う画像](image.jpg)

—から—の間に、メタ情報を入れていきます。

title記事のタイトル
category記事のカテゴリー
featuredアイキャッチの画像ファイル名
slug記事のスラッグ

他にも、tags(タグ)やmodifiedDate(更新日付)など、ブログ記事に入れたい情報をつけておくといいでしょう。

transformer-remarkをインストール

gatsby-transformer-remarkを導入することで記事のメタ情報(title, category, slugなど)を取得することができます。

gatsby-remark-imagesは記事から画像ファイルを相対パスで指定できるようにするためのプラグインで、本文内で画像を表示させるために使います。

npm install --save gatsby-transformer-remark gatsby-remark-images
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          // 中略
          { // ↓ブログの記事パスを追記
            resolve: `gatsby-source-filesystem`,
             options: {
               name: `blog`,
               path: `${__dirname}/content/blog`,
             },
          },
          { // ↓プラグインを追記
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 800,
              linkImagesToOriginal:false,
            },
          },
        ],
      },
    },

ここから、GraphQLを使っていきます。

gatsby developで開発サーバーを起動したら、下記URLにアクセスします。

http://localhost:8000/___graphql

下記のクエリを中央の欄に入力して、上部の「▶︎」ボタンを押して、実行してみましょう。
右側に取得された記事一覧が表示されます。

{
  allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {
    edges {
      node {
        frontmatter {
          category
          date
          slug
          featured {
            childImageSharp {
              gatsbyImageData
            }
          }
        }
      }
    }
  }
}

記事一覧の作成

src/
 ├ components
 ├ ...
 ├ pages
 │   └ blog
 │     ├ {MarkdownRemark.frontmatter__slug}.js // 各記事のテンプレート
 │     └ index.js // 記事一覧ページ
 ├ 404.js
 ├ index.js
 ├ ...

上記のファイル名にすることで、
記事一覧(index.js)のURLは/blog/、
各記事({MarkdownRemark.frontmatter__slug}.js)のURLは、/blog/スラッグ名/になります。

import * as React from 'react'
import { graphql } from "gatsby"
import Layout from '../../components/layout'
import Seo from "../../components/seo"
import PostCard from "../../components/postcard"

const Blog = ({data}) => {
  const posts = data.allMarkdownRemark.edges
  return (
    <Layout>
    <Seo title="Blog" />
    <section>
      <h2>Blog</h2>
      <div>
          {posts.map(({ node }) => {
            return <PostCard key={node.frontmatter.slug} node={node} />;
          })}
      </div>
    </section>
    </Layout>
  )
}
export default Blog
export const pageQuery = graphql`
{
  allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {
    edges {
      node {
        frontmatter {
          category
          date
          featured {
            childImageSharp {
              gatsbyImageData
            }
          }
          slug
        }
      }
    }
  }
}
`

export const pageQuery以降は先ほど、GraphQLで実行した記事一覧のクエリです。

このクエリの結果を、const posts = data.allMarkdownRemark.edgesに格納しています。

postsの配列から、各記事のデータを抜き出して、記事一覧を表示させています。

【Postcard:記事パーツ共通化】

import React from "react"
import { Link} from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image"

const PostCard = ({ node }) => {
  return (
    <Link to={`/blog/${node.frontmatter.slug}`}>
      <GatsbyImage
        image={node.frontmatter.featured.childImageSharp.gatsbyImageData}
        alt={node.frontmatter.title} />
        <div>{node.frontmatter.title}</div>
    </Link>
  );
}
export default PostCard

記事のテンプレート

import React from "react"
import { graphql } from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image"
import Layout from '../../components/layout'

const PostTemplate = ({data}) => {
  const { markdownRemark } = data
  const { frontmatter, html } = markdownRemark
  return (
    <Layout>
    <article style={{margin: `4rem auto`}}>
      <div>
        <div style={{margin: `0 auto`, textAlign:`center`}}>
        {frontmatter.featured && (
          <GatsbyImage
            image={frontmatter.featured.childImageSharp.gatsbyImageData}
            alt={frontmatter.title} />
        )}
        </div>
        <dl style={{marginTop: `4rem`}}>
          <dt>タイトル</dt>
          <dd>{frontmatter.title}</dd>
        </dl>
        <dl>
          <dt>日付</dt>
          <dd>{frontmatter.date}</dd>
        </dl>
        <div
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </div>
    </article>
    </Layout>
  )
}

export default PostTemplate

export const pageQuery = graphql`
  query($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
        date(formatString: "YYYY/MM")
        category
        featured {
          childImageSharp {
            gatsbyImageData(width: 800, placeholder: BLURRED, layout: CONSTRAINED)
          }
        }
      }
    }
  }
`
GatsbyImage

GraphQLに画像の表示条件などを記載して、画像情報を取得します。

featured {
          childImageSharp {
            gatsbyImageData(width: 800, placeholder: BLURRED, layout: CONSTRAINED)
          }
        }

表示するときは<GatsbyImage>タグを使います。(import { GatsbyImage } from “gatsby-plugin-image”を忘れずに。)

<GatsbyImage
            image={frontmatter.featured.childImageSharp.gatsbyImageData}
            alt={frontmatter.title} />

  • Gatsby公式:Gatsby Image plugin
  • もっとカスタマイズしたい人向けの参考図書:Webサイト高速化のための静的サイトジェネレーター

    以上が、ブログの基本構成になります。

    実際に作り始めると、もっとカスタマイズしたい部分が出てくるかもしれません。

    • Contentful(CMS)を使って記事を管理したい
    • カテゴリーページを作成したい
    • Google Analyticsを入れたい
    • RSSを導入したい

    GatsbyJSの本格カスタマイズには、「Webサイト高速化のための静的サイトジェネレーター」が参考になります。

    体系立ててGatsbyでサイトを作る方法が解説されています。

    • GraphQLの使い方、クエリの書き方
    • 画像を背景に表示させるやり方
    • メタデータ、OGPの追加方法
    • ページネーションの追加

    とっても役に立ちました。

    ただし、本の記載内容はGatsbyの前のverでの実装になります。

    最新版のGatsby v3では画像の表示方法と記事ページの生成方法が変わったので、この記事のコードを参考にしていただいた方がシンプルな記述になると思います。

    8 GatsbyブログをNetlifyで公開する

    最後に、作成したブログをWeb上に無料で公開する方法です。

    以上、GatsbyJSで基本的なブログの作り方でした。

    • URLをコピーしました!

    この記事を書いた人

    元エンジニア・コンサルタント→フリーランスへ。
    個人事業主さん向けにWordPress・HP作成の個人レッスンをしています。

    目次