10万リクエスト無料の超高速画像最適化CDNを作った話

スタートアップ企業や個人開発をしている皆さんに朗報です。Next.jsで超簡単に導入できる、無料で月間10万リクエストまで使える画像最適化CDNを作ったので、その紹介と技術的な裏側についてお話ししたいと思います。

## 作ったもの
https://toolpods.io/image-cdn

## 画像最適化で解決できる3つの課題
Web開発をしていると、画像の扱いって意外と厄介ですよね。サイズが大きい画像をそのまま使うとめちゃくちゃ重くなったり、費用がかさんだり。
でも、適切な画像最適化を実装すれば、以下の3つの課題を一気に解決できるんです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982301/96207edd-cf1a-487e-9c2b-ff9329468696.png" width=300 />


### 1. ページ表示の爆速化でユーザー体験を向上
最適化していない大きな画像をそのまま表示すると、読み込みに時間がかかってページの表示が遅くなります。画像を最適化することで、ファイルサイズを大幅に削減でき、ページの読み込み時間を短縮できるんです。
実際、ページの読み込みが3秒以上かかると、約40%のユーザーが離脱するというデータもあります。特にモバイル回線では、この差が体感できるレベルで現れ、ユーザーの満足度と滞在時間を大きく向上させることができます。

### 2. Core Web Vitalsスコア改善でSEO効果アップ
Googleの検索エンジンは、ページの読み込み速度を重視するようになっています。Core Web Vitalsと呼ばれる指標の中でも、LCP（Largest Contentful Paint）やCLS（Cumulative Layout Shift）といった画像に関連する指標は特に重要です。
画像が最適化されていないサイトは、これらの指標で低いスコアとなり、検索順位が下がる可能性があります。逆に言えば、画像最適化はSEO対策として非常に効果的なんです。

### 3. 転送データ量削減でインフラコスト削減
最適化された画像はファイルサイズが小さいため、転送データ量が減少します。これにより、サーバーやCDNのコストを削減できます。特に、画像が多いサイトでは、この削減効果は大きいです。
例えば、1MBの画像を100KBに圧縮できれば、転送データ量は約90%削減されます。
`アクセス数 × 1度に表示される画像枚数` を考えると、この差は決して小さくありません。

## 導入方法（たった3ステップで完了）
導入がめちゃくちゃ簡単になるように、意識して作ってみました。たった3ステップで完了します。

1. サービスに登録する
2. 利用中のサービスのURLを登録する
3. アプリケーション側で画像のURLを変更する

これだけです。

Next.jsの場合は個別の画像URLを変更しなくても、`next/image`を使っている場合下記の設定で簡単に設定できます👍

### Next.jsでの設定例

1. next.config.jsを変更して..

```js:next.config.js
/** @type {import('next').NextConfig} */

const nextConfig = {
  images: {
    loader: "custom",
    loaderFile: "./imageLoader.js",
  },
};

module.exports = nextConfig;
```

