PHPエンジニアのための Next.js 入門以前

以前 PHP エンジニア向けに、Next.js(>=13) を初めて学ぶ際、理解の助けとなることを意識しながら説明した内容をまとめました。

Next.js への理解

Next.jsは、Node.js上に構築されたオープンソースのWebアプリケーションフレームワークであり、サーバーサイドスクリプトや静的Webサイトの生成などの、ReactベースのWebアプリケーション機能を有効にする。

https://ja.wikipedia.org/wiki/Next.js

と Wikipedia にあります。上記を理解するために、少しずつ崩して言葉をとりあげていきます。

「Node.js」とは

まず、実行環境について比較的に見ていきます。

おおざっぱな考え方として JavasScript には

  • Web ブラウザ上で実行されるもの
  • サーバー上で実行されるもの

の2種類あります。少し詳しく言い変えると

  • 実行環境がWebブラウザ上、つまりクライアントサイド。Webブラウザに搭載されたJavasScriptエンジンで実行される
  • 実行環境がサーバー(コンピュータ)上、つまりサーバーサイド。Node.jsなどに搭載されたJavaScriptエンジンで実行される

という感じになります。

一つ目の方は馴染み深い、Webサイト上でリアルタイムにHTML要素を動かしたり、Ajax により動的にHTML要素を増減したりするやつです。Webブラウザに組み込まれた JSエンジンによって実行されています。

二つ目の方も実は普段から使っていて、Laravel においてSASSをコンパイルするために、laravel-mix(webpack)を実行していますが、これらはローカルコンピュータ上で実行されているものになります。Node.js(など)に組み込まれたJSエンジンによって実行されています。

以上よりNode.jsとは、コンピュータ上でJavaScriptを実行する環境・ツール、という程度の理解を持ってください。

コンピューター上で実行する、という点ではPHPと同じです。ちなみにPHPもZend Engineというエンジンによって実行されます。

WebでのJavaScriptの構文を知っていれば、PHPの構文を知らなくても動的/静的なWebサイトの構築に応用できる、と考えても良いでしょう。
※動的な、とはページごとにHTMLファイルを作っておくようなサイト(静的サイト)ではなく、アクセスしたURLやパラメータに応じてその場でHTMLデータを生成するようなサイト(動的サイト)を指しています

「Webアプリケーションフレームワーク」とは

PHPにおけるLaravelなどと同様に、Webアプリケーションを作成する上で、あらかじめ一般的な機能や処理の流れを一通り備えたツールを示します。

「ReactベースのWebアプリケーション機能」とは

ちょっと順番が前後しますが、つまり、Next.jsはReactの拡張版、みたいなことを言っています。

まずReactは何か、ざっくりいうと、ページの移動なくページのコンテンツの一部または全体を書き換える、SPA(Single Page Application)の JavaScriptライブラリの一つです。Reactのコードは独自の構文を持っており、最終的にWebのJavaScriptにコンパイルされるので、もちろんJavaScript単体でも同じことは可能です。

ここで押さえておきたいのはまず「ページの移動なく」というところです。React単体では、例えば https://example.com/article1, https://example.com/article2 のようにページごとに異なるコンテンツを表示することはできません。別途React Routerというライブラリが必要になります。
※React Routerなどのルーティング機能も、Web JavaScriptの仕様であるHistory APIを使用するので、JavaScriptのみでも実装可能です

次に押さえておきたいのは「JavaScript単体でも同じことは可能」ということです。ただしコンテンツの操作は通常のJavaScriptでは、ある程度機能ごとにまとめてあげないと、コードが煩雑になり開発や保守に手間がかかります。ReactはSPAの作成する上で、この陥りがちな煩雑さを回避するための仕組みを提供してくれているわけです。

以上から、ReactはWebブラウザにおけるJavaScriptに出来ないものを提供するものではなく、SPAを効率よく作成するためのツールである、ということがはっきりしてきたと思います。そしてNext.jsはそのSPAを効率よく作成するために提供している機能をベースとして備えているもの、と理解できます。

「サーバーサイドスクリプトや静的Webサイトの生成」とは

ここで Next.js の核心的なことが一気に出来てきました。

PHPはこのサーバーサイドスクリプトに該当します。Webサイトに接続すると、なんやかんやあって、Webサーバー上のPHPが実行され、PHPは実行結果を返し、なんやかんやあってWebサイトの表示として返しています。Next.jsでも同じことができますよ、と言っています。先ほど触れた通り、フレームワークなので、Laravelなどと同じようなことができますよ、と言っています

通常PHPの結果は、都度取得され、どこかにファイルとして保存されることなく、データのままWebサイトの結果として表示されます。ここでいう「静的Webサイトの生成」とは、あらかじめ結果を取得しHTMLファイルに保存して準備しておくこと(リクエスト毎に取得した結果を保存する場合もあります)を意味しています。Next.jsはこの「あらかじめ結果を取得しHTMLファイルに保存」する機能を標準で備えている、ということです。Laravelでも同じようなことはもちろんできますが、機能としては備えていません。

