All Articles

ブログを Gatsby + GitLab Pages に移行

Gatsby * GitLab

ブログを Gatsby のスターターで作成し、GitLab Pages にデプロイした際のメモ。

目次

開発環境の準備

Node.jsScoop で Cmder と Node.js をインストールでインストール済です。

Git for WindowsScoop で Git と SourceTree をインストールでインストール済です。

Yarnnpm-scripts で静的サイトの制作環境を構築 (1) でインストール済です。

gatsby-cli をインストール

グローバルに gatsby-cli をインストールします。

yarn global add gatsby-cli

Telemetry をオプトアウトします。

gatsby telemetry --disable

Node.js を推奨版に切り替え

Gatsby.js Tutorials を始めたところ、gatsby コマンドがエラーで先へ進めなかったので解決策を検索してみると、Node.js が最新版ではなく推奨版なら大丈夫らしいので、Scoop で切り替えます。

scoop reset nodejs-lts

これで gatsby コマンドがエラーになることもなく、先へ進めるようになりました。

スターターのインストール

スターターを選定

Starter Library からオフィシャルブログとして提供されている gatsby-starter-blog を試したものの、せっかくお手軽に始められるスターターを使うなら、もう少し機能が多いものが良いかなと考え、gatsby-starter-lumen に決めました。

gatsby-starter-lumen をインストール

プロジェクトフォルダに gatsby-starter-lumen をインストールします。

gatsby new プロジェクト名 https://github.com/alxshelepenok/gatsby-starter-lumen

Prettier のインストール

Prettier をインストール

npm-scripts で静的サイトの制作環境を構築 (3) (改)Prettier を使用しているので、ESLintstylelint がインストール済の gatsby-starter-lumen でも使えるようにインストールします。

yarn add prettier --dev

eslint-plugin-prettier と eslint-config-prettier をインストール

ESLint と Prettier が連携するよう eslint-plugin-prettier を、ESLint と Prettier が競合しないよう eslint-config-prettier をインストールします。

yarn add eslint-plugin-prettier eslint-config-prettier --dev

.eslintrc.json を編集

プロジェクトルートの .eslintrc.json ファイルを編集します。

{
  "extends": [
    "airbnb-base",
    "plugin:prettier/recommended"  ],
  "rules": {
    "prettier/prettier": [      "error",      {        "singleQuote": true      }    ]  }
}

extendsplugin:prettier/recommended を、rulesprettier/prettier を追加しました。

stylelint-order と stylelint-config-rational-order をインストール

CSS のプロパティをソートするルールは stylelint-orderstylelint-config-rational-order をインストールします。

yarn add stylelint-order stylelint-config-rational-order --dev

stylelint-prettier と stylelint-config-prettier をインストール

stylelint と Prettier が連携するよう stylelint-prettier を、stylelint と Prettier が競合しないよう stylelint-config-prettier をインストールします。

yarn add stylelint-prettier stylelint-config-prettier --dev

.stylelintrc.json を編集

プロジェクトルートの .stylelintrc.json ファイルを編集します。

{
  "extends": [
    "stylelint-config-recommended-scss",
    "stylelint-config-rational-order",    "stylelint-prettier/recommended"  ],
  "rules": {
    "prettier/prettier": [true, {      "singleQuote": true    }]  }
}

extendsstylelint-config-rational-orderstylelint-prettier/recommended を、rulesprettier/prettier を追加しました。

Netlify 用プラグインの無効化

gatsby-plugin-netlify と gatsby-plugin-netlify-cms を無効化

gatsby-starter-lumen には Netlify 用に gatsby-plugin-netlifygatsby-plugin-netlify-cms が含まれていますが、GitLab Pages には不要です。

プロジェクトルートの gatsby-config.js ファイルを編集します。

module.exports = {
  plugins: [
    /*
    'gatsby-plugin-netlify',
    {
      resolve: 'gatsby-plugin-netlify-cms',
      options: {
        modulePath: `${__dirname}/src/cms/index.js`,
      }
    },
    */
  ],
};

gatsby-plugin-netlifygatsby-plugin-netlify-cms をコメントアウトしました。

メタ情報の変更

config.js を編集

siteMetadata は gatsby-config.js に直接設定せずに config.js を参照しているので、プロジェクトルートの config.js ファイルを編集します。

