メインコンテンツへスキップ

Gatsbyによるブログ構築

··4 分·
Netlify Gatsby Blog
Makoto Morinaga
著者
Makoto Morinaga
技術メモ、コーディング、環境構築のための個人ノート。
目次

注意

現在、GatsbyからHugoに以降済です。以下は過去の内容になります。

ブログをWordPressからGatsbyに移行したため、その理由と手順をまとめます。

ブログを自宅サーバ上に立てたWordPressで、markdown記法の記事を公開していましたが、常々記事を「githubで管理」&「よりシームレスに公開・管理」と思っていました。

そこで、本記事では、以下の目次の流れでブログを構築していきます。 なお、記事量が多くなってしまったため、別記事として切り出している箇所もあります。

サービス・技術選定
#

まず、以下の理由を解消するためのサービス・技術を選定します。

  • 現在の自分の運用では、markdownで書いた記事をWordPressで公開する際に投稿欄に貼り付ける必要があるので、面倒。
    • 記事を書いているコマンドラインからプレビュー画面への出力がダイレクトにできれば良いので、ローカルで開発環境をたてられる静的サイトジェネレータ(Static Site Generator、以下SSG)を使えば、できそう。
  • WordPressのプレビュー画面から正確な記事デザインが見えるので、記事公開直前にWordPressと手元のMarkdownファイルをいったりきたり。
    • 1つ目と同様にSSGで解消できそう。
  • どんな更新をしたのか差分が分かりづらい(たまにWordPress上での自分の誤操作で文章がおかしくなってた…)。
    • Githubで管理すれば、差分が確認できるし、切り戻しも簡単。
  • WordPressのプラグインは凄く便利だけど、プラグイン更新がちょっと大変。
    • 動的サイトより静的サイトのほうがセキュリティリスクが低いので、頻繁なプラグイン更新を気にしなくても良いかも。なら、静的サイトが作れるSSGだな。
  • masterリポジトリにpushしたら、ブログを自動更新したい。
    • Github Actionsを使えば、BuildとDeployができそう。
  • なにやらSSGっておもしろそう。
    • うん、SGGやってみよう。

ちょっとSSGありきな感じがしますが、使うサービス・技術としては、SSGとGithub(+ Actions)が良さそうです。

また、デプロイ先としては、自宅サーバ上のNginxか静的コンテンツのホスティングサービスの2つの選択があります。 Github ActionsからDeployをするつもりなので、自宅サーバへDeployする場合は、sshで外部からアクセスできるようにしなければなりません。 心情的にVPNを通さない自宅サーバへのsshアクセスを許可したくなかったので、今回はホスティングサービスを利用することにしました(ホスティングサービスを使ってみたかったというのもあります)。

つまり、SSGとGithub(+ Actions)とホスティングサービスの構成になりました。

SSGの選定
#

SSGとは
#

SSGの詳細については、具体的に解説されているサイトが多いので、そちらをご参照いただければと思います。

SSGとは、簡単にいうと静的サイトを生成するためのソフトウェアです。 SSGでは、生成(ビルド)時に全てのHTMLを最初に生成し、生成されたファイルをホスティングサービスやWebサーバ上で公開します。 WordPressは、動的サイトといってアクセスがあった際にDBのデータを元にサーバでHTMLを生成して返します。 一般的なSSGのメリット・デリットには以下があります。

  • SSGのメリット
    • 動的サイトに比べ、セキュリティのメンテナンスコストが低い
    • 事前にHTMLを生成しているので、動的サイトと比較してレスポンスが高速
    • DB等がないため、バックアップが容易(Githubで管理ができる)
  • SSGのデメリット
    • ページ数が多いと、生成に時間がかかる
    • SSG単体では動的な機能(コメント機能やアクセス数管理)が利用できない
    • API等で外部から情報を取得している場合は、生成したタイミングのデータで固定される
    • プログラミング知識が必要(私はむしろうれしい…)

つまり、私のようなアウトプットを目的とした個人ブログならば、動的サイトでなくとも静的サイトでほぼ問題がありません。

SSGの選定
#

