Next.jsの画像、どこに置いていますか?
/publicフォルダは手軽だけど、画像が増えるとビルドが重くなる。Vercel Hobbyプランの帯域制限も気になる。外部ストレージ(S3など)は転送料金が...という課題が発生します。
この記事では、これらの課題を解決するために、Cloudflare R2 + 独自ドメインを利用してコストを抑える(小規模なら無料枠内でも十分な量)方法を解説していきます。
なぜ「R2 + 独自ドメイン」なのか?
「R2 + 独自ドメイン」を利用した場合のメリットは、
- データ転送料金が無料(独自ドメイン関係なし)
- Cloudflare CDN経由で高速配信(独自ドメイン関係なし)
- 独自ドメイン接続でキャッシュが効き、オペレーションコスト(クラスB)を削減できる
2025/11時点でのR2の無料枠は以下になります↓
- 月間10GBのストレージ
- Aクラス操作100万回/月(書き込む,変更する,一覧を見る 等)
- Bクラス操作1000万回/月(既存のデータを読み取る 等)
他の案と比較したものは以下になります(一部偏見含みます)↓
| 項目 | ① R2 + 独自ドメイン | ② R2(独自ドメインなし) | ③ 外部ストレージ (S3等) | ④ Next.js /public |
|---|---|---|---|---|
| URLの例 | images.example.com/pic.jpg |
pub-xxxx.r2.dev/pic.jpg |
bucket.s3.amazonaws.com/pic.jpg |
/img/pic.jpg |
| 表示速度 | 最速 (CDNキャッシュ) ✅ | 高速 (CDN経由だがキャッシュしない) | やや遅い (CDNなしの場合) | 最速 (CDNキャッシュ) ✅ |
| コスト | ほぼ無料 (転送料金ゼロ, オペレーション消費を抑制) |
ほぼ無料 (転送料金ゼロ, アクセス毎にクラスB消費) |
高コスト ⚠️ (データ転送料金が発生する場合) |
無料✅ |
| ビルド速度影響 | なし✅ | なし✅ | なし✅ | あり⚠️ |
| キャッシュ設定 | 柔軟 ✅ | なし⚠️ | 一部できる | 一部できる |
| ドメイン依存 | あり ⚠️ | なし ✅ | なし ✅ | あり ⚠️ |
ドメイン依存に関しても、.env等などを使用すれば解決できる場合もあるので、特に理由がない場合は、「R2 + 独自ドメイン」が個人的に良い選択肢だと思っています。
ただし、外部ストレージでも、「S3 + CloudFronts」を利用すれば最速 (CDNキャッシュ)にはなるので、クラス操作が多いプロジェクトの場合は「S3 + CloudFronts」などの方が適切な場合もあります。
Next.js + Cloudflare R2 + 独自ドメイン 設定手順
1、Next.jsアプリをCloudflare Workersにデプロイする
以下の記事で解説しているので、こちらをご覧ください↓
https://qiita.com/sattoon/items/bdb66ee327741b777aaf
2、デプロイしたプロジェクトに独自ドメイン(メインドメイン)設定
1年間無料で利用できるお名前.comで独自ドメインを取得しました。
以下の記事で解説しているので、こちらをご覧ください↓
https://qiita.com/sattoon/items/8c19c0f4d1bac0cb49c7
3、R2バケットを作成し、独自ドメイン(サブドメイン)設定
Cloudflareのホームアカウント画面の左側「ストレージとデータベース」→「R2オブジェクトストレージ」→「概要」→「バケット作成」→「バケット名」を入力し「バケットを作成」を押下します↓
今回は、以下のようにサブドメインを使用するため、
- nextjs-test.com(メインドメイン) : next.js用(アプリ用)
- img.nextjs-test.com(サブドメイン) : R2用(画像用)
サブドメインのDNSレコード(例:CNAME img nextjs-test.com)も追加します↓
作成したR2に独自ドメイン(サブドメイン)を設定していきます。「R2オブジェクトストレージ」→「概要」→「作成したR2のバケットを選択」→「設定」→カスタムドメイン「追加」で、設定したいサブドメイン(例: img.nextjs-test.com)を入力して、「続行」を押下します↓
Next.js側にメインドメインを設定しているため、R2はサブドメインを設定するようにしています。(サブドメインではなく、異なるメインドメインを設定することも可能です)
「続行」を押下後、以下のように表示されるので「ドメインに接続」を押下して既存のDNSレコードを更新します↓
最後にテスト画像をUPして動作確認します。Cloudflareから直接UPする場合は「R2オブジェクトストレージ」→「概要」→「作成したR2のバケットを選択」→「オブジェクト」→「コンピューターから選択します」クリックでファイルがUPできます(ディレクトリの作成なども可能です)↓
終わりに
以上の手順で画像が公開されたので(ファイルURLで画像読み込みが可能)なので、後はNext.js(プロジェクト)から必要に応じて参照します。





