前回のおはなし
若き開発者ヒロロはNode.jsでバックエンド開発を任されたがデバッグ方法がわからず、苦戦。
自力で調査しChrome DevToolでデバッグする方法を見つけ出し、なんとかconsole.log
地獄は免れた。
しかし、普段利用しているVSCodeのデバッグツールを活用してより快適なデバッグ環境を作ろうと決意する。
前回の詳細**「console.logからの脱却 - node.jsでデバッグするには(Chrome DevTool編)」**はこちら
VSCodeでのデバッグ環境構築
公式ドキュメント(https://code.visualstudio.com/docs/editor/debugging) によればVSCodeでデバッグを有効にするにはあらかじめ設定ファイルに情報を記載する必要があるそうです。
VSCodeを起動してデバッグメニューを開き、「create a launch.json file.」をクリックします。
その後、「Node.js」の項目が出てくるので選択します。
すると、以下のようなファイルが生成されます。
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${file}"
}
]
}
requestの項目について
ここからこのファイルにデバッグ設定を記載していきますが今回の記事で重要なrequest
について。
ここにはLaunch
かAttach
のいずれかが入ります。
Launch
に設定すると、デバッグを実行したときに指定したコマンドを実行して即座にプログラムのデバッグをすることができます。
一方Aattach
に設定すると、指定したポートを監視し、コマンドプロンプトやターミナルからデバッグモードでプログラムを実行することでデバッグすることができます。
いずれかの方法でないとデバッグできないというわけではなくどちらを使っても問題はありません。
どのように設定していくかは実際にあった私の事例をもとに取り上げていきます。
A. AWS Lambdaのコードをコマンドで実行したときにデバッグしたい
serverless frameworkでサーバーレスアプリケーションを開発していた時、TDD(テスト駆動開発)を採用していたので実装したらmochaで必ずテストをする必要がありました。
その際に失敗することがありますが、原因が何なのか特定しづらいときがありました。
その時はAttachパターンを使ってデバッグを行いました。
-
launch.json
を開き、画面右下に出てくる「Add Configuration...」ボタンを押し、「Node.js:Attach」を選択する。もしくは直接以下の設定を記載する。
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 9229,
"skipFiles": [
"<node_internals>/**"
]
}
]
}
- ターミナルを開き、デバッグモードでmochaを実行する。
mocha test.js --inspect
mochaを実行すると指定したテストに紐づくコードが実行されるのでこれによって対象のコードにbreakpointを打って止めることができるようになりました。
Node.jsはデバッグポートはデフォルトで9229に設定されるので、変更する際はlaunch.json
のポート番号もそれに合わせることを忘れずに。
B. Electronのmain processをデバッグしたい
Electronでの開発ではmain process
と呼ばれるWebアプリでいうサーバーサイド的な部分があるのですが、ここでの開発では開始ボタンを押すと自動でプログラムが起動し、デバッグできるようにしたかったという背景があります。また、スムーズに開発できるようファイルを変更するとすぐさまリロードされるよう(ホットリロード)にもしたいという要望がありました。
その時はLaunchパターンを使うように設定しました。
1.事前にElectron
とElectromon
をDevDependancyでインストールする。
npm install -D electron electromon
Electromon
はホットリロードを実現するためのライブラリ。nodemon
のElectronバージョンとでも考えてればわかりやすいと思う。
2.先と同じくAdd Configuration...
ボタンからNode.js : Electron Main
を選択する。その後、"runtimeExecutable":"${workspaceFolder}/node_modules/.bin/electromon"
"args": ["--inspect=5858"]``"port": 5858``"restart": true
のプロパティを追加する。
最終的に以下のようになる。
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
// Debug settings for electron with 'electromon' so that it can be live reloaded on saving files.
// For more information about setting, visit: https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_restarting-debug-sessions-automatically-when-source-is-edited
//
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Electron Main",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electromon",
"program": "${workspaceFolder}/main.js",
"args": ["--inspect=5858"],
"port": 5858,
"restart": true,
"skipFiles": ["<node_internals>/**"],
}
]
}
3.VSCode上でデバッグ画面からRun
を押す。するとruntimeExecutable
, program
, args
の設定により
electromon --inspect=5858 main.js
が起動する。さらにファイルを編集して保存すると"restart": true
により再度デバッグが行われる。
プロセスが終了しない
ひとまずこれで設定が終わったので開発を進めていると、Electronが同時に複数起動する問題に遭遇しました。
アプリケーション終了時の挙動を確認したかったのですが、終了するとデバッグも終了してしまうため、何度も終了→デバッグ起動を繰り返しているとそのようなことになってしまいました。
ps -ef | grep electron
でプロセスを確認すると、まだプロセスが残っていたことがわかりました。どうやらアプリケーションを閉じるとデバッグも終了するがelectromonは生き続けるみたいです。
VSCode公式サイトにもこのような記載がありました。
Tip: Pressing the Stop button stops the debug session and disconnects from Node.js, but nodemon (and Node.js) will continue to run. To stop nodemon, you will have to kill it from the command line (which is easily possible if you use the integratedTerminal as shown above).
ちゃんと「デバッグは終了しますがnodemonは走り続けます」と書かれてますね...(こちらはnodemonですがelectromonと置き換えても問題ありません)
・electronを終了するとデバッグも終了してしまう
・デバッグが終了してもelectromonは走り続ける
ということからアプリを終了するたびに手動でelectromonも止めないといけないということですね。
ご親切にintegrationTerminal
を設定すると簡単にプロセスの終了ができますと書いてくれてましたのでそれに合わせてlaunch.json
に
"console" : "integrationTerminal"
を追記してみました。
起動すると、VSCodeのターミナルにelectromonのコンソールが立ち上がるようになりました。
プロセスを終了する際はこのターミナルを終了してくださいということですね。
まとめ
これでVSCodeを使ってNode.jsをデバッグできるようになり、しかもそれぞれの利用シーンに応じてAttach
パターンとLaunch
パターンを使い分けることができるようになりました。
あれからしばらく経ちましたがもうデバッグで悩むことがほとんどなくなりました。もうNode.jsでもconsole.log地獄に悩まされなくてすみそうです。