Next.jsのサイト表示速度を向上させるCloudflare Workers導入法

現在、主流となりつつあるインフラ構築を意識せずにサーバーを利用できるサーバーレス環境。CDN環境を提供するサービスとして有名なCloudflareでもサーバーレス環境を構築できるCloudflare Workersという機能があります。
今回は、このCloudflare Workersを使ってNext.jsプロジェクトをデプロイする方法を紹介していきます。
Cloudflare Workersのメリットとは
Cloudflare workersは、他のサーバレス環境とは異なりホットスタンバイ環境のため、アクセスから起動までがゼロタイムで実行されます。
他のコールドスタンバイ環境では、アクセスがあってからサーバーを立ち上げるため処理実行までにタイムラグが発生します。Cloudflare Workersでは、それがないため非常に早くページへアクセスが可能になります。
ローカルにCloudflare Workersの環境を構築する
@opennextjs/cloudflare
というパッケージをプロジェクトに追加する必要があります。> yarn add @opennextjs/cloudflare@latest
wrangler
を開発依存として追加します。> yarn add -D wrangler@latest
次に、wranglerと連携するための設定ファイルをルートディレクトリに設置します。
// wrangler.jsonc
{
"main": ".open-next/worker.js",
"name": "my-app",
"compatibility_date": "2025-03-25",
"compatibility_flags": [
"nodejs_compat"
],
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
}
}
OpenNextで実行するための設定ファイルを設置
Next.jsは、異なるプラットフォーム(AWS, Cloudflare, Netlifyなど)でセルフホストする手段がないため、OpenNextを使ってそれを構築することができます。
// open-next.config.ts
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig();
最後に、package.jsonにローカル環境でOpenNextを実行するためのコマンドを追加します。
- preview : ローカル環境でOpenNextを使ってプロジェクト実行することができます。
- deploy : Cloudflare環境にプロジェクトをデプロイします。
- cf-typegen : プロジェクト内にenvのtypeファイルであるcloudflare-env.d.tsを生成します
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
ローカルでOpenNextを実行
以下のコマンドを実行してOpenNextサーバーでプロジェクトを起動します。
> yarn run preview
yarn run v1.22.21
warning ../../package.json: No license field
$ opennextjs-cloudflare build && opennextjs-cloudflare preview
┌─────────────────────────────┐
│ OpenNext — Cloudflare build │
└─────────────────────────────┘
App directory: /xxxx/xxxx/xxxx/xxxx
Next.js version : 15.3.3
@opennextjs/cloudflare version: 1.2.1
@opennextjs/aws version: 3.6.5
┌─────────────────────────────────┐
│ OpenNext — Building Next.js app │
└─────────────────────────────────┘
warning ../../package.json: No license field
$ next build
Using vars defined in .dev.vars
Using vars defined in .dev.vars
▲ Next.js 15.3.3
Creating an optimized production build ...
Using vars defined in .dev.vars
Using vars defined in .dev.vars
Using vars defined in .dev.vars
✓ Compiled successfully in 8.0s
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages (5/5)
✓ Collecting build traces
✓ Finalizing page optimization
Route (app) Size First Load JS
┌ ○ / 5.63 kB 107 kB
└ ○ /_not-found 977 B 102 kB
+ First Load JS shared by all 101 kB
├ chunks/4bd1b696-67ee12fb04071d3b.js 53.2 kB
├ chunks/684-c85650275c47a38c.js 45.9 kB
└ other shared chunks (total) 1.89 kB
○ (Static) prerendered as static content
┌──────────────────────────────┐
│ OpenNext — Generating bundle │
└──────────────────────────────┘
Bundling middleware function...
Bundling static assets...
Bundling cache assets...
Building server function: default...
Applying code patches: 4.757s
# copyPackageTemplateFiles
⚙️ Bundling the OpenNext server...
Applying code patches:
- patching require
Worker saved in `.open-next/worker.js` 🚀
OpenNext build complete.
┌───────────────────────────────┐
│ OpenNext — Cloudflare preview │
└───────────────────────────────┘
Incremental cache does not need populating
Tag cache does not need populating
warning ../../package.json: No license field
Cloudflare collects anonymous telemetry about your usage of Wrangler. Learn more at https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler/telemetry.md
⛅️ wrangler 4.19.1
───────────────────
╭──────────────────────────────────────────────────────────────────────╮
│ [b] open a browser [d] open devtools [c] clear console [x] to exit │
╰──────────────────────────────────────────────────────────────────────╯
Using vars defined in .dev.vars
Your Worker has access to the following bindings:
Binding Resource Mode
env.ASSETS Assets local
env.NEXTJS_ENV ("(hidden)") Environment Variable local
[wrangler:info] Ready on http://localhost:8787
⎔ Starting local server...
[mf:info] ✨ Parsed 1 valid header rule.
[wrangler:info] GET / 200 OK (304ms)
[wrangler:info] GET /_next/static/media/569ce4b8f30dc480-s.p.woff2 200 OK (73ms)
[wrangler:info] GET /_next/static/media/93f479601ee12b01-s.p.woff2 200 OK (71ms)
[wrangler:info] GET /_next/static/css/759b155474327f76.css 200 OK (71ms)
[wrangler:info] GET /next.svg 200 OK (19ms)
[wrangler:info] GET /_next/static/chunks/webpack-f029a09104d09cbc.js 200 OK (11ms)
[wrangler:info] GET /_next/static/chunks/4bd1b696-67ee12fb04071d3b.js 200 OK (14ms)
[wrangler:info] GET /_next/static/chunks/684-c85650275c47a38c.js 200 OK (80ms)
[wrangler:info] GET /_next/static/chunks/main-app-3b6c6040515531f7.js 200 OK (80ms)
[wrangler:info] GET /_next/static/chunks/app/page-e1249c665e4c9ed6.js 200 OK (71ms)
[wrangler:info] GET /_next/static/chunks/63-11f4d058746abff6.js 200 OK (82ms)
[wrangler:info] GET /vercel.svg 200 OK (71ms)
[wrangler:info] GET /window.svg 200 OK (63ms)
[wrangler:info] GET /file.svg 200 OK (224ms)
[wrangler:info] GET /globe.svg 200 OK (221ms)
[wrangler:info] GET /favicon.ico 200 OK (192ms)

実行時の注意点
Cloudflare Workersでは、CommonJSモードで動く一部の古いパッケージが使えないことがあります。基本的には、EMSモードで実装されたパッケージで動作しているためパッケージを置き換えるか、使わない形に実装を変える必要があります。
Cloudflare Workersへデプロイ
ローカル環境で動作確認ができたら、次は下記のコマンドでCloudflare Workersへデプロイしてみます。
> yarn run deploy
すると、ブラウザが開きCloudflare Workersにインスタンスを追加する許可を求められるので許可します。許可すると、ログの最後にURLが発行されるのでそこからページへアクセスすることができるようになります。

Cloudflareのページからも確認できる