module.exports = {
  url: 'サイトのURL',
  title: 'サイトのタイトル',
  subtitle: 'サイトのサブタイトル',
  copyright: 'コピーライト表記',
  disqusShortname: 'ディスカスのショートネーム',
  googleAnalyticsId: 'グーグルアナリティクスのトラッキング ID',
  menu: [
    {
      label: 'Articles',
      path: '/',
    },
    /*
    {
      label: 'About me',
      path: '/pages/about'
    },
    {
      label: 'Contact me',
      path: '/pages/contacts'
    }
    */
  ],
  author: {
    name: '著者名',
    bio: '著者紹介文',
    contacts: {
      rss: '/rss.xml',
    },
  },
};

url, title, subtitle, copyright, disqusShortname, googleAnalyticsId, menu, author を変更しました。

menuAbout me, Contact me はとりあえず後回しにしようとコメントアウトで非表示にしました。

lang 属性の変更

HTML の言語が英語に設定されているので日本語に変更します。

Layout.js を編集

src\components\Layout\Layout.js ファイルを編集します。

const Layout = ({ children, title, description, socialImage }: Props) => {
  return (
    <div className={styles.layout}>
      <Helmet>
        <html lang="ja" />      </Helmet>
    </div>
  );
};

langen から ja に変更しました。

ファビコンの変更

ファビコンを配置

static フォルダ内にファビコン(favicon.png)を配置します。

ファビコンを設定

プロジェクトルートの gatsby-config.js ファイルを編集します。

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-manifest',
      options: {
        icon: 'static/favicon.png',      },
    },
  ],
};

gatsby-plugin-manifesticon にファビコン(favicon.png)を設定しました。

著者画像の変更

著者画像を配置

static フォルダ内に著者画像(avatar.png)を配置します。

著者画像を設定

プロジェクトルートの config.js ファイルを編集します。

module.exports = {
  author: {
    photo: '/avatar.png',  },
};

author.photo に著者画像(avatar.png)を設定しました。

スタイルシートの適用

サイト全体に適用するスタイルシートを作成します。

_global.scss を作成

src\assets\scss\_global.scss ファイルを作成します。

/* Prism */
pre[class*='language-'] .gatsby-highlight-code-line {
  display: block;
  width: max-content;
  max-width: none;
  margin-right: -1em;
  margin-left: -1em;
  padding-right: 1em;
  padding-left: 0.75em;
  background-color: #515151;
  border-left: 0.25em solid #f2777a;
}

:not(pre) > code[class*='language-'] {
  white-space: pre-wrap;
}

/* Table of Contents */
.toc {
  border: 1px solid #e6e6e6;
  border-radius: 1.25rem;

  ul li {
    a {
      font-size: 1rem;
    }

    p {
      margin-bottom: 0.625rem;
    }
  }
}

/* Zebra Striped Table */
table {
  display: block;
  width: 100%;
  margin-bottom: 2rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  font-size: 1rem;
  white-space: nowrap;
  border-collapse: collapse;

  th,
  td {
    padding: 0.3rem;
    vertical-align: top;
    border-top: 1px solid #e6e6e6;
  }

  thead th {
    vertical-align: bottom;
    border-bottom: 2px solid #e6e6e6;
  }

  tbody tr:nth-of-type(odd) {
    background-color: rgba(0, 0, 0, 0.05);
  }

  tbody tr:hover {
    color: #212529;
    background-color: rgba(0, 0, 0, 0.075);
  }
}

コードブロックの指定行ハイライト、目次、表組みのスタイルを追加しました。

prism-tomorrow.css と _global.scss を適用

src\assets\scss\init.scss ファイルを編集します。

@import '../../../node_modules/prismjs/themes/prism-tomorrow.css';
@import 'global';

prism-tomorrow.css と _global.scss を追加しました。

プロジェクトルートの gatsby-browser.js ファイルを編集します。

require('./src/assets/scss/init.scss');
// require('./static/css/prismjs/theme.min.css');

init.scss に Tomorrow Night テーマを組み込んだことで不要になった theme.min.css をコメントアウトしました。

サイドバーの編集

Sidebar.js を編集

