Next.jsを使ってWebサイトのパフォーマンスを最適化する方法を考えてみる

最近周りでNext.jsを使ってる方が多くて気になっている私です。
触ってみたいな〜と思ったので勉強会とか参加してみたのでその時の記録。

とはいえ、Next.jsってなんだ???フレームワークなのは知ってるけど実際どんなことができるの??
という状態だったので、基礎的な基礎の部分というか特徴をまとめてみました。



## 高速化の歴史で辿るNext.js
サイトの高速化って大事ですよね。
表示速度遅かったらユーザー離脱しますもんね。
とはいえSSRとかSPAとか色々ありすぎてわかんないよ!!となったので
特徴とメリデメをまとめてみます。

なんたってここがNext.jsなどを開発環境に取り込むかどうかの肝になるからです。

### SPA（React / Angular / Vue.js）
SPAの特徴はユーザーがページ移動した時にページ全体を再読み込みするのではなく更新があった部分（差分）のDOMなどを置き換える方法。
差分の更新のみなのでクライアント↔︎サーバー間の負荷を減らすことができる。

<br>

**▼起用される場面**

- 業務アプリ
- 動的な画面構築

<br>

**■問題点?**
ただしクライアント側のパフォーマンス問題（Webページとスクリプトのダウンロードとレンダリングを担当するため負荷が上がる）や
初回のページ表示でパフォーマンスの問題が起きやすい。
なのでブラウザやデバイスの違いを考えることが大事。

<br>

**■開発プロセスのメリデメ**
メリット
- フレームワークもツールの幅が広い
- 自由度も高い

デメリット
- コードの追跡が難しくなる
- SEO対策：URLが変わらずページごとに固有のアドレスがないため検索エンジンがコンテンツを正しくインデックスできるようにしないといけない


### SSR（Next.js / Nuxt.js）
ウェブサーバーがレンダリングと初回のコンテンツを担当するのでJSのダウンロードや実行が完了するのを待たずに、ユーザーに対して早くレンダリングされたページを渡せる。
表示速度が最適化されるのでスムーズな体験ができる。

<br>

**■問題点?**
- Webサーバー（ブラウザの代わりにレンダリングを行わせるサーバー）を持たないとダメ
- レンダリングを2段階構成にしないといけないので複雑化する恐れも
- クライアント↔︎サーバーの間での通信が必要な場合があるので、ネットワークの遅延が問題となることも

なので、SPAの差分更新とSSRを組み合わせるのが主要な方法

サーバーサイドのレンダリングに依存するので、サーバーの負荷がめっちゃかかるかもしれないという状況が生まれるかもしれない。
これが一番怖い。

<br>

**■開発プロセスのメリデメ**
メリット
- SEO対策が簡単になる
- サーバーサイドのコードとクライアントサイドのコードを同じ言語で書ける

デメリット
- コードの追跡が難しくなるので開発が複雑化する
- ページの初回表示が遅くなることがある
- SPA同様のSEO対策が必要

<br>

### SSG（Next.js / Nuxt.js）
プリレンダリングを行う。
プレレンダリングってなんだ?ってなったので調べてみた。
あらかじめレンダリング（ビルド）を行い、静的なHTMLファイルとして生成させる。
これでリクエストが来るたびレンダリングを行う必要がなくなるという素敵な開発設計。

<br>
**▼起用される場面**
- カタログやブログなどの静的なコンテンツ

<br>

**■問題点?**
ログインページなどの作成が難しい。
ビルド時にサイト全ページが生成されるため、大規模サイトになればビルド時間がめっちゃかかるかもしれない。

**■開発プロセスのメリデメ**
メリット
- 静的なHTMLファイルとして生成されるのでウェブサイトの管理や運用が楽になる
- サーバーサイドの負荷を軽減さらにセキュリティの向上できる

デメリット
- 動的なコンテンツやユーザーの入力に応じてページを更新する必要がある場合にSSGが制限される

<br>

ここまでをざっとみるとデメリットはあるけれど、SSG良くない??って思いました。

## Reactとの違い
### React
Vue.jsの設計に焦点を当てたライブラリ。（フレームワークじゃないよ!）
データの変更を検知し、関連するコンポーネントだけを更新して描画することができる。
ReactNativeを使うことでモバイルアプリケーションを開発可能。
JSXを使用することで、HTMLの記述も使えるし変数の埋め込みや条件分岐、イベントハンドリングが可能。

コンポーネント管理とかがしやすいイメージ。
さすがUIライブラリ。

JSXを使用したReactコンポーネントはこんな感じ
```js:index.jsx
import React from 'react';

function HogeComponent(props) {
  return (
    <div>
      <h1>Hello, {props.name}!</h1>
      <p>This is a React component.</p>
    </div>
  );
}

export default HogeComponent;
```

状態管理の例↓
```js:index.jsx
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default Counter;
```

### Next.js
Reactフレームワークの一種。
Reactアプリケーション（Webアプリケーション）を構築するためのフルスタックフレームワークです。

- ルーティング
- レンダリング
- データ取得など
Reactアプリケーションの構築に関連する機能を扱え、サーバーサイドレンダリングや静的サイト生成の機能を提供しつつパフォーマンスやSEOにも優れた強者。

サーバーサイドのロジックを容易に統合できるため、APIエンドポイントの作成やデータ取得が容易なのもよし。

ページの作成とルーティングの例↓
```js:index.js
import React from 'react';

function TopPage() {
  return <h1>Welcome to Next.js!</h1>;
}

export default TopPage;
```

サーバーサイドレンダリングの例↓
```js:test.js
import React from 'react';

function TestPage({ data }) {
  return (
    <div>
      <h1>Test</h1>
      <p>{data}</p>
    </div>
  );
}

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/test');
  const data = await res.json();

  return {
    props: {
      data,
    },
  };
}

export default TestPage;
```

Next.jsはReactの機能を拡張して開発プロセスをサポートする機能が多いんだろうな。
公式サイトとかでみた例を書いてみたけどそんなに難しくはなさそう。