☁️ Web・クラウド構築

Cloudflare R2とキャッシュルールで実装する画像・3Dアセット配信の高速化と通信費ゼロ設計

#Cloudflare R2#オブジェクトストレージ#コスト削減#CDN#アセット配信

Webメディアや個人開発のアプリケーション、あるいはブラウザ上で動作する 3DCG・WebGL コンテンツを運用する際、最も頭を悩ませるのが 「画像・動画・3Dモデルなどの静的アセットの保管場所と通信費(エグレス料金)」 です。

Git リポジトリ(GitHub + Cloudflare Pages)にすべてを含める構成は手軽ですが、画像やバイナリファイルが数ギガバイトを超えてくると、リポジトリの肥大化やビルド時間の増加、さらには Pages のファイルサイズ上限(1ファイル25MB制限)に突き当たります。かといって一般的なクラウドストレージ(AWS S3 等)を使うと、アクセス急増時に高額なデータ転送料(Egress Fee)が発生するリスクがあります。

この課題を根本から解決するのが、エグレス料金が完全無料のオブジェクトストレージ 「Cloudflare R2」 です。本記事では、Cloudflare R2 に独自ドメイン(サブドメイン)を接続し、Cache Rules と組み合わせて高速なアセット配信基盤を構築する手順を解説します。


1. なぜ個人開発・メディア運用で「Cloudflare R2」が圧倒的に有利なのか?

従来のクラウドオブジェクトストレージと Cloudflare R2 の料金体系・仕様を比較すると、特に下り通信量(ダウンロード通信)が多いワークロードにおいて決定的な差があります。

比較項目一般的なクラウドストレージ (AWS S3等)GitHub リポジトリに直接同梱Cloudflare R2 + Custom Domain
データ転送料(エグレス料金)約 $0.09 / GB(月1TB配信で約1.3万円〜)無料(ただしLFS枠超過時は課金)完全無料(何TB配信しても $0)
無料ストレージ枠初年度のみ 5GB 等リポジトリ推奨上限 1GB〜5GB毎月 10GB まで永続無料(超過分も $0.015/GB・月)
1ファイルあたりのサイズ上限5TBCloudflare Pages は 25MB/ファイル最大 5TB / オブジェクト
APIの互換性AWS S3 標準 APIGit コマンドS3 互換 API(AWS CLI / SDK がそのまま使える)

とくにSNS等で記事やアプリが拡散(バズ)した際、「画像やアセットのダウンロード数が跳ね上がって翌月のクラウド請求額が数万円になる」という通称 「バズ破産」のリスクを物理的にゼロにできる 点が、個人開発者やクリエイターにとって最大の安心材料となります。


2. Cloudflare R2 バケットの作成とカスタムドメイン接続手順

それでは実際に R2 バケットを作成し、自サイトのサブドメイン(例:assets.egpl.net)から HTTPS で安全に配信できるように設定していきます。

2.1 Wrangler CLI(またはダッシュボード)でのバケット作成

普段からターミナルで作業している場合は、Wrangler CLI を使うと1コマンドでバケットを作成できます。

# R2 バケットの新規作成
npx wrangler r2 bucket create egpl-assets

2.2 r2.dev ではなく必ず「カスタムドメイン」を接続する理由

R2 にはテスト用の公開URL(pub-xxxx.r2.dev)を発行する機能もありますが、本番運用では必ず 自サイトのサブドメイン(assets.egpl.net 等)をカスタムドメインとして接続 してください。理由は以下の3点です。

  1. r2.dev にはレート制限(帯域制限)があるため、本番トラフィックの配信には向かない。
  2. カスタムドメインを接続した場合のみ、Cloudflare のエッジキャッシュ(Cache Rules)や画像最適化、WAF がフル機能で使える。
  3. 同一ドメイン配下(サブドメイン)にすることで、HTTP/2・HTTP/3 のコネクション再利用や セキュリティヘッダー設計 の統一が容易になる。

カスタムドメイン接続の手順

  1. Cloudflare ダッシュボード > 「R2 オブジェクト ストレージ」 > 作成したバケット(egpl-assets)を開きます。
  2. 「設定 (Settings)」 タブ内の 「カスタム ドメイン (Custom Domains)」 で「ドメインの接続」をクリックします。
  3. assets.egpl.net と入力して続行すると、Cloudflare DNS 上に自動的に R2 バケット向きのレコードが追加され、数分で SSL 証明書が有効化されます。