src\components\Sidebar\Sidebar.js ファイルを編集します。

const Sidebar = ({ isIndex }: Props) => {
  const { author, title, subtitle, copyright, menu } = useSiteMetadata();
  return (
    <div className={styles['sidebar']}>
      <div className={styles['sidebar__inner']}>
        <Author
          author={author}
          isIndex={isIndex}
          title={title}          subtitle={subtitle}        />
      </div>
    </div>
  );
};

Author.js に props で title, subtitle も渡せるように追加しました。

サイドバー用 Author.js を編集

src\components\Sidebar\Author\Author.js ファイルを編集します。

type Props = {
  author: {
    name: string,
    bio: string,
    photo: string,
  },
  isIndex: ?boolean,
  title: string,  subtitle: String,};

const Author = ({ author, isIndex, title, subtitle }: Props) => (  <div className={styles['author']}>
    {isIndex === true ? (      <h1 className={styles['author__title']}>        <Link to="/">          <img            src={withPrefix('/logo.png')}            className={styles['author__logo']}            width="180"            height="80"            alt={title}          />        </Link>      </h1>    ) : (      <h2 className={styles['author__title']}>        <Link to="/">          <img            src={withPrefix('/logo.png')}            className={styles['author__logo']}            width="180"            height="80"            alt={title}          />        </Link>      </h2>    )}    <div className={styles['author__subtitle']}>      <p className={styles['author__subtitle-center']}>{subtitle}</p>    </div>    <Link to="/">
      <img
        src={withPrefix(author.photo)}
        className={styles['author__photo']}
        width="75"
        height="75"
        alt={author.name}
      />
    </Link>

    {isIndex === true ? (
      <h2 className={styles['author__title']}>        <Link className={styles['author__title-link']} to="/">          {author.name}        </Link>      </h2>    ) : (
      <h3 className={styles['author__title']}>        <Link className={styles['author__title-link']} to="/">          {author.name}        </Link>      </h3>    )}

    <p className={styles['author__subtitle']}>{author.bio}</p>
  </div>
);

props で title, subtitle も受け取り、サイドバーにサイトのタイトル、サブタイトルを追加しました。

サイドバー用 Author.module.scss を編集

src\components\Sidebar\Author\Author.module.scss ファイルを編集します。

.author {
  &__subtitle {
    font-size: $typographic-small-font-size;

    &-center {
      text-align: center;
    }
  }

  &__logo {
    margin-right: auto;
    margin-left: auto;
  }
}

.author__subtitlefont-size を変更し、.author__subtitle-center, .author__logo を追加しました。

著者情報の変更

記事の下に表示する著者情報を変更します。

記事用 Author.js を編集

src\components\Post\Author\Author.js ファイルを編集します。

// import { getContactHref } from '../../../utils';
import { withPrefix, Link } from 'gatsby';
const Author = () => {
  const { author, title, subtitle, copyright } = useSiteMetadata();
  return (
    <div className={styles['author']}>
      <Link to="/">        <img          src={withPrefix(author.photo)}          className={styles['author__photo']}          width="75"          height="75"          alt={author.name}        />      </Link>      <h3 className={styles['author__title']}>        <Link className={styles['author__title-link']} to="/">          {author.name}        </Link>      </h3>      <p className={styles['author__subtitle']}>{author.bio}</p>      <h2 className={styles['author__title']}>        <Link to="/">          <img            src={withPrefix('/logo.png')}            className={styles['author__logo']}            width="180"            height="80"            alt={title}          />        </Link>      </h2>      <div className={styles['author__subtitle']}>        <p className={styles['author__subtitle-center']}>{subtitle}</p>      </div>      <div className={styles['author__copyright']}>{copyright}</div>    </div>
  );
};

使わなくなった getContactHref をコメントアウト、新たに使用する withPrefixLink を import し、著者情報に著者画像やサイトのタイトル、サブタイトル、コピーライトを追加しました。

記事用 Author.module.scss を編集

src\components\Post\Author\Author.module.scss ファイルを編集します。

