Next と React は結構違います!

記事
IT・テクノロジー

Next と React は結構違います!

Next は React で利用している、仮想 DOM を活用しているので似ている部分も多いのですが、設計の仕方は結構違う所もたくさんあります。React の場合、React Router を使うと「ページ」という概念での設計も可能ですが、基本的には、「1ページアプリ」の要素の方が強くなっています。 一方で、Next の場合は、サーバー側で「ページを用意する」というイメージで動作するので、設計は基本的にはページ単位ですることになります。

Next の基本的なコンセプトは「ページ」

Next で Web アプリや Web サイトを設計する場合、ページ単位での実装を考えると上手くまとめる事ができます。 もちろん、同じページで Web ブラウザ側でレンダリング(描画)する事もできるのですが、別の画面にする場合は、ページごと入れ替えてしまった方が設計上はシンプルでスッキリした実装になります。Web ブラウザで表示を動的に変えるような実装の場合、React などのフロントエンドのフレームワークを中心に作った方が実装もスッキリします。

Next でページを設計する上で考えることは、「いつ」ページを作るかです。

「いつ」とはどういうことかというと、大きく分けると2つです。

* Next の公開用のイメージを作る時
* Web ブラウザがリクエストした時
最初にすることは、Web アプリや Web サイトで必要なページがどちらのタイプなのかを分類する事が最初の作業になります。

基準はシンプルで、同じ画面を表示する場合は、Next の公開用のイメージを作成する際に作って仕舞えば、リクエスト時はその情報を Web ブラウザに提供するだけなので高速に表示が可能です。例えば、入力フォームなどは、予め作成しておく事が可能です。

一方で、表示画面が変わる場合は、Next の公開イメージを作成する際にはページを作る事ができないので、Web ブラウザがリクエストした際に、動的にサーバー側でページを作ることになります。例えば、データベースのデータを取得して表示する場合などは、表示する内容が変わるので動的にページを作る必要があります。ブログなどの場合も、ブログの原稿を投稿してそれを表示するような場合は動的にページを作る必要がある場合が多くなります。例えば、投稿は Markdown で記述されていて、投稿データを Next のイメージを作り直すことなしに表示するようなサービスの場合は、Next の公開イメージ作成時にはブログのデータはないので、投稿された原稿を変換してページを作るのは事後の作業になります。

ページに必要なデータの処理のやり方で動作が変わる!
次に考えるのが、ページに必要なデータは何かという事です。フロントエンドでレンダリングする場合は、Web ブラウザがページを読み込む際に、必要な Javascript のプログラムも読み込んで、Javascript を利用してレンダリングするので、ページに必要なデータを Javascript から取得することも可能です。

Next でも、同じような処理も可能ですが、通常は、サーバーがページを作る前に、サーバー側でデータを取得する作り方をする場合が多くなります。そもそも、Next を選択する大きな理由はサーバー側でレンダリング(描画)するのが目的なので、殆どの場合は、データ処理もサーバー側で行う作りにする方が多くなります。

この処理は、Next の場合、「getServerSideProps()」という関数を使って処理します。この関数は、Next がページを作成する前に呼び出されて、必要なデータを取得したりデータの処理を行ってページの作成(レンダリング)に必要なデータを渡す役割をしています。この関数を使ってページを作成する場合は、Web ブラウザがリクエストした際に動的にサーバー側でページが作られます。 この関数が返す値が、React のコンポーネントにプロパティとして渡されます。

一方で、「getServerSideProps()」の代わりに、「getStaticProps()」を使ってデータを取得したりデータの処理を行う場合は、ページは Next の公開イメージを作成(ビルド)する際の作られます。つまり、「getStaticProps()」はビルド時にしか呼ばれない関数ということになります。(デバッグ環境の場合は、ページの生成は動的に行っているのでどちらを利用しても見た目には同じです)

ページの切り替えは?
Next で Web アプリや Web サイトを作る場合、ページの切り替えは、Web ブラウザで URL を指定する以外にも必要な場合があります。 その場合のページの切り替えは、リンクなどのように、次に表示するページの URL を指定する形で行えます。

