Next.js middleware の実行環境 Edge Runtime とは?
こんにちは、Gaji-Labo フロントエンドエンジニアの下條です。
Gaji-Labo では、React や Next.js を得意分野として、スタートアップ支援・プロダクトチーム支援をしています。
Next.js が Node.js の実行環境で動作していることはご存知かと思いますが、middleware が Edge Runtime という実行環境で動作していることをご存知でしょうか?
この記事では、
- Edge Runtime って何?
- Node.js Runtime と何が違うの?
- middleware で Node.js Runtime を使えるの?
という疑問を持っている読者を想定して書いています。
middleware の役割
middleware は名前の通り、クライアントとサーバの中間で、リクエストを処理する仕組みです。 middleware で行う用途の例としては、
- 認証前にログイン後の URL にアクセスした際にログイン画面にリダイレクトする
- リクエストデータをキャプチャしてログに記録する
- A/Bテストのためにリクエストごとにパスを書き換えて返却する
などが挙げられます。
具体的な使用例は Next.js の公式ドキュメントを参照してください。
Edge Runtime とは?
タイトル通り、Next.js middleware は、Edge Runtime という実行環境で動作しています。
Edge Runtime を一言で言うと、「軽量で速いけど機能が一部制限されたJavaScriptの実行環境」です。
Edge Runtime は V8 エンジン を採用しており、fetch
, Request
, Response
などの Web 標準 API をサポートしていますが、 fs
, http
, crypto
といった Node.js のネイティブ API が使用できません。
そのため、middleware 上で認証情報を暗号化したい場合や、ファイルシステムにアクセスしたい場合に、Node.js のAPI を使用できず、外部モジュールの使用やアプリケーション側に機能を移すなど、代替手段を検討するしかありません。
サポートしているAPIの詳細は、公式ドキュメントの Edge Runtime 章を参照してください。
Edge Runtime はエッジコンピューティングでの使用を想定されており、必要な機能だけを厳選して軽量化を図っています。
エッジコンピューティングとは、実際のサーバーから離れた場所(エッジ)に配置することで、物理的にユーザに近い距離で提供されるため一般的にレスポンスが速いとされています。
エッジコンピューティングは、
- Cloudflare Workers
- Vercel Edge Functions
- AWS Lambda@Edge
などのサービスが挙げられますが、多くのサービスでは軽量設計のため利用可能なメモリやコードサイズに制限があります。例えば Vercel の場合、1MB〜4MBのコードサイズの制限や、25秒以内のレスポンスをしないとタイムアウトになる制限があります。(Edge Middleware Limitations – Vercel)
Next.js v15.2 から middleware のランタイム環境で Node.js が選択できるようになりました。
これまで middleware は Edge Runtime のみサポートされていましたが、Next.js v15.2 から実験的に、middleware のランタイム環境を Edge Runtime と Node.js から選択できるようになりました。 Node.js ランタイムが選択できることで、fs
, http
など Node.js のネイティブ API が使用できるようになります。これは非常に大きな恩恵であり、早く安定版でリリースされることを期待しています。
簡単にですが、Edge Runtime から Node.js Runtime へ切り替える手順を紹介します。
移行手順
- Next.js v15.2 (canary版) 以降にアップデートします。 (Next.js 公式ブログ)
$ npx @next/codemod@canary upgrade latest
$ pnpm i next@canary
next.config.ts
に以下の設定を追加します。
module.exports = {
experimental: {
nodeMiddleware: true,
},
};
middleware.ts
の config にruntime
の設定を追加します。
export const config = {
// ...省略
runtime: 'nodejs',
};
以上です。簡単ですね!
考慮する点
Node.js のネイティブ API が使用できるようになったことで、より複雑で多くの機能を middleware を書くことができるようになりました。 その一方で、middleware が複雑であることのリスクとして、パフォーマンスの低下やリソースの消費 が伴います。
以下に、考慮すべきポイントをまとめます。
middleware はなるべくシンプルに保つ。
middleware の本質は「リクエスト/レスポンスの前処理」です。ヘッダー操作、リダイレクト、ログ出力など、シンプルな処理に留め、複雑な処理や重い処理はサーバ側へ委譲するのが無難です。 その前提で、Node.js のネイティブ API を使用する場面が発生した時のみ、Node.js Runtime を選択するようにしましょう。
適切に処理の範囲を絞る。
middleware の処理は、基本的に画像なども含めて全てのリクエストに対して毎回実行されます。リクエスト対象の絞り込みや、処理の分岐を適切に行うことで、影響範囲を必要最小限に抑えるようにしましょう。
middleware.ts の config で matcher で、対象パスのフィルタリングを行うことができます。
export const config = {
matcher: ['/about/:path*', '/dashboard/:path*'],
}
テストを徹底する
middleware でエラーが発生すると、その影響範囲はサーバ全体まで及ぼす可能性があります。 Next.js 15.1 以降、middleware の単体テストに役立つユーティリティ が用意され、 単体テストや middleware 機能全体のテストが書きやすくなっています。こちらを活用して、テストを書くようにしましょう。
パフォーマンス測定
軽量な Edge Runtime と比較して、 Node.js Runtime の使用によりパフォーマンスが低下する可能性があるため、 レスポンスタイム、メモリ使用量など、パフォーマンス指標を監視できるようにしておくと安心かもしれません。
まとめ
Next.js の middleware における Edge Runtime を紹介しました。
- 軽量で高速
- 機能が制限されている
- リソース制限がある
また、Next.js v15.2以降で実験的に Node.js Runtime を middleware で使用できることを紹介しました。 安定版へのリリースを期待しつつ、それぞれの実行環境の特徴を理解して適切に選択するための手助けになれば幸いです。
Gaji-Laboでは、 Next.js 経験が豊富なフロントエンドエンジニアを募集しています
弊社では Next.js の知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違う Gaji-Labo を味わいに来ませんか?
Next.js の設計・実装を得意とするフロントエンドエンジニア募集要項
もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!