3. R2 の Class B オペレーション課金を防ぐ「Cache Rules」設定

Cloudflare R2 はエグレス(通信帯域)こそ無料ですが、バケットからオブジェクトを読み出す回数である 「Class B オペレーション(GetObject / HeadObject)」には月間 1,000万リクエストの無料枠 が設定されています。

もしエッジキャッシュを効かせずに毎回バケット本体へアクセスが到達してしまうと、アクセス数が多いサイトでは Class B オペレーション数を無駄に消費してしまいます。そこで、Cloudflare の「Cache Rules(キャッシュルール)」を設定し、一度読み込まれた画像は Cloudflare のエッジサーバーから直接返す ように構成します。

推奨する Cache Rule の設定値

Cloudflare ダッシュボードの 「Caching」>「Cache Rules」 で以下のルールを作成します。

・ルール名: Cache R2 Static Assets
・条件式: (http.host eq "assets.egpl.net")
・キャッシュのステータス: キャッシュの対象 (Eligible for cache)
・エッジ TTL (Edge TTL): cache-control ヘッダーが存在する場合はそれを使用、ない場合は「1ヶ月 (1 month)」
・ブラウザ TTL (Browser TTL): 7日間〜1年(用途に応じて指定)

この設定を入れておくことで、同じ画像に対する2回目以降のリクエストは世界中の Cloudflare エッジ拠点から直接レスポンス(cf-cache-status: HIT)され、R2 バケットへの Class B リクエスト消費もゼロ、表示速度(Core Web Vitals の LCP)も最速 という理想的な状態になります。


4. WebP / AVIF 変換と wrangler r2 object put による一括アップロード

ブログ記事のスクリーンショットや 3DCG のレンダリング画像をアップロードする際は、事前にローカルで WebP(または AVIF)へ変換し、Cache-Control ヘッダーを付与してアップロードするシェルスクリプトを用意しておくと運用が非常にスムーズです。

# 例:ローカルの画像を Cache-Control 付きで R2 バケットへアップロードするコマンド
npx wrangler r2 object put egpl-assets/blog/2026/studio-setup.webp \
  --file=./studio-setup.webp \
  --content-type="image/webp" \
  --cache-control="public, max-age=31536000, immutable"

また、大量のファイルやディレクトリを一括同期したい場合は、S3 互換 API トークンを発行して rclone または aws s3 sync コマンドを使うのが最も高速です。

# AWS CLI を使った R2 バケットへの高速ディレクトリ同期例
aws s3 sync ./public-assets s3://egpl-assets/ \
  --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com \
  --cache-control "public, max-age=31536000"

5. CORS(Cross-Origin Resource Sharing)設定が必要なケース

単なる <img src="https://assets.egpl.net/..."> タグで画像を表示するだけであれば CORS 設定は不要ですが、Three.js / WebGL で 3D モデル(.glb / .gltf)やテクスチャ画像を fetch で読み込む場合、あるいは <canvas> 上で画像を操作する場合 は、R2 バケットの CORS ポリシー設定が必須となります。

バケットの「設定」>「CORS ポリシー」に以下の JSON を設定することで、本番ドメイン(https://egpl.net)およびローカル開発環境からの 안전한 クロスオリジン読み込みを許可できます。

[
  {
    "AllowedOrigins": [
      "https://egpl.net",
      "http://localhost:4321"
    ],
    "AllowedMethods": [
      "GET",
      "HEAD"
    ],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag", "Content-Length"],
    "MaxAgeSeconds": 86400
  }
]

まとめ

HTML や軽量な CSS/JS は Cloudflare Pages / Workers で Git 管理し、大容量の画像や動画・3Dアセットは Cloudflare R2 + カスタムドメイン + Cache Rules に分離するハイブリッド構成を採ることで、リポジトリを常に軽量に保ちながら、通信費ゼロで高速なメディア・アプリ運用が可能になります。


📚 関連する技術記事

Web・クラウド構築の記事一覧 →