その場合、ページを切り替える前に次に表示するページにデータを渡すこともできます。例えば、名簿のような形で名前のリストを表示するページがあるとします。その中の一人をクリックなどで選択した場合に、選択された人の詳細情報(住所や電話番号など)を表示する画面に切り替える場合を考えます。もちろん、ブラウザー側でレンダリング(描画)するという方法もありますが、別のページをサーバにリクエストするという方法の方が、Next を利用する場合は便利です。その際、選択した人の ID を URL に含めて(クエリーパラメータ)渡せば、サーバー側でデータを取得して詳細データを表示するページが作れます。

このような場合、フロントエンドで処理する場合は、選択(ボタンのクリックなど)のイベント処理で、選択された人を特定してデータを取得して、表示を書き換えるという動作が一般的ですが、Next の場合、リンクに ID を含めておけば、Javascript なしでもページの切り替えができます。

フロントエンドのフレームワークは Web ブラウザで Javascript が有効になっていないと動作しませんが、Next でサーバー側に処理を集めれば、Javascript が有効になっていない場合でも Web アプリや Web サイトが機能するという利点があります。

ブラウザ内で処理をする場合は?
Next でもブラウザ側で処理を行うことは可能です。Firebase などの機能も React と同様に Web ブラウザから呼び出してデータを処理する事も可能です。しかし、Next で Firebase を使う場合は、Firebase のアクセスはサーバー側に一本化した方がスッキリとした実装になるため、管理もしやすく便利です。その場合は、Next では、サーバー側に処理をリクエストする API を使う機能があるので、これを利用して、サーバー側で処理する設定にできます。Next のプロジェクトを「create-next-app」でテンプレートのプロジェクトを作成すると「pages/api/hello.js」という API のサンプルが作られているので、これを元に必要な API を追加して処理をコーディングするとブラウザでのデータの処理や簡単なレンダリングも行う事ができます。

フォームのデータも URL にクエリパラメータを付加してデータを送る場合は、API の利用は不用ですが、HTTP の POST メソッドなどを使いたい場合は、API でサーバー側にデータを渡す仕組みが必要になります。

Next のフレームワークは「サーバー側のレンダリングのフレームワーク」と言われていますが、実際は、フロントエンドとバックエンドが混在する形のフレームワークになっています。使いこなすには、Next の中での動作の関係をきちんと理解していないと実装が難しい側面があります。

全部 Javascript で書かれているので、区別がしにくいのですが、どの部分のプログラムがサーバー側で動いて、どの部分のプログラムが Web ブラウザで動くかがきちんと把握されていないと、全体をまとめるのが難しくなります。上で説明している API は、同じように書かれていますが、ネットワークを介して、サーバー側で動作する部分になります。

まとめ
Next と React は似ているように見えますが、実は中身は別の物です。 React は全てのコードが Web ブラウザ上で実行されるので、あまりバックエンドや HTTP の知識がなくても十分に使いこなすことも可能ですが、Next の場合は、Web ブラウザ上で実行されるコードと、サーバー(バックエンド)側で実行されるコードが混在しているので、プログラムがどこでいつ実行されるかを理解していないと使いこなすのが難しい側面があります。

Next の実装は最初は、できるだけシンプルにページをベースにした実装で、Web ブラウザ側の処理を最小限にするような形で設計した方が、Next の理解が深まります。その上で、全体のバランスを見ながら Web ブラウザ側の処理を割り当てるように作るとスムーズに進む場合が多いかと思います。

簡単にどこで実行されているかを、見分ける方法は、「console.log()」でメッセージを出してみると簡単にわかります。Web ブラウザの開発ツールで出る部分は、基本的にブラウザ上で動いていますし、Next のデバッグサーバーを起動したシェル(コマンドライン)に表示される部分はサーバー側で動いているという事です。これをヒントに実行の流れを追いかけると仕組みが分かってきます。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す