🦄

[Next.js] Next.js 実行環境の性質まとめ

に公開

はじめに

独習JavaScript本を読んでいて、JavaScriptの実行環境の説明がされていた。
「WebブラウザとNode.jsの2つがあって、それらは別の特徴を持つよ」と説明されており、「Next.jsの場合はどういう仕組みになっているんだろう?」と気になったので、調べることにした。
以降Next.jsv15.3.4のドキュメントを参照している。

前提1: JavaScriptの実行環境

ブラウザ環境、サーバサイド用環境に大別される。

ブラウザ環境

クライアント用の環境。

  • ブラウザの構成: JavaScriptエンジン, DataStorage, User Interface (GUI)などから構成される。
    • 構成要素(※): UserInterface, Data Storage, Browser Engine, Rendering Engine, JavaScript Engine, Network, UI Background
  • JavaScriptエンジン: JavaScriptコードを解析して実行するためのインタプリタ。
    • V8 (Chrome), JavaScriptCore(Safari)など。
    • ブラウザごとに、搭載されたエンジンが異なる。
  • ECMAScriptに加えてWebAPIが使える。
    • ECMAScript: プログラミング言語仕様。JavaScriptはECMAScriptに準拠している。ECMA-262とも表記される。
  • Web API:JavaScriptコードからブラウザを操作するためのAPI。
    • DOMの操作やWindowオブジェクト、localStorage, sesisonStorageへのアクセスなど。
    • ブラウザ操作の用途なので、後述のサーバサイド用環境では使えない。

※以下の解説の図解が詳しかった。
https://web.dev/articles/howbrowserswork?hl=ja

ブラウザで動作するJavaScript

サーバサイド用環境

Node.jsが有名。DENO,BUNなどもある。

  • Node.js: JavaScriptエンジンはV8を搭載。
    • Node.jsは実行環境の名前。React.jsライブラリやVue.jsフレームワークといった、「JavaScriptのコードの集まり」とは明確に役割が異なる。
    • Node.jsのフレームワークでは「Express」が有名。
  • ECMAScriptの他にCommonJSも使える。
    • Date,Mathなどの組み込みオブジェクトは、ECMAScriptの言語仕様に含まれているため、Node.js環境でも使える。
    • CoomonJSではファイル操作用のfsモジュールの他、crypto,process,os,streamなど多くの組み込みモジュールがある。

以下の記事が図解で大変詳しかった。
https://ask-nugey.com/posts/javascript-runtime

Node.jsで動作するJavaScript

前提2: Next.jsの概念

component

Client Component, Server Componentに大別される。

  • Client Component: 従来のブラウザ環境。WebAPIの使用、useStateなどの状態管理が行える。
  • Server Component: サーバサイドでHTMLをレンダリングしてブラウザに渡す。処理が高速で、機密情報を含む操作も行える。

↓使い分けの詳細は以下参照。
https://ja.next-community-docs.dev/docs/app/building-your-application/rendering/composition-patterns

Server Component⇔API

Server/Client Componentでレンダリングの順が異なるので、API呼び出しを例にとって記載。
Server Component経由でAPIを呼び出した場合の処理。
API実行後、取得したデータも含めてから、HTMLを生成している。

Client Component⇔API

Client Component経由でAPIを呼び出した場合の処理。
一度ブラウザで画面をレンダリングした後で、APIを実行して、データを取得・反映している。

middleware

すべてのルートに対して必ず実行される。リクエスト実行前に必ず中継する。
https://nextjs.org/docs/app/api-reference/file-conventions/middleware

本題: Next.jsの実行環境

runtime

それぞれの実行環境は以下。

  • Client Side: ブラウザ環境を使用。
    • Server ComponentからClient Componentをimportして呼び出すことはできる。importしたClient Componentの実行はブラウザ側で行われる。
    • Client Component内で、Server Componentをimportはできない。(Hydration Errorになる)
  • Server Side: Node.js環境を使用。
    • Server Component, Server Actions, Route Handler (API)
    • Server Actionsは別ファイルに定義することで、Server Component, Client Componentどちらからでも呼び出せる。(厳密には内部処理が異なるらしいが、結果的にどちらでも参照できる。)
  • middleware: Edge Runtimeを使用。
    • Edge Runtime →Node.jsベースだが、軽量な代わりに一部機能を制限したruntime。
    • request, response, fetchなどが使える。
    • fs,process,osなどは使えない。cryptoは一部のWebCrypto APIが使えるが、Node.jsのcryptoモジュールは非対応。
    • 軽量化を実現するために、重い処理の使用を意図的に制限している。
    • v15.2以降は設定を追加することで、Node.js runtimeが実験的に使えるようになったらしい。

↓middlewareの実行環境、Node.js runtimeが使えるかについては以下の記事が詳しかった。
https://www.gaji.jp/blog/2025/03/28/22690/?cta=b

↓middlewareで動作するAPIは以下参照。
https://nextjs.org/docs/pages/api-reference/edge

build

  • 開発環境: localサーバでnext devで起動する。
    • リアルタイムでコード解析してコンパイルする。ライブ感。
    • ビルド不要で動作するが、コードの増加につれて、サーバの動作が重くなる。
  • 検証/本番環境: next buildでビルドし、デプロイする。
    • ビルド時に、Client/Server/middlewareの実行環境別に振り分ける。
    • ビルド時に分離・最適化を行うことで、動作が高速になる。

↓以下の「Local dev vs. production」項目にて言及されていた。
https://nextjs.org/docs/app/guides/local-development

ローカル開発環境と本番環境 next devの開発プロセスは、next buildやnext startとは異なります。next devは、アプリケーション内のルートを開いたり移動したりするたびにコンパイルします。 これにより、アプリケーション内のすべてのルートがコンパイルされるのを待つことなく開発サーバーを起動できます。 productionビルドを実行すると、ファイルの最小化やコンテンツハッシュの作成など、ローカル開発では不要な他の最適化が適用されます。

まとめ

  • ブラウザはGUIの他にエンジン各種やストレージ、NWなどから構成されている。
  • JavaScriptの実行環境として、ブラウザ側とサーバ側に大別される。
  • ブラウザ側は ECMAScript+WebAPI, Node.js側はECMAScript+CommonJSが使われている。
  • WebAPIはブラウザのWindow、DOM、Storage等を操作できるAPI。Serverでは使えない。
  • Next.jsでは Clientがブラウザ、ServerがNode.js、middlewareがEdge Runtimeが使われている。
  • Edge Runtimeでは軽量な動作の代わりに、Node.jsでのファイル操作・プロセス制御など重い処理のmoduleが使えない。
  • ローカルの開発環境ではリアルタイムでコード解析・実行環境別に振り分けられている。
  • 検証・本番環境にデプロイする場合はビルド時に分離・最適化が行われ、高速な動作になる。またServer SideのコードがClient(ブラウザ側)に露出しないことが保証される。

最後に

JavaScriptの本質を理解するためには、ECMA Script言語仕様、runtime、ブラウザ構成など構造や背景の理解は必須だと思った。
Next.jsはruntimeを使い分けているから、ClientとServer側の処理を実装できるのだとわかった。

Next.jsはcacheが重要だとよく言われる。runtimeが「どこでコードが実行されるか」、cacheが「どこで結果を保存・再利用するか」なので、どのruntimeで実行されるかによって、cacheの戦略が変わる。

両者は連携してアプリのパフォーマンスを最適化しているため、cacheについても挙動を理解して、記事にまとめたい。

参考情報

Document

Next.js v15.3.4のドキュメントを参照している。

Blog

Book

Discussion