Hugo で生成しているブログを Firebase Hosting に移行して、ついでに permalink を修正してリダイレクト設定した

Dec 26, 2021 ( Feb 11, 2022 更新 )

このブログは、ずっと Hugo という静的サイト生成ツールでページを作成して GitHub Pages でホスティングしていたのですが、なんとなく Firebase 系の製品を試してみたくなり、冬休みということで勢いで Firebase Hosting に移行してみました。

ブログ等のホスティング先の移行を考えている方の参考になるかもしれないので記録しておきます。

Firebase Hosting とは

Firebase Hosting は、 Firebase 製品群のひとつとして提供されているホスティングサービスです。 静的コンテンツのホスティングと、基本的なルーティング(リダイレクトを含む)や、カスタムドメイン、SSL 証明書、デプロイ時のチャンネルを切り替えることによってプレビューが簡単にできるなどの機能をサポートしています。

料金は無料枠として Spark プランがあり、ストレージが 10GB、データ転送が 1 日 360MB までとなっています。それ以降は従量課金制の Braze プランが用意されています。

個人のブログ用途であれば無料枠で収まる場合がほとんどのような気がします。

移行前の運用方法

サイト全体は Hugo で管理し、記事は markdown で書いていました。

ファイル構成はこんな感じです:

.
├── archetypes
├── config.toml
├── content # markdown の記事本体が格納されている
├── public # Hugo で生成した公開する静的ファイル一式
├── static # 記事で表示する画像ファイルなど
└── themas # サイトのテーマファイル

HTML や CSS などのカスタムしたテーマファイル一式と、コンテンツの markdown ファイルを元にサイト全体を手元でビルドし、できた静的ファイル一式を GitHub 上のリポジトリにプッシュして公開していました。

以前は特に CI 環境は用意しておらず、サイトのファイルを一緒にデプロイ用のシェルスクリプトを管理していて、手元でそれを実行して記事の更新をしていました。

プロジェクトのセットアップとデプロイ CI の設定

特に難しいことは何もしてなくて、 Firebase Hosting の Getting Started に従って新規プロジェクトを作成し、 Firebase CLI を使って firebase init hosting を実行しました。 インタラクティブに用途をポチポチ選択していくと以下のように必要なファイルを作ってくれます。

  • .firebaserc
    • CLI 用の設定ファイル
  • firebase.json
    • Firebase Hosting の設定ファイル。ルーティング設定などを書いて反映できる
  • .github/
    • デプロイ用の GitHub Actions のサンプル

GitHub Actions で PR 毎にプレビュー環境を作成する

Firebase Hostring には channels という概念があります。 デプロイする単位で管理された release を、特定の URL でアクセスできるよう切り替えて利用することができます。

例えば、

  • live channel
    • Git 管理されたリポジトリの main ブランチの内容を配信する
  • PR-1 channel
    • Pull Request 1 の内容を配信する
  • PR-2 channel
    • Pull Request 2 の内容を配信する

ということができ、PR 作成時に CI でプレビュー環境を用意し、確認して問題なければ main ブランチにマージして production 環境に反映させるという運用が簡単にできます。

Firebase CLI 経由で Firebase Hosting のファイル一式を生成すると、この用途に使える GitHub Actions のファイルも一緒に作成してくれます。 Hugo のファイル生成をする step を追加する場合は以下のように step を追加します。

PR 単位の Action

# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
  build_and_preview:
    if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.91.2'
      - name: Build
        run: hugo --minify -t simple
      - name: Deploy
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_FOOBAR }}'
          projectId: foobar

main ブランチへのマージが発生した時の Action

# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - main
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.91.2'
      - name: Build
        run: hugo --minify -t simple
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_FOOBAR }}'
          channelId: live
          projectId: foobar

カスタムドメインの設定

カスタムドメインの設定は、 Firebase のコンソールからすることができます。

domain

設定画面に従って操作していけばいいのですが、DNS レコードの設定後、SSL 証明書の生成と反映を Firebase Hosting 側でしてくれるのですが反映までに数時間ほどかかります。なのでしばらく http 限定での配信のみになります。

ブログ記事をプレビューしていて気づいたのですが、あるときから permalink の生成方法を変えていたため、 URL がマルチバイト文字を含むタイトルから構成されている記事とそうでない記事が混ざってしまっていました。

記事によっては permalink がかなり長くなっていたので、ついでに permalink も Hugo の slug を元に生成する方式に統一しました。

力技で Hugo の記事の Front Matter を更新する

Hugo は、管理している記事一覧を CSV 形式で出力してくれるコマンドを用意してくれています:

hugo list all

path,slug,title,date,expiryDate,publishDate,draft,permalink
# 以下カンマ区切りで各項目が一覧できる

私の Hugo の記事は、最初期のものは slug が設定されておらず、ある時期から slug を元に permalink を生成する設定に変更していたので前述したように統一感のない permalink となっていました。

なので、

  • slug が設定されていない記事はファイル名をもとに slug を追記する
    • 今後 Hugo でコンテンツを再生成すれば permalink は更新される
  • 旧 permalink を Firebase Hosting のリダイレクト設定に追加する
    • リダイレクト設定については後述します

という作業が必要でした。

とりあえず力技で hugo list all から awksedjq を使って上記の作業を行うシェルスクリプトを用意しました…。

Firebase Hosting のリダイレクト設定を追加する

Firebase Hosting はリダイレクト設定もサポートしています

firebase.json という JSON の設定ファイルに必要な情報を書いていくだけなので楽です。 公式ドキュメントにもありますが、リダイレクト設定を書く場合はこんな感じで転送元、転送先、リダイレクト方式(ステータスコードを 301 にするか、302 にするか)を記入していくのみです:

"hosting": {
  // ...

  // Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
  "redirects": [ {
    "source": "/foo",
    "destination": "/bar",
    "type": 301
  } ]
}

そんな感じで、かなり簡単に移行することができました。 もともと静的サイトジェネレータを使っているだけだったので、単にホスティングサービスを変えれば良いというところではあったのですが、プレビュー環境も簡単に作れるし、デプロイやリダイレクト設定も簡単にできたので Firebase Hosting いいじゃんという気持ちになっています。

このノリで Firebase の他の製品群も試してみたいです。

あと、この移行のタイミングでブログの OGP 画像を生成する機能も追加してみたのでそれも別記事で紹介しています。 興味ある方は読んでみてくだだい。

Return to top