SSGには、Nuxt(JavaScript/Vue)、Next(JavaScript/React)、Gatsby(JavaScript/React)、Hugo(Go)など多数存在しています。

私は、JavaScriptとGraphQLをちゃんと使ってみたかったので、Gatsbyを選択しました。

ホスティングサービスの選定
#

SSGで生成したhtmlを公開するためには、ホスティング先が必要です。 Gatsbyのドキュメントを見ると、対応しているホスティングサービスが大量にあります。

今回は、GatsbyとGithubの連携記事も多く、私のブログだと無料枠で収まりそうなNetlifyを選択しました。

Gatsbyでのブログ構築準備
#

Starterの選択
#

Gatsbyでは、最初に構築する際にテンプレート(Starter)を選択して構築する仕組みになっています。 色々なテンプレートが公式やコミュニティで公開されていますので、その中から自分が作りたいブログに近いStarterを選択するとすぐにブログが公開できます。

私はなるべく自分でブログ自体を構築したかったので、公式のgatsby-starter-blogを選択しました。 gatsby-starter-blogのリンク先をみてもらうと分かるとおりシンプルな一覧ページと記事で構成されたstarterです。カスタマイズのしがいがありそうです。

Node.jsのインストール
#

gatsbyをローカル環境で動かすためには、Node.jsが必要になります。 Node.jsのインストールについてはOSごとで異なり、複雑なので、今回は割愛します(いつか記事にしたい)。

とりあえず、nodebrewを使って安定バージョンであるNode.js v14.15.5をインストールしています。

Gatsby CLIのインストール
#

Gatsbyのコマンドを実行するために、以下のコマンドを実行します。

Terminal
npm install -g gatsby-cli

ターミナルを再起動し、以下のコマンドが正常に実行できれば、インストール成功です。

Terminal
gatsby --help

初回構築
#

以下のコマンドでgatsby-starter-blogをもとにブログを初期構築します。

Terminal
gatsby new mkt3.dev https://github.com/gatsbyjs/gatsby-starter-blog

mkt3.dev はディレクトリ名なので、任意の名前にしてください。

生成されたディレクトリに移動して、develop(開発モード)でブログを起動します。

Terminal
cd mkt3.dev
gatsby develop

これで、http://localhost:8000 にブログが以下のように構築されました。

Gatsbyで実現したい機能
#

とりあえず、WordPressで気にいっていた機能をなるべくGatsbyでも実現したいです。 この初期状態から追加したい機能をリストアップすると以下になります。 全部をこの記事に載せると大変なので、簡単にできるものから書いていきます。

  • PostCSSとSCSSの有効化
  • Header・Footer・SideBarの追加
  • 本文の目次の追加
  • 記事の更新日時をgithubでの更新日時に変更
  • paginationの追加
  • categoryページ・tagページの追加
  • 関連記事ぺージの追加
  • 日付のフォーマットを日本用に変更
  • Shareボタンの追加
  • コメント機能の追加
  • Sidebarのコンテンツ拡充
    • 検索バーの追加
    • 人気記事リストの追加
    • twitterタイムライン追加
    • カテゴリ一覧の追加
    • タグクラウドの追加
    • 最新記事一覧の追加
    • 追従する目次の追加
  • お問い合わせページ・プロフィールページの追加
  • プラグイン対応
    • gatsby-plugin-sitemap
    • gatsby-plugin-robots-txt
    • gatsby-remark-external-links
    • gatsby-remark-line-breaks
  • Google AnalyticsとGoogle Searchコンソールへの登録
  • デザインの修正
  • レスポンシブル対応
  • Google AdSenseの登録

PostCSSとSCSSの有効化
#

PostCSS
#

PosCSSでは、生成されたCSSをJavaScriptのプラグインで変換することができます。 PostCSSのプラグインは色々ありますので、以下を採用します。

  • autoprefixer:ベンダープレフィックスを自動で付与するプラグイン
  • postcss-pxtorem: px表記をrem表記に変換するプラグイン

以下のコマンドでプラグインをインストールします。 なお、Gatsbyのプラグインをインストールする場合は、コマンドを作業ディレクトリ(ローカルリポジトリ)内で実行します。

