注意
現在、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のコマンドを実行するために、以下のコマンドを実行します。
npm install -g gatsby-cli
ターミナルを再起動し、以下のコマンドが正常に実行できれば、インストール成功です。
gatsby --help
初回構築 #
以下のコマンドでgatsby-starter-blogをもとにブログを初期構築します。
gatsby new mkt3.dev https://github.com/gatsbyjs/gatsby-starter-blog
mkt3.dev
はディレクトリ名なので、任意の名前にしてください。
生成されたディレクトリに移動して、develop(開発モード)でブログを起動します。
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のプラグインをインストールする場合は、コマンドを作業ディレクトリ(ローカルリポジトリ)内で実行します。
npm install --save-dev autoprefixer postcss-pxtorem
リポジトリ直下に以下の 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
を読み込みます。
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をインストールします。
npm install sass gatsby-plugin-sass
次に gatsby-config.js
に以下を追記してプラグインを有効化します。
5行目で先ほどのPostCssPluginsを読み込みます。
plugins: [
{
resolve: 'gatsby-plugin-sass',
options: {
postCssPlugins: [...postCssPlugins],
cssLoaderOptions: {
camelCase: false
}
}
}
]
ついでにnormalize-scssもインストールします。
npm install normalize-scss
normalize-scssでは、適宜、以下のようにbaseとなるscssファイルで読み込みます。
@import 'normalize-scss';
Header・Footer・SideBarの追加 #
ボリューム多いので、別記事に。
本文の目次の追加 #
ボリューム多いので、別記事に。
記事の更新日時をgithubでの更新日時に変更 #
ボリューム多いので、別記事に。
paginationの追加 #
ボリューム多いので、別記事に。
categoryページ・tagページの追加 #
ボリューム多いので、別記事に。
関連記事ぺージの追加 #
ボリューム多いので、別記事に。
日付のフォーマットを日本用に変更 #
ボリューム多いので、別記事に。
Shareボタンの追加 #
ボリューム多いので、別記事に。
コメント機能の追加 #
ボリューム多いので、別記事に。
Sidebarのコンテンツ拡充 #
ボリューム多いので、別記事に。
お問い合わせページ・プロフィールページの追加 #
ボリューム多いので、別記事に。
プラグイン対応 #
便利なGatsybyプラグインを導入ます。
gatsby-plugin-sitemap #
gatsby-plugin-sitemapは、サイトマップを生成してくれるプラグインです。 プラグインのインストールは以下の通りです。
npm install gatsby-plugin-sitemap
プラグインの読み込みは以下の通りです。
siteMetadata: {
siteUrl: `https://www.example.com`,
},
plugins: [
{
resolve: `gatsby-plugin-sitemap`,
options: {
exclude: [`/page/*`, `/tag/*`],
},
},
]
gatsby-config.js
の SiteMetadata.SiteUrl
が必要となりますので、 SiteMetadata.SiteUrl
の情報が無い場合は gatsby-config.js
に追記します。
また、excludeオプションで任意のページをサイトマップから除外できます(上記設定では、page配下とtag配下を除外しています)。
gatsby-plugin-robots-txt #
gatsby-plugin-robots-txtは、robots.txtを生成してくれるプラグインです。
プラグインのインストールは以下の通りです。
npm install gatsby-plugin-robots-txt
プラグインの読み込みは以下の通りです。
siteMetadata: {
siteUrl: `https://www.example.com`,
},
plugins: [`gatsby-plugin-robots-txt`]
gatsby-plugin-sitemapと同様に gatsby-config.js
の SiteMetadata.SiteUrl
が必要となるので、 SiteMetadata.SiteUrl
の情報が無い場合は gatsby-config.js
に追記する。
gatsby-remark-external-links #
gatsby-remark-external-linksは、外部リンクを別タブで開くようにしてくれるプラグインです。
プラグインのインストールは以下の通りです。
npm install gatsby-remark-external-links
プラグインの読み込みは以下の通りです。
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のバージョンを指定しています。
npm install [email protected]
プラグインの読み込みは以下の通りです。
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を進めます。
- Netlifyにログイン後、
New site from Git
を押下 - Continuous Deploymentで、
GitHub
を選択 - Github上のブログのリポジトリを選択
- 以下の通り設定をして
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
に以下のように記載すればリダイレクトの設定ができますが、デバッグ用にサブドメインへのアクセスは残しても良いと思います。
# 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分/月となっており、超過した時点でワークフローが実行されなくなるので、追加料金も発生しません。
- ローカルで記事を更新
- mainブランチにpush
- Github ActionsでBuild & NetlifyへDeploy
Github Actionsのワークフロー作成 #
リポジトリ配下に .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_EMAIL
と PRIVATE_KEY
はBuild時にGoogle Analyticsへアクセスするための情報です(Google Analyticsの情報を元に人気記事一覧を作成しています)。
こちらは、人気記事一覧の作成時に取得していますので、そちらを参照ください。
31、32行目の NETLIFY_SITE_ID
と NETLIFY_AUTH_TOKEN
はNetlifyにDeployするために必要となります。以下のリンクに取得方法が記載されています。
NETLIFY_SITE_ID
: Link with an environment variableNETLIFY_AUTH_TOKEN
: Obtain a token in the Netlify UI
24、25、31、32行目の値は機密性の高い情報ですので、ワークフローにべた書きせずに、リポジトリの「Setting」→「Secrets」に登録して参照するようにしています。
終わりに #
やっとブログの移行が完了しました。 夜にちまちまやっていたので、移行のために三ヶ月くらいかかりました。 (移行中にGatsbyが2系から3系にあがってしまったことが悲しみです。そのうち3系に移行しないと…)
今までWordPressやそのテーマにまかせていた部分、Javascript、React、GraphQLの理解がかなり深まりました(といってもプラグインも色々活用させていただきました)。 Starterに存在していたファイルにはすべて手を入れたので、全体像がかなり把握できて大満足です。
まだまだ直したい・良くしたいところがいっぱいありますので、これからもこのブログを記事だけでなくコードの観点からも育てていきたいと思います。