.author {
  &__photo {
    display: inline-block;
    margin-bottom: 0;
    background-clip: padding-box;
    border-radius: 50%;
  }

  &__title {
    font-weight: 600;
    font-size: $typographic-base-font-size * 1.125;
    @include line-height(1.125);
    @include margin(0.5, 0, 0.5, 0);

    &-link {
      color: $color-base;

      &:hover,
      &:focus {
        color: $color-base;
      }
    }
  }

  &__subtitle {
    color: $color-gray;
    font-size: $typographic-small-font-size;
    @include line-height(1);
    @include margin-bottom(1);

    &-center {
      text-align: center;
    }
  }

  &__logo {
    margin-right: auto;
    margin-left: auto;
  }

  &__copyright {
    color: lighten($color-gray, 18%);
    font-size: $typographic-small-font-size;
  }
}

.author__photo, .author__title, .author__subtitle, .author__logo, .author__copyright を追加しました。

目次の自動生成

gatsby-remark-table-of-contents をインストール

記事の目次を自動生成する gatsby-remark-table-of-contents をインストールします。

yarn add gatsby-remark-table-of-contents

gatsby-remark-table-of-contents を有効化

プロジェクトルートの gatsby-config.js ファイルを編集します。

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: [
          'gatsby-remark-table-of-contents',          'gatsby-remark-autolink-headers',
        ],
      },
    },
  ],
};

gatsby-remark-autolink-headers の前に gatsby-remark-table-of-contents を追加しました。

自動生成用コードブロック

記事内の目次を付けたい位置に toc を指定したコードブロックを記入します。

## 目次

```toc# This code block gets replaced with the TOCexclude: 目次```

exclude で除外するタイトルの文字を指定しました。

リダイレクトの設定

旧ブログでは /年/月/日/slug/ だった URL が、新ブログでは /posts/slug になったのでリダイレクトを設定します。

gatsby-redirect-from と gatsby-plugin-meta-redirect をインストール

GitLab Pages では .htaccess は使用出来ないので、gatsby-redirect-fromgatsby-plugin-meta-redirect をインストールします。

yarn add gatsby-redirect-from gatsby-plugin-meta-redirect

gatsby-redirect-from と gatsby-plugin-meta-redirect を有効化

プロジェクトルートの gatsby-config.js ファイルを編集します。

module.exports = {
  plugins: [
    'gatsby-redirect-from',    'gatsby-plugin-meta-redirect',  ],
};

plugins の最後に gatsby-redirect-fromgatsby-plugin-meta-redirect を追加しました。

Frontmatter を編集

記事の Frontmatter に redirect_from を追加します。

```
title: "npm-scripts で静的サイトの制作環境を構築 (3) (改)"
slug: "npm-scripts-static-site-3-mod"
redirect_from:  - "/2019/12/20/npm-scripts-3-1/"```

これで /2019/12/20/npm-scripts-3-1/ が /posts/npm-scripts-static-site-3-mod にリダイレクトされるようになりました。

リモートリポジトリの設定

プロジェクトを作成

GitLab にログインし、新規プロジェクト > Create blank project で可視レベルがプライベートなプロジェクトを作成します。

権限を変更

設定 > 一般から可視性、プロジェクトの機能、権限展開ページプロジェクトメンバーのみから全員に変更し、変更を保存をクリックします。

.gitlab-ci.yml を作成

プロジェクトの概要 > 詳細から CI/CD 設定をクリックして .gitlab-ci.yml ファイルの作成画面を出し、テンプレートを適用から PagesGatsby を選択します。

# This file is a template, and might need editing before it works on your project.
image: node:latest

# This folder is cached between builds
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
  paths:
    - node_modules/

pages:
  script:
    - yarn install
    - ./node_modules/.bin/gatsby build --prefix-paths
  artifacts:
    paths:
      - public
  only:
    - master

ローカルの開発環境で gatsby コマンドがエラーにならないよう Node.js を最新版から推奨版に変更したので、.gitlab-ci.yml ファイルも推奨版を指定します。

image: node:12.18.3

node -v でローカルのバージョンを調べ(今回は 12.18.3) image を変更、Commit changes をクリックし、.gitlab-ci.yml ファイルを作成します。

独自ドメインの設定

ドメインを追加

設定 > Pages から新ドメインで独自ドメインを追加します。

ドメインを検証

DNS に CNAME レコードと TXT レコードを登録、未検証の横のアイコンをクリックし、検証済みと表示されることを確認します。