Terminal
npm install --save-dev autoprefixer postcss-pxtorem

リポジトリ直下に以下の postcss-config.js を作成します。 この postcss-config.js でプラグインのロードとプラグインごとの設定をします。

postcss-config.js
'use strict'

const pxtorem = require('postcss-pxtorem')
const autoprefixer = require('autoprefixer')

module.exports = [
  pxtorem({
    rootValue: 16,
    unitPrecision: 5,
    propList: [
      'font',
      'font-size',
      'height',
      'line-height',
      'letter-spacing',
      'margin',
      'margin-top',
      'margin-left',
      'margin-bottom',
      'margin-right',
      'padding',
      'padding-top',
      'padding-left',
      'padding-bottom',
      'padding-right',
      'border-radius',
      'width',
      'max-width'
    ],
    selectorBlackList: [],
    replace: true,
    mediaQuery: false,
    minPixelValue: 0
  }),
  autoprefixer()
]

gatsby-config.js の先頭付近に以下を追記して postcss-config.js を読み込みます。

gatsby-config.js
const postCssPlugins = require('./postcss-config.js')

読み込んだPostCSSは後述のSCSSのプラグインと組み合せて有効化します。

SCSS
#

スタイルシートをCSSからSCSSに変更します。 SCSSはCSSを拡張しており、入れ子構造や変数利用等、格段にスタイルシートの記述が楽になります。

GatsbyでSCSSを有効化するには、gatsby-plugin-sassプラグインを使います。 また、このプラグインは、CSS Moduleにも対応していますので、SCSSとCSS Moduleを組み合せてスタイルシートを記述します。

以下のコマンドでgatsby-plugin-sassをインストールします。

Terminal
npm install sass gatsby-plugin-sass

次に gatsby-config.js に以下を追記してプラグインを有効化します。 5行目で先ほどのPostCssPluginsを読み込みます。

gatsby-config.js
plugins: [
  {
    resolve: 'gatsby-plugin-sass',
    options: {
      postCssPlugins: [...postCssPlugins],
      cssLoaderOptions: {
        camelCase: false
      }
    }
  }
]

ついでにnormalize-scssもインストールします。

Terminal
npm install normalize-scss

normalize-scssでは、適宜、以下のようにbaseとなるscssファイルで読み込みます。

css
@import 'normalize-scss';

Header・Footer・SideBarの追加 #

ボリューム多いので、別記事に。

本文の目次の追加
#

ボリューム多いので、別記事に。

記事の更新日時をgithubでの更新日時に変更
#

ボリューム多いので、別記事に。

paginationの追加
#

ボリューム多いので、別記事に。

categoryページ・tagページの追加
#

ボリューム多いので、別記事に。

関連記事ぺージの追加
#

ボリューム多いので、別記事に。

日付のフォーマットを日本用に変更
#

ボリューム多いので、別記事に。

Shareボタンの追加
#

ボリューム多いので、別記事に。

コメント機能の追加
#

ボリューム多いので、別記事に。

Sidebarのコンテンツ拡充
#

ボリューム多いので、別記事に。

お問い合わせページ・プロフィールページの追加
#

ボリューム多いので、別記事に。

プラグイン対応
#

便利なGatsybyプラグインを導入ます。

gatsby-plugin-sitemap
#

gatsby-plugin-sitemapは、サイトマップを生成してくれるプラグインです。 プラグインのインストールは以下の通りです。

Terminal
npm install gatsby-plugin-sitemap

プラグインの読み込みは以下の通りです。

gatsby-config.js
siteMetadata: {
  siteUrl: `https://www.example.com`,
},
plugins: [
  {
    resolve: `gatsby-plugin-sitemap`,
    options: {
      exclude: [`/page/*`, `/tag/*`],
    },
  },
]

gatsby-config.jsSiteMetadata.SiteUrl が必要となりますので、 SiteMetadata.SiteUrl の情報が無い場合は gatsby-config.js に追記します。 また、excludeオプションで任意のページをサイトマップから除外できます(上記設定では、page配下とtag配下を除外しています)。

gatsby-plugin-robots-txt
#

