Tech

手軽に静的サイトを公開したいと思った時のホスティングサービス検討(非商用)2024-01

モチベーションと前提

Codepenのように気軽にかけて、さらにReact等を書きやすい環境が欲しく、個人用のStorybook環境を作ろうと思いました。また、それをビルドしたものをどこかに上げておきたいと思い、手軽にホスティングできるような環境を探していました。
ただ、当初思っていたよりホスティングサービスの比較で時間を使ったため、今後は迷わないように記録を残しておこうと思います。

この記事では以下のような自身の経験の背景した判断になっていると思います。

  • 個人のコード管理はほぼ完全にGithubに依存している
  • Github Actionsを使ったデプロイは個人開発でそこそこ慣れている
  • Cloudflare系サービスはまだあまりガッツリ触っていない

結論

「手軽にどこかにホスティングできれば良い」という場合は個人的には今後はGithub Pagesで良さそう、という結論になりました。

ただし、以下の点は注意が必要です。

  • 商用利用は利用できない
  • PRに対してプレビュー環境が立ち上がるような機能ははない
  • 恐らく自動デプロイのためにはGithub Actionを使う必要がある
  • Cacheの細かいコントロールはできない(必ずmax-age=600がつきます)
  • Cloudflare PagesのようなクリックのみでAnalyticsを付けるような機能はない
  • 月間100GBで転送量のソフトリミットがある

要件はなんだったのか

言葉としては「どこかに適当に」、「どこかに気軽に」と思っていましたが、この言葉はなんだったのか考えてみました。

  • 普段使っていないプラットフォームをこのプロジェクトのためだけに新たに採用するのは避けたい
  • プラットフォーム側の事情でメンテが必要な回数が少ない方が望ましい
    • 放置する期間が基本的に長いことが想定されるため
  • ダウンタイム等の稼働の安定性はそこまで重要ではない
  • 無料範囲でのビルド時間の制約が無いか、または細かく従量課金されると嬉しい
    • 今後も同じようなことに取り組む際にも同じプラットフォームを使いたいため
  • セットアップが手間ではない
  • グローバルCDNがついている

ビルド時間の制約についてはStorybook系のインストールは結構時間がかかることや、Renovateが生成するPRからパッケージアップデートの更新情報をキャッチアップしていたりするため、そういったPRが激しめに動いていても気にならない環境が欲しいと思っていました。

また、同じような用途で今後も同じプラットフォームでホスティングしていった場合にも懸念が少ない、という所も気にしていたと思います。

Github Pageの実装方法

実際に使用したGithub Actionを掲載します。以下はmain branchにpushされた時にGithub Pagesにデプロイされます。

# Add build steps コメントと actions/upload-pages-artifactpath 以外の部分はリポジトリのSetting > Pages > Sourceの設定をGithub Actionsに設定際に自動生成されました。

また、独自ドメインについても CNAME subdomain [github_username].github.io
という内容だけで設定できました。

# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["main"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  # Single deploy job since we're just deploying
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Add build steps
      - name: Setup
        uses: pnpm/action-setup@v2
        id: pnpm-install
        with:
          version: 8
          run_install: false
      - uses: actions/setup-node@v3
        with:
          node-version-file: '.tool-versions'
          cache: pnpm
          cache-dependency-path: pnpm-lock.yaml
      - name: Install Dependencies
        run: pnpm install --frozen-lockfile --ignore-scripts
      - name: Build
        run: pnpm build-storybook
      # ===end Add build steps

      - name: Setup Pages
        uses: actions/configure-pages@v4
      - uses: actions/upload-pages-artifact@v3
        with:
          path: storybook-static
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

検討したものたち

Cloudflare R2

R2の前段としてworkerをかませるとできるらしい記事は色々見つかるものの、R2のPublic URLからできないかを模索しました。R2のパブリックURLではS3のように 末尾 / のURLを で index.html を読み込ませるような機能はなさそうでした。

ただ、Cloudflareでドメインを管理しているのであれば、ドメインを接続した上で、ドメイン側のルールで Rewrite Ruleを定義すると実現できましたが、使用したいドメインは現状ではCloudflareで管理していないため、除外しました。

この手順はこちらを参考にしました。

その他余談として一旦手動でファイル郡をブラウザからアップロードして試していたのですが、Bucketを削除するためにはすべてのオブジェクトを削除しないといけないものの、ディレクトリがGUIから削除できず悲惨でした…。

認証情報を設定後、aws cliを使って削除しました。(--dryrunを消すと実行)

$ aws s3 rm s3://<bucket-name> --endpoint-url https://<cloudflare-id>.r2.cloudflarestorage.com --recursive --dryrun

Cloudflare Pages

GUIからポチポチするだけでデプロイが完了し、Analytics機能もワンクリックで有効にできたため、もう少しまともなものを運用する選択肢としては良さそうでした。

引っかかったのは .tool-version で定義されたNode.jsバージョンや package.jsonengines に定義されたpnpmのバージョンが上手く復元されず、ビルドエラーになってしまったことです。(もしかしたら packageManager を使用するのが正しく engines で認識しないほうが正しいかもしれません。再検証はしていません。)

これらは NODE_VERSIONPNPM_VERSIONの環境変数を設定することで動作はできたものの、変更があるたびに環境変数を変更しないといけないとなるとちょっと手間だなと思いました。

その他サービスとしてビルドの制限が500回/月がフリープランでの制約となっており、超えてしまった場合には従量課金ではなく$20課金する必要があり、今回探しているものとしてはマッチしませんでした。商用利用を含めちゃんとした中身をホスティングしたい場合には良さそうだなと思いました。

また、今のビルド回数がどこにも表示されておらず、いつ上限に達するのかがわからない漠然とした不安がある部分も個人的にはあまり好きではありませんでした。どこかに表示されていないかなと探してみても今は表示されていない、という結論になっているフォーラムの情報しか見つかりませんでした。

ちなみにWranglerを使ってDirect Uploadする、という方法で恐らくビルド回数を増やさない方法もありましたが、慣れていないということもあって採用しませんでした。

その他今回は関係ないですが、モノリポ構成の場合2つ目からGUI経由でホスティングできないという問題もありそうでした。

その他の選択肢

ビルド時間の制約、設定の簡易さ、プラットフォームの重さ等で見送っています。

  • Render
    • 500 min / Free Pipeline Minutes per Month
  • Netlify
    • 300 / build minutes per month
  • Vercel
    • 100 / Deployments Created per Day
  • Amplify / S3 + Cloudfront / 似たようなGCP
    • こういうレベルの用途でAWS・GCPを使いたくない
  • Firebase Hosting
    • Git連携レベルで簡単に構築できなさそう(深くは調査していません)

おわりに

結構月間のビルド時間や回数を気にして検討しての結果になってしまったかもしれません。
とはいえ、Github Actionsの場合、パブリックであればそもそも無料ですし、無料でプライベートでも月当たり無料枠 2000min (proは3000min)、超過しても $0.008 / min なため、用途に対してマッチしすぎているなと思いました。

あとはそもそもとしてこんなに無料で簡単にホスティングできる選択肢があるのすごいなと思いました。

なんとなく最近はADRを残す文化を参考にArchitectureに限らず決断したことを残していったりしつつ、年末になって「今年なんもやってない」と感じるのを避けていけたらと思います。

それではまた!

参考記事類

share