2.imageLoader.jsを配置したら完了！
```js:imageLoader.js
// ローカル開発環境の判定
const isDevMode = process.env.NODE_ENV === "development";
// クライアントのドメイン.
const clientDomain = process.env.NEXT_PUBLIC_CLIENT_DOMAIN;

// ドメインを整形
const shapeDomain = (domain) => {
  const prefix = domain.startsWith('http') ? '' : 'https://';
  const suffix = domain.endsWith('/') ? domain.slice(0, -1) : domain;
  return `${prefix}${suffix}`;
}

// 相対URLを絶対URLに変換
const convertToAbsoluteUrl = (src) => {
  const isAbsoluteUrl = src.startsWith('http');
  return isAbsoluteUrl 
    ? src 
    : `${shapeDomain(clientDomain)}${src}`;
}

// 画像のローダー
module.exports = ({ src, width, quality }) => {
  return isDevMode 
    ? src
    : `https://cdn.toolpods.io/?url=${convertToAbsoluteUrl(src)}&w=${width}&q=${quality || 75}`;
};
```
これで完了です！あとは通常通りnext/imageコンポーネントを使うだけで、すべての画像が自動的に最適化されます。

## なぜ無料で提供できるのか？
「そんな便利なサービス、しかも10万リクエストまで無料で使えるって、本当に大丈夫なの？」って思いますよね。実はここには二つの理由があります。

### 1. 有料プランへの広告費として
一つ目の理由は、有料プランを使ってもらうための広告費として無料プランを提供していることです。個人開発者の方には無料プランで十分なケースが多いと思いますが、サービスが成長して月間10万リクエストを超えるようなら、有料プランへの移行をご検討いただければと思います。そしてぜひ周りの方にもシェアしてもらえると嬉しいです！
ちなみに、月額9,800円の有料プランだと月間1,000万リクエストまで使えるので、本格的なサービス運用にもマジでオススメです。サイトがめっちゃ早くなるし、インフラ費用もぐっと抑えられるはずですよ。

### 2. 徹底したインフラコスト削減の工夫
もう一つの理由は、Cloudflareのサービスを最大限活用してコストを極限まで抑えていることです。具体的には以下の技術を使っています：

- Cloudflare Workers - エッジで処理を行い、ユーザーの近くのサーバーでリクエストを処理
- Cache API - 一度処理した画像をキャッシュして再利用
- Durable Objects - 分散システム内での状態管理に使用

注目すべき点は、Cloudflareの変換APIは使っておらず、変換処理は自前で実装していることです。基本的には画像をWebP形式に変換し、サイズを動的に変更できるようにしています。
また、コスト削減の重要なポイントとして、画像の実体は私たちのサービスでは保持していません。オリジンサーバーから画像を取得して変換するだけなので、ストレージコストを大幅に削減できているんです。

## 爆速レスポンスの秘密
このサービスを開発する上で最も重視したのは「爆速レスポンス」です。どうやって実現したかというと、最速でキャッシュヒットさせてレスポンスを返し、その後の非同期処理でその他の処理を行うようにしました。

### キャッシュ戦略と非同期処理の最適化
一般的な画像変換処理は注文を受けてから一から調理して時間がかかりますが、私たちのCDNは「よく注文される商品はあらかじめ作っておく」方式です。キャッシュがあれば（人気メニューがすでに作ってあれば）即座に提供し、その後でレシート発行や在庫管理（ログ保存など）をバックグラウンドで行います。

これにより、ユーザーが体感するレスポンス時間を劇的に短縮しています。

## 導入効果：Before & After
このサービスを導入すると、Webサイトのパフォーマンスがどれだけ向上するのか気になりますよね。
ということで適当なフリー画像を9枚表示する簡易的なサイトを作成し、画像最適化の有無で比較してみます。
画像は適当に拾ったのでかなりサイズにばらつきがありますが、そのまま使っています。

### 最適化前

![スクリーンショット 2025-04-25 16.28.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982301/a7f65465-1de6-4513-b9b1-3497b524a572.png)

16.5MBという爆弾のような画像がありますね。
当然サイズが大きので、その分かかる時間も長くなっていますね。

![スクリーンショット 2025-04-25 16.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982301/4e975a1b-9788-40a2-8d6f-20f93a4de352.png)

Page Speed Insightsでの測定結果です。
画像9枚並べただけで、スコアが非常に悪く、特にLCP（Largest Contentful Paint）が25.5秒とすごい事になっています。

### 最適化後

![スクリーンショット 2025-04-25 16.28.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982301/d8efb2af-cc0d-4fe5-adc6-90f5cd55ed7e.png)

先ほど最大16.5MBという画像もありましたが、今回は全てwebp及び適切なサイズに変換され、最大でも56.1KBまで削減されています！
サイズも小さいのでリクエスト完了までの時間もかなり50ms未満と大幅に短くなっています👏

![スクリーンショット 2025-04-25 16.30.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982301/8d6ee448-f6ba-4ff6-89b7-f5fb7df20246.png)

Page Speed Insightsでの測定結果です。
LCPは2.6秒まで下がり、点数も48点→90点へと大幅に上がっています👏

## Vercelを使っている開発者にもおすすめ
Next.js開発者、特にVercelでホスティングしている方にとって、このサービスはさらに大きなメリットがあります。
### 画像変換料金の大幅削減
Vercelの画像最適化は便利ですが、料金体系が複雑で予想外のコストが発生しやすいんです。具体的には：
- Hobbyプランでも月5,000回、Proプランでも月10,000回という制限があります
- 制限を超えると1,000回あたり$0.05〜$0.0812のコストが発生
- 画像が多いサイトだと、この制限はあっという間に超えてしまいます

### 複雑なキャッシュコスト問題の解消

- 画像キャッシュの読み取りと書き込みに別々の料金がかかります
- 特にキャッシュ書き込みは100万回あたり$4.00〜$6.40と高額
- これらの変数が多すぎて、使用量の予測が難しいんです

### 帯域幅課金からの解放

- Vercelの高速データ転送は1GBあたり$0.15〜$0.47かかります
- 私たちのサービスなら月間10万リクエストまで無料、有料プランでも月間1000万リクエストまで使い放題なので、そもそも帯域幅で課金されるという心配がありません

何より素晴らしいのは、複雑な料金体系ではなく、月額固定の明確な料金体系なので、突然の高額請求に悩まされることがないという安心感です。

## 多様なプラットフォームに対応
このサービスはNext.jsやVercelだけのものではありません。様々なプラットフォームで活用できます。

### AWS S3 / Google Cloud Storageと組み合わせた使い方

クラウドストレージに保存されている画像も最適化できます。AWSのS3やGoogle Cloud Storageと組み合わせることで、ストレージコストはそのままに、配信時の最適化が可能です。
特に大量の画像を扱うECサイトなどでは、この組み合わせが非常に効果的です。

### VPSとApacheやNginxを組み合わせた使い方

自前のVPSでサイトを運用している方も、このCDNサービスの恩恵を受けられます。ApacheやNginxのサーバー設定に数行追加するだけで、既存のウェブサイトのすべての画像リクエストを最適化経路にリダイレクトできます。
例えば、Nginxなら以下のような設定を追加するだけです：
```nginx
location ~* \.(jpg|jpeg|png|gif|webp)$ {
    # 元のURLをエンコード
    set $encoded_url $scheme://$host$request_uri;
    set $cdn_url "https://cdn.toolpods.io/?url=$encoded_url&w=800&q=75";
    
    # プロキシパス
    proxy_pass $cdn_url;
    proxy_set_header Host cdn.toolpods.io;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
```
これにより、サーバーのCPU負荷を減らしながら画像配信を高速化でき、特にVPSのリソースが限られている個人開発者やスモールビジネスにとって大きなメリットとなります。既存システムに一切手を加えることなく画像最適化が実現できるのは魅力的ですね。

### WordPressサイトでの活用例
WordPressサイトでも簡単に導入できます。プラグインを使用するか、テーマのfunctions.phpに数行のコードを追加するだけで、サイト内のすべての画像を自動的に最適化できます。
特に画像を多用するブログやポートフォリオサイトでは、ページ読み込み時間が大幅に短縮され、ユーザー体験が向上します。

## まとめ：個人開発とスタートアップに最適な理由
今回紹介した画像最適化CDNサービスは、特に個人開発をしている方やスタートアップの方にぴったりだと思います。Next.js+Vercelの組み合わせを使っている方はもちろん、WordPressや各種クラウドサービスを利用している方にも、コスト面でもパフォーマンス面でも大きなメリットが得られるはずです。
とはいえ、万能というわけではありません。月間10万リクエストを大幅に超えるような大規模サービスの場合は、有料プランの検討か、他の選択肢も視野に入れるといいかもしれません。
というわけで、Next.jsで個人開発をしている方、これから始めようとしている方、ぜひ一度試してみてください。サイトの高速化と、画像最適化の悩みから解放されること間違いなしです！
質問や導入でのお困りごとがあれば、いつでもお気軽にご連絡ください。みなさんの個人開発がもっと楽しく、そして成功するものになりますように！

https://toolpods.io/image-cdn