水無瀬のプログラミング日記

プログラムの勉強した時のメモ

GatsbyJSでGithubPagesに静的サイトを作る

はじめに

Angularで静的サイトを作ってた今日このごろ。
Gatsbyも触ってみたかったので今回はGatsbyを使って静的サイトをGithubPagesに公開してみる。

ただ公開するのはチュートリアルですぐできそうなので、
Markdownページを公開できるようにするのと自動デプロイも試してみる。

TL;DR.

今回作ったもの

導入

公式のQuickStartを見ながら進めていく。

$ npx gatsby-cli new gatsby-blog
> yarnとnpmどっち使うか聞かれるので好みで設定

yarn (npm run) developで↓のようなページが表示されれば導入は完了。 f:id:minase_mira:20200322194339p:plain

TypeScript化する

デフォではjsなのでts対応する。
公式からプラグインが出ているのでそれを使うことにする。

必要なものをインストール

# プラグインとtsをインストール
$ yarn add gatsby-plugin-typescript typescript

# 型定義もインストールしておく
$ yarn add --dev @types/react @types/react-dom @types/node

tsconfigの作成

サクッと設定。
ミニマムではないと思うけど、問題ないと思うのでこれでやる。

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": [
    "./src/**/*"
  ]
}

ts化

ファイル全般を.tsxに変更すれば完了

Markdown対応

静的サイトはこれまでの手順で作成可能だが一々HTMLを書くのはしんどいので、
Markdownで書いたものを表示できるようにする。

Markdownに対応させるのはlibraryがあるのでそれを使う。
導入方法は公式に乗っているので参考にしながらすすめる。

libraryのインストール

$ yarn add  gatsby-source-filesystem gatsby-transformer-remark

Markdownファイルを作成

適当にMarkdownの記法を色々試してみる。
—--で囲まれた部分はコンテンツではなく、メタデータとして扱われる。

---
path: "/blog/20200318"
date: "2020-03-18"
title: "My first blog post"
tag: ["JavaScript", "TypeScript"]
---

# はじめに
マークダウンを読めるようになったので試す。

# TL;DR.
このページ

# ヘディング
## レベル2
はこんなもん

### レベル3
はこれ

#### レベル4
だよ

# リスト
* hoge
* huga
* piyo

# 順番付き
1. first
2. second
3. third

# コード系
インライン`code`はこんな感じ  
ブロックは↓みたいな  

const hoge = () => 'hoge'; console.log(hoge());

# テーブル
|title|value|
|:---:|:----|
|中央寄せの文字を入れている。|左寄せの値を入れてみている。|
|2段目タイトル|2段目バリュー|

# 文字装飾
**ボールド**  
_イタリック_  

# 引用
> 引用してみた
>> もっと

gatsby-configに追加

gatsby-source-filesystem

これでMarkdownをソースとして読み込むことができるようになる。

{
  resolve: `gatsby-source-filesystem`,
  options: {
    name: `markdown-pages`,
    path: `${__dirname}/src/markdown-pages`
  }
}

gatsby-transformer-remark

これを使用することでMarkdownのコンテンツ部分をHTMLに。
メタデータ部分をformatterに変換してくれる。

{
  resolve: `gatsby-source-filesystem`,
  options: {
    name: `markdown-pages`,
    path: `${__dirname}/src/markdown-pages`
  }
},
// 追記
`gatsby-transformer-remark`

Markdownファイルのテンプレート作成

とりあえず公式のテンプレートそのまま使う。
(tsxに変更しただけ)

import React from "react"
import { graphql } from "gatsby"

export default function Template({ data }) {
  const { markdownRemark } = data // data.markdownRemark holds your post data
  const { frontmatter, html } = markdownRemark
  return (
    <div className="blog-post-container">
      <div className="blog-post">
        <h1>{frontmatter.title}</h1>
        <h2>{frontmatter.date}</h2>
        <div
          className="blog-post-content"
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </div>
    </div>
  )
}

export const pageQuery = graphql`
    query($path: String!) {
        markdownRemark(frontmatter: { path: { eq: $path } }) {
            html
            frontmatter {
                date(formatString: "MMMM DD, YYYY")
                path
                title
            }
        }
    }
`

gatsby-nodeを使ってページを作成する

Markdownで書いたページから静的ページを作成するため、gatsby-nodeを用意する。
今回はTypeScriptを使ったので、ts-nodeを使う。
基本は公式のままで、ts-node部分を足しただけ。

const path = require(`path`)

// ここを追加
require('ts-node').register({
  compilerOptions: {
    module: 'commonjs',
    target: 'esnext',
  },
});

exports.createPages = async ({ actions, graphql, reporter }) => {
  const { createPage } = actions

  const blogPostTemplate = path.resolve(`src/templates/blogTemplate.tsx`)

  const result = await graphql(`
    {
      allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___date] }
        limit: 1000
      ) {
        edges {
          node {
            frontmatter {
              path
            }
          }
        }
      }
    }
  `)

  // Handle errors
  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.frontmatter.path,
      component: blogPostTemplate,
      context: {}, // additional data can be passed via context
    })
  })
}

GithubActionsを使って自動デプロイをする

GithubPagesに公開するのは有効にした上で、Markdownで書いたものをbuildしてpushすれば完了する。
ただ、公開の都度buildするのはめんどくさいのでActionsを使って自動化してみる。
※GithubPagesの公開方法は公式参照

workflow作成

GithubPagesにデプロイするActionはすでにあるので、これを使ってやってみる。
ただし、このActionはデプロイ先のブランチをすべて上書きしてしまうっぽいので、
pagesを公開するブランチ以外をdefaultブランチにしたほうが良いかもしれない。
(自分はmasterブランチを公開用にして、作業用をdevelopブランチとした)

name: deploy-pages

on:
  push:
    # 作業用ブランチにpushされた時に動かす
    branches:
      - develop

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1

      - name: setup
        uses: actions/setup-node@v1
        with:
          node-version: 12

      - name: install and setup config
        run: npm install

      # Gatsbyのビルド
      - name: build
        run: npm run build

      # pagesへdeployする
      - name: deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          personal_token: ${{ secrets.PERSONAL_TOKEN }}
          # developブランチのpublicディレクトリの内容を
          publish_dir: ./public
          # masterブランチにpushする
          publish_branch: master

まとめ

GatsbyJSを使って静的サイトを作った。
Gatsbyをts化してうまく動かすところに苦戦した。
今回の様な使い方をするのであれば、
型があるメリットも薄い気がしたのであまり必要ないかなと思った。

ブログ部分のレイアウトも自由にできるのでもっとマシにして行ければなと。
Gatsbyが意外と色々できる気がしたのでこれからもちょくちょく触っていきたいところ。

参考リンク