GitHub のサービスだけで Jamstack っぽいものを作る


JAMSTACK とは何?

を読んでみると、

  • サーバー通信を伴う動的要素は排除して、クライアントサイドで完結するコンテンツ配信をしようぜ
  • 動的にコンテンツを変えたいなら、その都度、サイト自体を生成しなおそうぜ

という方式に見えます(解釈者によってだいぶ「揺れ」があるようにも感じますが)。。

東京都 新型コロナウイルス感染症対策サイト (および派生サイト)もこの方式で作られていて、「あ、これ JAMSTACK って言うんだー」と思った次第です。

Webアプリを(PWA などで)オフライン対応したいと考えたとき、オフライン環境下では通信処理が一切使えないわけですから、コンテンツを静的に含んだ形で配信してしまう Jamstack はよい方式だな、と感じました。

コンテンツを変化させサイトを再構築する仕組みも含めて、できるだけシンプルな構成で MVP(Most Viable Product) をサクッと作って公開できるテンプレートのリポジトリを作ってみました。

作成したサンプル "jamstack-sample-angular-node"

「ある GitHub ユーザーが持つリポジトリ群へ送信されたプルリクエスト一覧を新しい順に表示する」というサイトです。

JAMSTACK でないなら、

  1. ページをサーバーに要求して、サーバー側でデータを収集し、ページを生成して返却(いわゆる SSR<Server Side Rendering>)
  2. フロントエンドの JavaScript で GitHub からデータを収集し、DOM を組み立てる(DHTML というか Ajax というか)

のように構築されるでしょうか(2. はそれ自体が "NOT Jamstack" を示すものではないとは思います)。

今回作成したものは、

  1. データの収集はサーバー側のバッチ処理で行う
  2. 同じくバッチ処理で 1. のデータを組み込んだサイトを生成する
  3. サイトを公開する
  4. サイトは自身が持つコンテンツのみを使用する

1~3 は GitHub Actions で行い、プログラムは node.js 製です。
3 のホスティングは、GitHub Pages を使用します。 1
4 のサイトは Angular による SPA(Single Page Application) です。2

全体

リポジトリの構成は以下のようになっています。

root
 ├/tool
 ├/spa
 ├/docs
 └/.github

tool ディレクトリは、node(TypeScript)製のプログラムで、バッチ処理自体を担当するものです。
yarn gen で起動し、プログラム中に記述されている GitHub ユーザーのリポジトリと PR群 を収集して、spa ディレクトリ配下に data.json を生成します。

spa ディレクトリは、Angular 製の SPA プログラムです。
配下にある data.json の内容を table で表示するだけのシンプルな Webアプリ です。

docs ディレクトリは、GitHub Pages によりホスティングされる場所で、ビルドされた Angularアプリのファイル群が後述の GitHub Actions によりコピーされます。
より詳しくは、Repository の Setting で「master ブランチの docs ディレクトリを公開する」と設定された結果です。
尚、ブランチの使い方としては、master は公開用とするため docs ディレクトリしか存在せず、ソースファイル群は development ブランチで管理しています。

公開されたリポジトリは、 ttps://<ユーザー名>.github.io/<リポジトリ名>/ が公開用URLになります。私のサンプルの場合は https://amay077.github.io/jamstack-sample-angular-node/ です。

.github ディレクトリは、GitHub Actions のワークフローファイル が格納されています。

このファイルの記述により、「development ブランチへの push」または「毎日午前3時(JST)」に、

  1. tool ディレクトリで yarn gen を実行して spa 配下に data.json を生成
  2. spa ディレクトリで yarn build-prod を実行して公開用Webアプリを生成
  3. 2 のファイル群を master ブランチの docs ディレクトリにコピー
  4. master ブランチを push して公開

を行っています(この workflow yml はシロウトが書きました)。

サンプルの対象ユーザーは Microsoft になっているので、公開されたサイト では、Microsoft のリポジトリ(更新順に10件)へ送られた Pull Request が新しい順に表示されます。

Fork して動かす方法

  1. https://github.com/amay077/jamstack-sample-angular-node を Fork する
  2. Repository の Setting で「master ブランチの docs ディレクトリを公開する」と設定する
  3. development ブランチの、tool の対象ユーザー を任意の GitHub ユーザーに変える
  4. development ブランチを push する

で、GitHub Actions が起動して、サイトが公開されるはずです。
公開される URL は前述の通り、 ttps://<ユーザー名>.github.io/<リポジトリ名>/ 。

ローカルで動かす方法

node(npm), yarn が必要です。

  1. https://github.com/amay077/jamstack-sample-angular-node を clone する
  2. GitHub - Personal Access Tokens で、repo へのアクセス権を持った token を生成する
  3. 環境変数 GITHUB_TOKEN に、2 の token を設定する(tools/.env ファイルに GITHUB_TOKEN=<2 の token> と記述しても OK)
  4. tools, spa 各ディレクトリで yarn を実行する
  5. tools ディレクトリで yarn gen を実行する( spa/src/data/data.json が更新されるはずです)
  6. spa ディレクトリで、npx ng serve を実行する
  7. ブラウザで http://localhost:4200/ を開く

で動くと思います。


  1. Jamstack の説明でよく紹介されているのは Netlify や Firebase Hosting、Azure でも可能になった ようです。 

  2. Jamstack の説明では SSG<Static Site Generator> が挙げられているので、この部分は厳密には Jamstack ではないのかも知れません。GitHub Pages には Jekyll が搭載されていますが、今回は使用していません。