gatsby-plugin-robots-txtは、robots.txtを生成してくれるプラグインです。

プラグインのインストールは以下の通りです。

Terminal
npm install gatsby-plugin-robots-txt

プラグインの読み込みは以下の通りです。

gatsby-config.js
siteMetadata: {
  siteUrl: `https://www.example.com`,
},
plugins: [`gatsby-plugin-robots-txt`]

gatsby-plugin-sitemapと同様に gatsby-config.jsSiteMetadata.SiteUrl が必要となるので、 SiteMetadata.SiteUrl の情報が無い場合は gatsby-config.js に追記する。

gatsby-remark-external-links #

gatsby-remark-external-linksは、外部リンクを別タブで開くようにしてくれるプラグインです。

プラグインのインストールは以下の通りです。

Terminal
npm install gatsby-remark-external-links

プラグインの読み込みは以下の通りです。

gatsby-config.js
plugins: [
  {
    resolve: 'gatsby-remark-external-links',
    options: {
      target: '_blank',
      rel: 'noopener noreferrer',
    },
  },
]

Google AnalyticsとGoogle Searchコンソールへの登録
#

Google Analyticsの登録
#

gatsby-plugin-google-gtagプラグインを使用します。

プラグインのインストールは以下の通りです。 私の環境では、Gatsbyのバージョンが2系のため、2.8.0のバージョンを指定しています。

Terminal
npm install [email protected]

プラグインの読み込みは以下の通りです。

gatsby-config.js
plugins: [
  {
    resolve: "gatsby-plugin-google-gtag",
    options: {
      trackingIds: ["UA-XXXXXXXX-X"],
      pluginConfig: {
        head: true,
      },
    },
  },
]

すでにWordPressでGoogle Analyticsを利用していましたので、5行目でその trackingIDをtrackingIds を指定して、7行目で head 内に記述されるようにしています。

Google Searchコンソールへの登録
#

すでにWordPressでサイトマップを登録しています。サイトマップのURLは同じなので、特に対応は不要でしたが、移行完了に念のためサイトマップを登録しなおしました。

デザインの修正
#

SCSSを修正して、好きなデザインに修正します。 SCSSとCSS Moduleの組み合わせなので、スタイルシートは書きやすいですが、時間が一番かかったかもです。まだPCでの表示のみの対応しています。

レスポンシブル対応
#

とりあえず、CSS Gridを使って1024px未満と以上で少し変えています。

Google AdSenseの登録
#

ボリューム多いので、別記事に。

NetlifyでのBuildとDeploy
#

ここまでで、ローカルの開発環境でとりあえず満足がいくブログが作成できましたので、公開します。 今回はDeploy先の静的ホスティングサービスとして、Netlifyを利用します。

アカウント作成
#

Netlifyのアカウントを作成します。 その際に、GithubやGitbucket等と連携してアカウントを作成可能です。

ブログのDeploy
#

以下の手順でブログのDeployを進めます。

  1. Netlifyにログイン後、 New site from Git を押下
  2. Continuous Deploymentで、 GitHub を選択
  3. Github上のブログのリポジトリを選択
  4. 以下の通り設定をして Deploy site を押下
    項目 設定値 備考
    Owner default値 変更なし
    Branch to deploy main default branchをmainにしているため
    Build command gatsby build gatsbyのbuildコマンド
    Publish deirectory public 公開ディレクトリ

デプロイが完了すると、Netlifyから割当てられたドメインでブログが公開されていますので、確認します。 すでにssl化までしてくれていますね。素晴らしい!

ブログドメインの変更
#

今回はWordPressからの移行ですので、すでにブログ用のドメイン(mkt3.dev)をxdomainでもっています。

Netlifyのcustom domainにブログ用ドメインを登録して、NetlifyのDNSサーバをxdomainに登録して完了です。 ただし、今回は移行のため、反映に数時間から72時間程度かかります。

また、このままではNetlifyからデフォルトで付与されたサブドメインからもアクセスできてしまいます。 SEO上の観点から良くないかと思いましたが、 Improved SEO with canonical link headersによると、Netlify側でcanonicalリンクを付与しているとのことですので、特に対応は不要そうです。

