BMS, Movie, Illustrations, Programming

Rails で作成したサイトを SSG して GitHub Pages で公開する

以前、Ruby on Rails の勉強のために Rails でサイトを制作しました。しかし、Heroku でサイトを運営しても良いのですが、重いと思いますし、静的で済むものは静的にしようということでやってみます。

静的なサイトを生成する

ほぼ答え → https://antulik.com/2016-05-27-rails-as-a-static-site-generator.html

静的サイトジェネレーター(SSG)としてのRails

(中略)

解決策としては、ブロク部分をRubyで書き、RailsでWebインターフェースを追加して、wgetコマンドを使用してそれを静的サイトに変換します。最後にS3に静的サイトをアップロードします。

wgetを様々なパターンで試しましたが、結局この形に落ち着きました。

  wget -r -l inf -k -nc -nH -p -E -e robots=off -P ./out http://localhost:3000

そして、ご覧の通り、Railsから生成された静的なウェブサイトが表示されています。

ということで、wget を SSG として使うんですね、なるほど……。

mkdir -p tools/ssg
vim tools/ssg/generate.sh
#!/bin/bash
######## tools/ssg/generate.sh ########
set -eux

rm -rf dist

wget -r -l inf -k -nc -nH -p -E -e robots=off -P ./dist https://hatoq.net
# ※localhost:3000 でもよいが、Productionビルドにしたかったのでリモートから取ってくることにした。
chmod +x tools/ssg/generate.sh
git add tools/ssg/generate.sh
git commit -m 'add Static Site Generator'

これで、dist ディレクトリに静的な HTML と画像などのリソースが保存されます。dist/index.html を開いて正しく保存できているか確認しましょう。トップページ以外のURLには .html が追加されてしまうため一部手動で修正が必要かもしれません。今回はトップページしか存在しないため、この問題は発生しませんでした。

デプロイの下準備~デプロイ完了まで

※この記事より簡単な方法をフォロワーさんが教えてくれました。

npm run deploy で GitHub Pages にお手軽デプロイ https://qiita.com/star__hoshi/items/490959aee12dbf528f7c #Qiita @star__hoshiより

これを使うと、デプロイ用のスクリプトは以下のように書くことができます。

#!/bin/bash
######## tools/ssg/deploy.sh ########
set -eux

./tools/ssg/generate.sh

cp CNAME dist/

# できれば Ruby の gem で統一したかったけど一旦 npm で
npx gh-pages -d dist

ということで簡単にデプロイ出来ましたので、ここから下は読まなくて大丈夫です。

以下、ぼくが考えたさいきょうのデプロイツール

下準備

GitHub Pages にデプロイするために、 gh-pages ブランチを切りましょう。親コミットが存在しなくなるように、 --orphan オプションを付けます。

git checkout --orphan gh-pages
git rm -rf .
git commit -m 'GitHub Pages Initial Commit' --allow-empty
git checkout master

デプロイ

しかし困ったことに、gh-pages ブランチには静的サイト生成に必要なファイルが無いため、gh-pages ブランチをチェックアウトした状態では静的サイト生成を実行することが出来ません。そこで、masterブランチで静的サイトを生成し、distディレクトリをgh-pagesブランチに移動してからコミットします。今回は、git の stash 機能を使うことでこれを行いました。まず、git stash で dist ディレクトリを隔離します。

git stash --include-untracked

これで dist ディレクトリがスタッシュされたはずです。ブランチを gh-pages に切り替えて、一旦すべてのファイルを削除します。git で管理していないファイルは完全に消去されてしまうため注意してください。(管理されていないファイルを残すバージョンはこの記事の最後に示します。)

git checkout gh-pages
rm -rf *

その後、dist ディレクトリを復元して、プロジェクトルートにファイルを移動します。

git stash pop
mv dist/* .
rmdir dist

あとはファイルを git に追加して push するだけです。

git add .
git commit -m 'Generate Static Site'

git push
# ※初回のみ git push -u origin gh-pages

git checkout master # 元のブランチに戻る

無事 GitHub にアップロードされました。

スクリプト化と改良

上記の手順が面倒であれば、これもスクリプトにしてしまいましょう。また、こちらのスクリプトでは、カスタムドメイン対応と、git で管理されていないファイルを残す対応が入っています。スクリプトの1回目の git stash で dist ディレクトリを隔離し、2回目の git stash では untracked なファイルを全て隔離します。push の完了後に隔離した untracked なファイルを元に戻します。

このプログラムを使用する場合は最初の一度だけ事前にリモートブランチを作成しておく必要があります。

git checkout gh-pages
git push -u origin gh-pages
git checkout -

スクリプトはこんな感じです。

vim tools/ssg/deploy.sh
#!/bin/bash
######## tools/ssg/deploy.sh ########
set -eux

./tools/ssg/generate.sh
git stash --include-untracked
git checkout gh-pages

if [ -e CNAME ]; then
  git rm -rf .
  git stash --include-untracked
  rm -rf *

  git checkout HEAD -- CNAME
else
  git rm -rf .
  git stash --include-untracked
  rm -rf *
fi

git stash pop stash@{1}

mv dist/* .
rmdir dist

git add .
git commit -m 'Generate Static Site'
git pull
git push

git checkout HEAD^
git stash pop stash@{0}
git reset --hard HEAD

git checkout master
chmod +x tools/ssg/deploy.sh
git add tools/ssg/deploy.sh
git commit -m 'add Deploy Tool'

なんか想像以上に回りくどかったので、もっとマシな方法とか、良い gem とかがあるよという方は Twitter: @yuinore までご一報ください。たすけて。