できるだけわかりやすくNext.jsの特徴を説明する

## はじめに
この記事ではReactとNextの違いについて扱います。

私は今の業務ではNextなどのフレームワークを使わず、ただのReactを使ってコードを書いています。
しかし、公式サイトにもあるように、フレームワークを使わないReactの開発は推奨されてはいないようです。

https://ja.react.dev/learn/start-a-new-react-project

そこで、Reactのフレームワークとしておそらく最も有名であろうNextについて、その特徴を確認していきます。

### 環境
本記事では以下を使用しています。
| ライブラリ | バージョン | 
|:-|-:|
| React | 18.2.0 |
| TypeScript | 5.2.2 |
| Next | 14.2.4|

## Nextとは
### 概要
公式サイトに書かれている説明がもっとも簡潔でわかりやすいので引用します。

> Next.js is a React framework for building full-stack web applications. You use React Components to build user interfaces, and Next.js for additional features and optimizations.

https://nextjs.org/docs#what-is-nextjs

Next.jsはフルスタックのWebアプリを作ることができるReactのフレームワークであり、UIの構築にはReactを、追加の機能や最適化にはNext.jsを使える、ということのようです。

### 特徴的な機能
公式ページではメインの機能が6つ紹介されています。

* Routing
* Rendering
* Data Fetching
* Styling
* Optimizations
* TypeScript

それぞれの機能について個別に見ていきます。

## Routing
React単体ではルーティングを行うことができません。
`react-router`というライブラリを使うことで、はじめてルーティングが可能になります。
（`react-router`については[こちらの記事](https://qiita.com/course_k/items/09483d4189edce4fbf39)を参照）

一方、Next.jsではフォルダ構成がそのままパスになります。
「app」というディレクトリがルートパスとなり、その下にあるフォルダがそのままURLのパスとして設定され、ルーティングできるようになります。
```
app/
├── layout.js
├── page.js
├── about/
│   └── page.js
├── blog/
│   ├── layout.js
│   ├── page.js
│   └── [slug]/
│       └── page.js
└── api/
    └── route.js
```
上記のようなフォルダ構成になっている場合、それぞれのフォルダ・ファイルは以下のURLに対応します。
/ ⇒ app/page.js
/about ⇒ app/about/page.js
/blog ⇒ app/blog/page.js
/blog/my-post ⇒ app/blog/[slug]/page.js

:::note warn
これはNext.jsのバージョン13から導入されたApp Routerについての説明となります。
それ以前のバージョンではPage Routerが使用されています。
:::

## Rendering
Reactはフロントエンド側の処理を書くものですが、Next.jsを使うことでサーバーサイドレンダリングの実現も可能になります。

### 動作の仕組み
ユーザーがページをリクエストすると、サーバー上でReactコンポーネントが実行されます。
サーバーがHTMLを生成し、それをクライアント（ブラウザ）に送信します。
クライアントは受け取ったHTMLを表示し、その後Reactがブラウザ上で「ハイドレーション」を行います（イベントリスナーの追加など）。


### Reactとの違い
通常のReactでは、ブラウザ上ですべてのレンダリングが行われます。
SSRでは、初期HTMLがサーバーで生成されるため、ユーザーはコンテンツをより早く見ることができます。

## Data Fetching
Next.jsはサーバーサイド、ビルド時、クライアントサイドなど、様々なタイミングでデータをフェッチできます。
また、もともとあるJavaScriptのfetchを拡張し、キャッシュと再検証の動作を設定できるようにしています。

### キャッシュについて
デフォルトで、サーバー上のData Cacheにfetchの結果を自動的にキャッシュします。
これにより、パフォーマンスが大幅に向上します。
キャッシュを使用しない場合にはオプトアウトすることもできます。

### 再検証について
データの再検証には2つの方法があります：

* 時間ベースの再検証：一定時間後に自動的にデータを再検証
* オンデマンド再検証：イベントに基づいて手動でデータを再検証

データの再検証により、静的サイト生成の利点（高速なページロード、SEOの向上）を維持しつつ、動的なコンテンツ更新の柔軟性を享受できます。

## Styling
様々なスタイリングの方法をサポートしているので、自分のプロジェクトに合った最適な方法を選ぶことができます。

以下は対応しているスタイリングの方法について、公式サイトからの抜粋して日本語に訳したものです。

https://nextjs.org/docs/app/building-your-application/styling

### グローバルCSS
従来のCSSに慣れた人にとっては使いやすく馴染みやすい方法です。
しかし、アプリケーションが大きくなるにつれてCSSバンドルが肥大化し、スタイルの管理が難しくなる可能性があります。

### CSSモジュール
ローカルにスコープされたCSSクラスを作成することで、命名の衝突を避け、保守性を向上させることができます。

### Tailwind CSS
ユーティリティファーストのCSSフレームワークで、ユーティリティクラスを組み合わせることで迅速にカスタムデザインを作成できます。

### Sass
人気のあるCSSプリプロセッサで、変数、ネストされたルール、ミックスインなどの機能でCSSを拡張します。

### CSS-in-JS
CSSをJavaScriptコンポーネント内に直接埋め込むことができ、動的でスコープされたスタイリングが可能になります。

## Optimizations
アプリケーションのパフォーマンスと開発効率をあげるための、様々な最適化機能が組み込まれています。

### 組み込みコンポーネント
画像やリンクなどのUIを最適化するためのコンポーネントが用意されています。
これにより、画像の遅延ロードやリサイズ、リンク先のページのプリフェッチ、スクリプトの読み込み制御などができるようになります。

### メタデータ
検索エンジンがWebアプリの中身をより理解できるようにするためのメタデータを設定することができます。
メタデータは設定ベースか、ファイルベースかの2つの設定方法がありますが、ここではその詳細については割愛します。

### 静的アセット
`/public`フォルダに画像やフォントなどの静的ファイルをおいておくことができます。
これらはキャッシュすることもできるため、効率的に配信することができます。

## TypeScript
Next.jsはTypeScriptを使用した開発をサポートしています。

プロジェクトの生成時、TypeScriptがデフォルトで設定されたり、AppRouteを使用することで、サーバーからクライアントのデータフローを型安全にしたりすることができます。


## まとめ
Next.jsには特徴的な6つの機能があることがわかりました。
実際の開発をまだしていないので、これらがどのように実際の実装に生きてくるのか、のイメージがまだついていませんが、大規模なアプリ開発には欠かせないものなのだろうと思いました。

しかし、一方でかなり機能が複雑であるように思ったので、小さいアプリなのであればReactだけで事足りるのかな、とも思いました。