Blog を Firebase にホスティング

Netlify の環境がおおよそ分かったところで、 今度は Firebase を使ってみました。 最初は Jekyll を使ってローカルにサイトを構築した上で手作業でデプロイして動作確認を行い、 次に Travis CI を使って自動デプロイできるようにします。

今回はとりあえずパイプラインを作ってみるのが目的なので、 競合サービスとの比較検討などはしてません。

サービスの概要

Firebase

今回は静的サイトのホスティングに使うだけですが、 Firebase は認証やストレージを含めた Web、モバイルアプリケーション構築のためのバックエンドサービスを幅広く提供しています。 Firebase は2014年に Google に買収され、 現在は Google のインフラに統合されています。

競合サービス: Amazon Web Service, Microsoft Azure

Travis CI

GitHub と連携して使える継続的インテグレーション (CI) サービスで、 GitHub 上のリポジトリへの push や pull リクエストをトリガーとして、 指定したリポジトリ上のファイルを自動的に取得してビルドやテストを実行するサービスです。

GitHub の公開リポジトリに対して使う分には無料で利用できますが、 Travis CI のビルドログや設定ファイルも公開されます。 非公開リポジトリと連携する場合には有料。

競合サービス: Circle CI, Buddy, Jenkins

環境構築

Firebase に手作業でデプロイ

まずは手元のマシンでサイトを構築し、 それを手作業で Firebase にデプロイします。

手元ではサイト構築が完了して _site ディレクトリ以下のファイルを転送するだけという状態から、 Firebase にデプロイするまでの手順は次のようになります。

  1. Firebase のコンソール からプロジェクトを作成します。
  2. firebase 上のプロジェクトを管理するためにコマンドラインツール Firebase CLI をインストールします。
    参考: Firebase CLI リファレンス - CLI を設定または更新する
    % curl -sL https://firebase.tools | bash
    
  3. Firebase にログインします。
    % firebase login
    
  4. ブログのトップディレクトリに移動し、 そのディレクトリを Firebase に転送するための初期設定を行います。 ホスティングを選択して、公開ルートディレクトリとして _site を選択します。
    % firebase init
    
  5. .firebaserc と firebase.json というファイルが作成されるので、このうち後者を表示して _site 以下のディレクトリのみ転送するように設定されていることを確認します。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
        {
            "hosting": {
                "public": "_site",
                "ignore": [
                    "firebase.json",
                    "**/.*",
                    "**/node_modules/**"
                ]
            }
        }
    
  6. 転送後のサイトをプレビューして、意図通りのファイルが転送されているか確認します。
    % firebase serve
    
  7. ファイルを Firebase に転送します。
    % firebase deploy
    

これで Firebase の URL https://プロジェクト名.web.app/ でサイトが表示されたら、 Firebase 側の設定は完了です。

Travis CI

継続的ビルド設定

次に Travis CI を介して、 ブログの記事や設定ファイルなどを GitHub リポジトリに push するとサイトを自動的に構築・デプロイするようにします。

個人のブログ程度だと、 ここまで環境を作っても得られるメリットは限られますが、 複数人で同一のブログに別々の記事を投稿したり記事を公開する前にレビューする場合には、 競合を解決したり事前レビューのためのフローを簡単に作成できます。

公式の Travis CI Tutorial を読んで、 その手順に従います。

  1. Travis CI のページから Sign up を選択し、GitHub アカウントでサインアップします。
  2. 表示される手順に従って、GitHub 上の情報に Travis CI からアクセスすることを許可します。
  3. .travis.yml ファイルをブログのリポジトリのトップディレクトリに追加します。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
        dist: focal
        language: ruby
        rvm: 2.7.1
    
        # Assume bundler is being used, therefore
        # the `install` step will run `bundle install` by default.
        script: bundle exec jekyll build
    
        # branch whitelist, only for GitHub Pages
        branches:
            only:
            - master
    
        env:
            global:
            - JEKYLL_ENV=production
    
        cache: bundler # caching bundler gem packages will speed up build
    
  4. Travis CI の ダッシュボード からブログのリポジトリを選択し、 ビルドが正常に終了することを確認します。

設定内容解説

今回は Ruby で書かれたツール Jekyll で静的サイトを構築します。

手元の環境が Ruby 2.7.1 だったので、 ビルド環境との差異を減らすため同一バージョンの Ruby を使うことにし、 Ruby 2.7.1 がプリインストールされている Linux 環境の focal を選択しました。

参考: Building a Ruby Project

1
2
3
dist: focal
language: ruby
rvm: 2.7.1

Gemfile が Git リポジトリに含まれている場合、 Travis CI は Bundler を使って必要なパッケージをインストールするため、 自分でインストール手順を指示する必要はありません。 サイトのビルド方法のみ指定します。

1
2
3
4
5
script: bundle exec jekyll build

env:
    global:
    - JEKYLL_ENV=production

あとは設定ファイル中のコメントの通りです。

デプロイ設定

ビルドが問題なく行えるようになったら、 次に構築したサイトを Firebase に転送するための設定を .travis.yml に追加します。

参考: Firebase Deployment

  1. Travis CI から Firebase にファイルを転送する際に、 正当なユーザーであることを示すトークンを作成します。
    % firebase login:ci
    
  2. このトークンをそのまま設定ファイルに記述すると GitHub リポジトリを見たユーザーがトークンを再利用できてしまうため、 Travis CI からのみ使えるように暗号化します。
    % gem install travis
    % travis encrypt "得られたトークン"
    
  3. .travis.yml に deploy セクションを追加します。
    1
    2
    3
    4
    5
    
    deploy:
    provider: firebase
    token:
        secure: "oSfN..." # travis encrypt で得られた暗号化トークン
    skip_cleanup: true
    
    デフォルトでは Travis CI は、 デプロイ開始前に作成されたファイルをすべて削除します。 今回はそれだと困るので skip_cleanup を指定します。
    参考: Uploading Files and skip_cleanup
  4. (オプション) ビルド成功・失敗時に通知する条件と通知先を設定します。 私は Slack に専用のチャンネルを作成し、そこに通知するようにしました。
    参考: Deployment - Configuring Build Notifications

雑感

Netlify は CDN を持っていますが、 Firebase と比べるとスイスからアクセスするのが遅いです。 人間の目でも、 画像が読み込まれて上から徐々に表示されるのが見えます (ベンチマークを取った結果もありますが、 計測条件が適当すぎるので略)。

一方で、 設定の容易さは Netlify が圧倒的です。 もともと Travis CI は静的サイトのホスティングのためのサービスではなく、 継続的ビルド・テスト・デプロイのための汎用プラットフォームなので、 柔軟な設定が可能ですが、 その裏返しとして最低限の設定項目が多いです (まだドキュメントを読みきれてない)。

あとは必ずしも Netlify の問題ではないですが、 静的サイト構築に Jekyll を使うと、 ページ数が増えるとサイトの構築に時間がかかるようになります。 Netlify の無料プランは月300分までなので、 複数人で作業するサイトだと超える可能性があります。

規模が大きくなることが想定される場合には、 Python, Ruby や JavaScript といったインタプリタ言語ではなく、 たとえば Go 言語で書かれた Hugo などを使うほうが良いかもしれません。