Next.js を VisualStudioCode(VSCode)を使ってデバッグする方法

## 概要
フロントエンドにNext.jsを採用して開発を進めた際、そのデバッグの設定に少々手間取ったため、ここに備忘録として残しておきます。

ここではNext.jsのサーバーサイド、クライアントサイド双方のデバッグ環境を整えて行きます。


## 環境

Windows11, WSL2
```
❯ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
```

Visual Studio Code (VSCode)
```
Version: 1.79.2
```

node.js
```
❯ node --version
v16.17.0
❯ npm --version
8.15.0
```

Next.js
```
❯ cat package.json | grep next
"next": "13.2.4",
```


# サーバーサイドデバッグについて

Next.jsはReactベースのフレームワークであり、クライアントサイドとサーバーサイドの両方のレンダリングをサポートしています。この為それぞれの領域におけるデバッグシステムの構築をしなければいけません。

ここではまずサーバーサイドのレンダリング時におけるデバッグの方法を記します。



## 各種設定

:::note
$project_dirはNext.jsプロジェクトを配置したディレクトリとして以下表記しています。
:::

### package.json の設定

まず、こちらのファイルにNext.jsをDebugモードで立ち上げるためのスクリプトを設定します。
$project_dir/package.jsonの"scripts"要素の中に"dev"や"start"が既に設定されていたりすると思いますが、ここに"debug"という項目を下記のように追加します。

```json:$project_dir/package.json
"debug": "NODE_OPTIONS='--inspect' next dev"
```


### .vscode/launch.json の設定

次に、$project_dir/.vscode/launch.jsonに以下の設定を追加します。
.vscode/launch.json がない場合はファイルを作成してください。

```json:$project_dir/.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Nextjs: Server",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "port": 9229
    }
  ],
}
```

### ブレイクポイントの設定

ここまで設定が終わったら、ひとまずソースコードの中にブレイクポイントを設定します。

サーバーサイドレンダリング時のコードでのデバッグの確認のため、getServerSideProps()の中にブレイクポイントを置きます。

![server1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/c7bc0d00-1c5d-5373-5d63-26e867f6660b.png)


### Next.jsの起動

ターミナルを開いて```npm run debug```コマンドでNext.jsを起動します。

![server3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/9bcbfcb9-af83-a1b8-be98-837c9d4c2ea2.png)

### VSCodeのDebuggerの起動

次に、VSCodeのDebugアイコンをクリックして、先程設定したlaunch.jsonの"Next.js Server"設定を使って、デバッガーを起動します。

![server5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/06928138-b7e7-aa7e-b1c3-a75c9cff859a.png)

するとNext.jsを起動しているターミナルに Debugger attached.のログが流れます。（大事なことなので2度言うスタイル）

![server4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/5549a3a8-8a2d-2403-0523-cd97927b49d6.png)

### ブレイクポイントの動作の確認

これが確認できれば、先程ブレイクポイントを設定したコードの部分を走らせます。

ブレイクポイントでコードが停止すれば成功です。

![server2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/b32a237e-e0d3-87fa-d75f-020947843bf9.png)


# クライアントサイドデバッグについて

サーバーサイドデバッグと概ね同じ流れとなります。

## 各種設定

### .vscode/launch.json の設定

先程の$project_dir/.vscode/launch.jsonに、今度はクライアントサイドのデバッグ用に以下の設定を追加します。

```json:$project_dir/.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Next.js Client",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}"
    }
  ],
}
```

先程のサーバーサイドの設定と合わせると全体で以下のようになります。

```json:$project_dir/.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      // client side debug
      "type": "chrome",
      "request": "launch",
      "name": "Next.js Client",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}"
    },
    {
      // server side debug
      "type": "node",
      "request": "attach",
      "name": "Nextjs: Server",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "port": 9229
    }
  ],
}
```

ちなみに上記ではクライアントサイドのデバッグ時のブラウザを```"type": "chrome"```と設定しています。私の環境がChromeを使っているからなのですが、お手元の環境にChromeがない場合はここを変更する必要があると思います。


### ブレイクポイントの設定

今回はクライアントサイドレンダリング時でのブレイクの確認なので、NextPageの関数定義の内部にブレイクポイントを設定します。

![client2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/a33c5231-0889-47f0-1ede-85c6ad94c950.png)


### Next.jsの起動

ターミナルを開いて```npm run dev```コマンドで普通にNext.jsを起動します。

![client5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/4f8eed5c-e7a8-bb23-68f0-3aebad8754be.png)


### VSCodeのDebuggerの起動

次に、VSCodeのDebugアイコンをクリックして、先程設定したlaunch.jsonの"Next.js Client"設定を使って、デバッガーを起動します。

![client1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/14a01cdf-fe64-560d-2e6f-a522f16e94d5.png)

すると既にlocalhost:3000に接続されたデバッグ用ブラウザが新たに開きます。

この状態で上記で設定したブレイクポイントを通るコードを走らせると、プログラムがブレイクポイントで停止します。

![client4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3249097/8f07f4b3-fc90-e975-8820-5c2df63075eb.png)


# サーバーサイドとクライアントサイド、どちらの領域でもブレイクポイントを作動させる

上記においては、サーバーサイド、クライアントサイド、別々にデバッグ方法を説明しましたが、両方同時にデバッグしたいこともあると思います。

その場合には以下の手順を踏みます。

1. ```npm run debug```でNext.jsを起動する
1. VSCodeのデバッグ機能からNext.js Serverを実行する
1. VSCodeのデバッグ機能からNext.js Clientを実行する

これで、サーバーサイド、クライアントサイド、どちらのブレイクポイントでもプログラムはブレイクするようになります。


# 終わりに

Next.jsのデバッグの方法、なかなか複雑かつウェブ上にも断片的な情報しかない場合が多くて、上手くいくまで時間がかかってしまいました。

一応上記の方法で上手く行くことが再現できたので、私的ベストプラクティスとして公開しますが、おそらくもっと簡単な方法もあるんじゃないかなという気もします。。

もし、もっといい方法があるよ！とご存知の方いらっしゃれば、教えていただけると幸いです。

# 追記 2024年3月18日

saint_seino氏より、

:::note info
下記にてもっといいやり方があったので掲載しておきます。
https://nextjs-ja-translation-docs.vercel.app/docs/advanced-features/debugging
:::

というご連絡を受けたので共有いたします。
どうもありがとうございます・・！