もし、サブドメイン自体へのアクセスを拒否したいのならば、 static/_redirects に以下のように記載すればリダイレクトの設定ができますが、デバッグ用にサブドメインへのアクセスは残しても良いと思います。

static/_redirects
# These rules will change if you change your site’s custom domains or HTTPS settings

# Redirect default Netlify subdomain to primary domain
https://xxxxxxx.netlify.app/* https://mkt3.dev/:splat 301!

Github ActionでのBuildとDeploy
#

Netlifyでの公開時点で、mainブランチにpushすると、自動でブログ更新ができるようになりました。 このままでは、Github Actionsの出番はありません。Github Actions使ってみたい…

ところで、Netlifyの無料プランは、Build時間の制限が300分/月となっており、それを超過すると自動で追加料金が発生してしまうようです。300分なので、毎日Buildしても10分の猶予があります。

ブログの記事量でのbuild時間は3分程度です。今後の更新頻度を考えても問題ないような気がします。 しかし、私はサイドバーの人気記事一覧を毎日更新(build)したいのです(SSGのためbuildしたタイミングの人気記事が反映されるため)。

となると、300分はで心許無いです。そこで、Github Actionsの登場です。 Github ActionsでBuildを実行します。 プライベートリポジトリでのGithub Actionsの無料枠は2000分/月となっており、超過した時点でワークフローが実行されなくなるので、追加料金も発生しません。

  1. ローカルで記事を更新
  2. mainブランチにpush
  3. Github ActionsでBuild & NetlifyへDeploy

Github Actionsのワークフロー作成
#

リポジトリ配下に .github/workflows/build.yml を以下のように作成します。

.github/workflows/build.yml
name: Build Gatsby and deploy to Netlify

on:
  push:
    branches: [main] # main branchにpushされた時に実行
  shedule:
    - cron: '0 20 * * *' # UTC20:00(JST05:00)時に実行

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    strategy:
      matrix:
        node-version: [14.x]
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/[email protected]
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm run build --if-present
        env:
          CLIENT_EMAIL: ${{ secrets.CLIENT_EMAIL }}
          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
      - name: Publish
        run: npx netlify-cli deploy --dir=public --prod
        env:
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}

5行目のpush時にBuildするbranchesはmainとしています。

また、7行目で、前日までのアクセスログから人気記事一覧を作成するために5:00に自動的にBuildをするようにしています。

18行目で、git cloneのfetch-depthを0に指定しています。default値だと1となり、gitのauthor dateが正しく取得できず、記事の更新日時がおかしくなってしまいます。

24、25行目の CLIENT_EMAILPRIVATE_KEY はBuild時にGoogle Analyticsへアクセスするための情報です(Google Analyticsの情報を元に人気記事一覧を作成しています)。 こちらは、人気記事一覧の作成時に取得していますので、そちらを参照ください。

31、32行目の NETLIFY_SITE_IDNETLIFY_AUTH_TOKEN はNetlifyにDeployするために必要となります。以下のリンクに取得方法が記載されています。

24、25、31、32行目の値は機密性の高い情報ですので、ワークフローにべた書きせずに、リポジトリの「Setting」→「Secrets」に登録して参照するようにしています。

終わりに
#

やっとブログの移行が完了しました。 夜にちまちまやっていたので、移行のために三ヶ月くらいかかりました。 (移行中にGatsbyが2系から3系にあがってしまったことが悲しみです。そのうち3系に移行しないと…)

今までWordPressやそのテーマにまかせていた部分、Javascript、React、GraphQLの理解がかなり深まりました(といってもプラグインも色々活用させていただきました)。 Starterに存在していたファイルにはすべて手を入れたので、全体像がかなり把握できて大満足です。

まだまだ直したい・良くしたいところがいっぱいありますので、これからもこのブログを記事だけでなくコードの観点からも育てていきたいと思います。

関連記事

EmacsでのElpyをベースとしたPython開発環境
··3 分
Elpy Python Emacs
libskkでSticky Shift
··1 分
Linux Skk
~/.ssh/configによるssh接続の管理
··1 分
Arch-Linux Ssh