1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【小ネタ】Cloudflare Pages Functionsを「開発環境だけ」実行させたい(本番で無料枠を使いたくない)

1
Posted at

やりたかったこと

  • Cloudflare Pages Functionsで認証などの処理をかけたい
  • 開発環境(プレビュー)には認証をかけたい
  • 本番環境には認証をかけたくない
  • さらに、本番環境ではそもそもPages Functionsを実行させたくない(重要)
    • 無料枠に収めるには1日10万回のリクエスト制限内に抑える必要があるため

背景

Cloudflare Pages Functionsで functions/_middleware.ts を配置すると、すべてのリクエストに対してミドルウェアが動作します。環境変数で分岐して開発環境のみにBasic認証をかけること自体は可能ですが、

  • 本番環境でも _middleware.ts が存在する限り、全リクエストでFunctionsが実行される → つまり無料枠(1日10万回)を消費してしまう

という問題があります。
静的配信だけで済むはずの本番環境で、Functionsの実行回数を使い切りたくありません。

なお、認証だけが目的なら本来は Cloudflare Access を使うのが正攻法ですが、今回は諸事情(独自の認証ロジックを使いたい等)でPages Functionsを使う前提の話です。

解決方法

2通りの方法を紹介します。

方法1: _routes.json で Functions の実行範囲を制御する(推奨)

_routes.json は、Functionsをどのパスで実行するかを制御する設定ファイルです。includeexclude でルートを指定でき、excludeinclude よりも優先されます

つまり、exclude: ["/*"] と書けば全パスでFunctionsが非実行になります。

本番デプロイ時だけこの _routes.json をビルド成果物ディレクトリに配置することで、

  • 開発:全パスでFunctionsが実行される(_routes.json を配置しない)
  • 本番:全パスでFunctionsが実行されない(全exclude の _routes.json を配置)

という切り分けができます。

# 本番のみ、全パスでFunctionsを実行させない _routes.json を配置
- name: Disable Functions for production
  if: env.DEPLOY_ENV == 'production'
  run: |
    cat > out/_routes.json <<'EOF'
    {
      "version": 1,
      "include": ["/*"],
      "exclude": ["/*"]
    }
    EOF

- name: Deploy to Cloudflare Pages
  uses: cloudflare/wrangler-action@v3
  with:
    command: pages deploy out --project-name=test_proj --branch=main

方法2: _middleware.ts をそもそもアップロードしない(力技)

こちらはちょっと力技で、本番デプロイ時に _middleware.ts ファイル自体を削除してからアップロードする方法です。

ファイルが存在しなければFunctionsも定義されないので、当然実行もされません。

# 本番デプロイ時のみ削除
- name: Remove _middleware.ts
  if: env.DEPLOY_ENV == 'production'
  run: rm -f functions/_middleware.ts

- name: Deploy to Cloudflare Pages
  uses: cloudflare/wrangler-action@v3
  with:
    command: pages deploy out --project-name=test_proj --branch=main

注意

方法2が使えるのは「事前ビルド+アップロード型」のCI/CDだけです。

GitHub Actionsなどでビルド済み成果物をPagesにアップロードする構成であれば、どちらの方法も使えます。

一方、Pages側のビルドシステム(Cloudflareのダッシュボードで設定するビルドコマンド)でビルドを行う場合、方法2はうまくいきません。

Pages側ビルドで試してダメだったこと

次のような方法を試しました。

  • package.json のビルドスクリプトに _middleware.ts を削除するコマンドを仕込む
  • ビルドコマンドに npm run build --extract-middleware のようなオプションを用意して削除する

しかし、Pages側のデプロイでは functions/ ディレクトリがビルド成果物とは別にリポジトリのルートから直接読み込まれるようなので(推測)、ビルドスクリプトの中で _middleware.ts を削除しても反映されませんでした。

まとめ

  • 今回の方法は、諸事情でPages Functionsを使う必要があり、かつ無料枠に収めたい場合の苦肉の策
  • 本来、Cloudflare Pagesに認証をかけたい場合は Cloudflare Access を使ってOTPやIP制限を設けるのが正攻法
  • ドメインをCloudflareで管理しているなら、Cloudflare Workers を使えばドメイン単位でEdge関数を実行できるので、そちらのほうが柔軟

同じような制約で悩んでいる人の参考になれば幸いです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?