Reactが持っておらず、Next.jsが備えている機能として、今まで出てきたものを例として挙げると、React Routerによるルーティング機能や、サーバーサイドスクリプトとして実行すること、静的Webサイトを生成することなどとなります。改めてNext.jsはReactを拡張したもの(Webアプリケーションを作成する上で有用なライブラリを集めたもの=フレームワーク)、という認識がはっきりしてきました。

ここまでで意識しておきたいのは、本来ReactまたはWebのJavaScriptでは出来なかった「サーバーサイドスクリプトや静的Webサイトの生成」がNext.jsではできるようになった、という点です。なぜ出来るようになったかというと、それがサーバー上で実行されるNode.jsによる機能だからです。

すなわち、Next.jsは、React取り込むことでJavaScriptによるWebアプリケーション作成を効率化しつつ、さらにPHPのようにサーバーサイドスクリプトの挙動もサポートするもの、ということです。

このクライアントサイド・サーバーサイドの二つの側面を持つ、ということには細心の注意が必要です。Laravelなどにおけるフレームワークの認識と異なる、直接通用しないと理解してください。

以下でその辺りを見ていきます。

Next.js 上のコードはどのように利用されるのか

「クライアントサイド・サーバーサイドの二つの側面を持つ」という話をしましたが、Next.jsを利用して作成したコードがどのように利用されるのかを見ていき、その真意について触れていきます。

まず、Next.js のプロジェクトフォルダ配下は下記のような構成になっています。
※より詳細はリンク先を参照してください

app App Router
pages Pages Router
public Static assets to be served
src Optional application source folder

https://nextjs.org/docs/getting-started/project-structure

まず前提として、このプロジェクトに基づくWebサイトにアクセスしても、クライアントサイド・サーバーサイドともに、これらのフォルダ配下にあるファイルに直接アクセスすることはありません

どういうことかというと、前述の通り、ReactのコードはJavaScriptにコンパイルされます。実際にはnpm run buildなどのコマンドを実行することで指定した、git 管理していないディレクトリ(デフォルトでは.next)にコンパイルされた結果が出力されます。

Laravelなどで使用されるPHPはコンパイルしない言語(インタプリタ型言語)なので、フレームワークのディレクトリ構成そのままに、配置されたPHPファイルが読み込まれますが、React/Next.jsは効率化を提供するためにReact独自の構文を持っているため、そのままではクライアントサイドにしても、サーバーサイドにしても利用することはできません。
※ここでいうコンパイルは同じレイヤーでの変換を意図しておらず、あくまで開発者からみて表層部分を取り上げていますが、複雑になるので触れません

クライアントサイドのファイルはどれ?

クライアントサイド、つまりブラウザでサイトを開いた後に実行されるJS群の話ですが、これらは.next/static配下に設置されています。ただし、ここに配置されているのはCSSや画像、JSファイルなどのコンパイル済みのアセットファイルになるので、ページとして読み込むためにはhtmlファイルが必要です。

htmlファイルは、コンパイル時に生成された.next/server/pages/_app.js起点で動的にレンダリングされたものになります。
※SSGの場合はコンパイル時にhtmlファイルが作成されますが、ここでは触れません

ここで押さえておきたいのは、実際に参照されるクライアントサイドのJSファイルは.next/static配下のものである、ということです。

サーバーサイドのファイルはどれ?

先に触れた通り、.next/server/pages/_app.jsとなります。

Webサーバーに設置されたNode.jsは、リクエストを受けると、このファイルに従って処理を実行します。

Next.js とは

コンパイルによって、Next.jsのファイルはクライアントサイド(Web)とサーバーサイド(Node.js)のファイルに分化したことが分かりました。

ここまでくると、馴染み深いPHPフレームワークと同じような構造になっていることが分かります。例えばLaravelでは、アセットファイルをまとめるpublicディレクトリなどと、PHP処理群が含まれるappなどのディレクトリとで構成されていますが、これはまさにNext.jsのコンパイル後のフォルダ群と同じ構造を持っています。言ってみれば、PHPとNode.jsのJSとで、サーバーサイド言語を置き換えたようなものです。

しかし、先ほどディレクトリを示したように、コンパイル前は同じディレクトリ配下内に両サイドのファイルが管理されています。なぜ、Laravelなどと同様に、サーバーサイドはサーバーサイド、クライアントサイドはクライアントサイドとしてディレクトリをまとめて分けないのでしょうか。

実はこれこそがNext.jsの特徴であり、WebのJSとNode.jsのJSの記述を効率的なReact構文で記述しつつ、コンポーネントなどの恩恵を受けるための仕様となっています。

つまりNext.js とはWeb JSとNode.js JSとをReactの構文・概念で効率的に統合できるWebフレームワークなのです。