30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

SPA を GitHub Actions でビルドして GitHub Pages にデプロイする

デプロイの自動化と History API のフォールバック設定を行うことで、GitHub Pages で SPA を公開できるようにする。

具体的なゴールは以下の通り。

  • masterブランチにプッシュすると、自動的にビルドが行われる
  • ビルドした内容が GitHub Pages として公開される
  • History API のフォールバックが設定されており、SPA として問題なく機能する

以下がサンプルコード。

github.com

上記のリポジトリによって公開されたページ。内容はない。
https://numb86.github.io/spa-sample/

なお、この記事では SPA の作り方そのものは扱わない。

ビルド用のコマンドを用意し、ビルドの出力先を決める

サンプルコードでは、$ yarn buildでビルドし、その結果をpublic/に出力するようにしている。
public/の内容を GitHub Pages として公開することになるので、公開に必要なものは全てこのディレクトリに含まれるようにしておく。

GitHub Actions の設定を行う

デプロイを行うための GitHub Actions の設定を行う。

ここがこの記事の主題ではあるのだが、まさにそのための Action を公開している方がいたので、そのままそれを使うことにした。

github.com

README に記載されているサンプルも、ほぼそのまま流用した。

これを元にしたコードを.github/workflows/gh-pages.ymlとして保存した。
これで、GitHub Actions が有効になる。

以下のように記載することで、masterブランチにプッシュされたときにのみ、実行されるようになる。

on:
  push:
    branches:
      - master

最後の行のpublish_dir: ./publicで、public/の中身がgh-pagesブランチに展開されるように設定している。
その前に$ yarn buildでビルドすることを忘れないようにする。

${{ secrets.GITHUB_TOKEN }}と記載してトークンを使用しているが、このトークンは自動的に生成されるので、改めて何かする必要はない。

help.github.com

これもREADME に書かれてあるが、初回デプロイ時のみ、リポジトリの設定ページで GitHub Pages の設定し、改めてもう一度デプロイする必要がある。

History API のフォールバックを設定する

GitHub Pages に限らず、SPA を公開する場合は History API のフォールバックを設定する必要がある。

フォールバックを設定しない場合、https://numb86.github.io/spa-sample/aboutに直接アクセスしたり、このページでリロードしたりすると、404 ページが表示されてしまう。
今回のサンプルページの場合、まずindex.htmlが表示され、そこに記載されている JavaScript が読み込まれることで、SPA が展開される。
そのため、まず最初にindex.htmlを表示する必要がある。だがhttps://numb86.github.io/spa-sample/aboutにアクセスするとabout.htmlを表示しようとするため、ファイルが見つからず 404 エラーになってしまう。

通常はサーバ側で対応するが GitHub Pages ではそういったことはできないため、JavaScript で対応する。

まず、オリジナルの 404 ページを用意する。デフォルトだと GitHub が用意した 404 ページが表示されるが、404.htmlという名前のファイルを用意することで、404 エラーのときにそのファイルが表示されるようになる。
今回はsrc/404.htmlを用意し、それをGitHub Actions のなかでpublic/にコピーすることにした

そしてその 404 ページにスクリプトを書き込み、index.htmlにリダイレクトさせる。
その際に URL にクエリパラメータをつけることで、どこからリダイレクトされてきたのかが分かるようにする。
最後にindex.htmlにもスクリプトを書き、リダイレクト元に応じてページの内容を書き換える。

https://numb86.github.io/spa-sample/aboutの場合、以下のような流れになる。

  1. https://numb86.github.io/spa-sample/about.htmlが存在しないため、https://numb86.github.io/spa-sample/404.htmlが表示される
  2. 404.htmlのスクリプトによって、https://numb86.github.io/spa-sample/?originalPath=/aboutにリダイレクトされる
  3. https://numb86.github.io/spa-sample/index.htmlが返され、そこに書かれているスクリプトによって URL がhttps://numb86.github.io/spa-sample/aboutに書き換えられ、React Router によって処理されてThis is about page.と表示される