VS CodeでのNode.jsデバッグ
Visual Studio Codeエディターは、Node.jsランタイムのデバッグを組み込みでサポートしており、JavaScript、TypeScript、およびJavaScriptにトランスパイルされる他の多くの言語をデバッグできます。VS Codeが適切な起動構成のデフォルト値とスニペットを提供するため、Node.jsデバッグ用のプロジェクトのセットアップは簡単です。
VS CodeでNode.jsプログラムをデバッグするには、いくつかの方法があります
- VS Codeの統合ターミナルで実行するプロセスをデバッグするには、自動アタッチを使用します。
- 統合ターミナルを使用するのと同様に、JavaScriptデバッグターミナルを使用します。
- プログラムを起動するには起動構成を使用するか、VS Codeの外部で起動されたプロセスにアタッチします。
Auto Attach
自動アタッチ機能が有効になっている場合、NodeデバッガーはVS Codeの統合ターミナルから起動された特定のNode.jsプロセスに自動的にアタッチします。この機能を有効にするには、コマンドパレットから自動アタッチの切り替えコマンドを使用する (⇧⌘P (Windows, Linux Ctrl+Shift+P))か、すでにアクティブになっている場合は、ステータスバーの自動アタッチ項目を使用します。
自動アタッチには3つのモードがあり、結果のクイックピックで、またはdebug.javascript.autoAttachFilter設定を介して選択できます
smart
-node_modules
フォルダーの外でスクリプトを実行したり、mochaやts-nodeのような一般的な「ランナー」スクリプトを使用したりする場合、プロセスはデバッグされます。「ランナー」スクリプトの許可リストは、Auto Attach Smart Pattern設定 (debug.javascript.autoAttachSmartPattern
) を使用して構成できます。always
- 統合ターミナルで起動されたすべてのNode.jsプロセスがデバッグされます。onlyWithFlag
---inspect
または--inspect-brk
フラグで起動されたプロセスのみがデバッグされます。
自動アタッチを有効にした後、ターミナル右上隅の⚠アイコンをクリックするか、新しいターミナルを作成してターミナルを再起動する必要があります。その後、デバッガーは1秒以内にプログラムにアタッチされるはずです。
自動アタッチがオンの場合、VS Codeウィンドウ下部のステータスバーに「自動アタッチ」項目が表示されます。これをクリックすると、自動アタッチモードを変更したり、一時的にオフにしたりできます。一時的に自動アタッチをオフにするのは、デバッグが必要ない一度限りのプログラムを実行する場合に便利ですが、機能を完全に無効にしたくない場合です。
追加の構成
その他の起動構成プロパティ
通常はlaunch.jsonにある他のプロパティを、debug.javascript.terminalOptions設定で自動アタッチに適用できます。例えば、ノードの内部をskipFilesに追加するには、ユーザー設定またはワークスペース設定に以下を追加できます
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**"
]
},
自動アタッチ スマートパターン
smart
自動アタッチモードでは、VS Codeはあなたのコードにアタッチしようとし、デバッグに興味のないビルドツールにはアタッチしません。これは、メインスクリプトをグロブパターンのリストと照合することで行われます。グロブパターンは、debug.javascript.autoAttachSmartPattern設定で構成可能であり、デフォルトは次のとおりです
[
'!**/node_modules/**', // exclude scripts in node_modules folders
'**/$KNOWN_TOOLS$/**' // but include some common tools
];
$KNOWN_TOOLS$
は、ts-node
、mocha
、ava
などの一般的な「コードランナー」のリストに置き換えられます。これらの設定が機能しない場合は、このリストを変更できます。例えば、mocha
を除外し、my-cool-test-runner
を含めるには、2行を追加できます
[
'!**/node_modules/**',
'**/$KNOWN_TOOLS$/**',
'!**/node_modules/mocha/**', // use "!" to exclude all scripts in "mocha" node modules
'**/node_modules/my-cool-test-runner/**' // include scripts in the custom test runner
];
JavaScript Debug Terminal
自動アタッチと同様に、JavaScriptデバッグターミナルは、その中で実行するすべてのNode.jsプロセスを自動的にデバッグします。コマンドパレットからDebug: Create JavaScript Debug Terminalコマンド (kbs(workbench.action.showCommands)
) を実行するか、ターミナルスイッチャーのドロップダウンからCreate JavaScript Debug Terminalを選択することで、デバッグターミナルを作成できます。
追加の構成
その他の起動構成プロパティ
通常launch.jsonにある他のプロパティを、debug.javascript.terminalOptions設定でデバッグターミナルに適用できます。例えば、Nodeの内部をskipFilesに追加するには、ユーザー設定またはワークスペース設定に以下を追加できます
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**"
]
},
起動構成
起動構成は、VS Codeでデバッグを設定する従来のM方法であり、複雑なアプリケーションを実行するための最も多くの構成オプションを提供します。
このセクションでは、より高度なデバッグシナリオのための構成と機能について詳しく説明します。ソースマップ、外部コードのステップオーバー、リモートデバッグなど、デバッグの手順を見つけることができます。
入門ビデオをご覧になりたい場合は、VS Codeでのデバッグの始め方をご覧ください。
注: VS Codeを初めて使用する場合は、一般的なデバッグ機能と
launch.json
構成ファイルの作成について、「デバッグ」のトピックで学ぶことができます。
起動構成属性
デバッグ構成は、ワークスペースの.vscode
フォルダーにあるlaunch.json
ファイルに保存されます。デバッグ構成ファイルの作成と使用については、一般的なデバッグの記事で紹介しています。
以下は、Node.jsデバッガーに固有の一般的なlaunch.json
属性のリファレンスです。オプションの完全なセットは、vscode-js-debugオプションのドキュメントで確認できます。
次の属性は、タイプlaunch
およびattach
の起動構成でサポートされています
outFiles
- 生成されたJavaScriptファイルを検索するためのグロブパターンの配列。セクションソースマップを参照してください。resolveSourceMapLocations
- ソースマップを解析する場所のグロブパターンの配列。セクションソースマップを参照してください。timeout
- セッションの再起動時に、このミリ秒数を超えたらあきらめます。セクションNode.jsへのアタッチを参照してください。stopOnEntry
- プログラム起動時にすぐにブレークします。localRoot
- VS Codeのルートディレクトリ。以下のセクションリモートデバッグを参照してください。remoteRoot
- Nodeのルートディレクトリ。以下のセクションリモートデバッグを参照してください。smartStep
- ソースファイルにマッピングされないコードを自動的にステップオーバーしようとします。セクションスマートステップを参照してください。skipFiles
- これらのグロブパターンに該当するファイルを自動的にスキップします。セクション関連のないコードをスキップするを参照してください。trace
- 診断出力を有効にします。
これらの属性は、リクエストタイプlaunch
の起動構成でのみ使用できます
program
- デバッグするNode.jsプログラムへの絶対パス。args
- デバッグするプログラムに渡される引数。この属性は配列型であり、個々の引数を配列要素として期待します。cwd
- このディレクトリでデバッグするプログラムを起動します。runtimeExecutable
- 使用するランタイム実行可能ファイルへの絶対パス。デフォルトはnode
です。セクション「npm」およびその他のツールに対する起動構成のサポートを参照してください。runtimeArgs
- ランタイム実行可能ファイルに渡されるオプションの引数。runtimeVersion
- 「nvm」(または「nvm-windows」)または「nvs」がNode.jsバージョンの管理に使用されている場合、この属性を使用して特定のNode.jsバージョンを選択できます。以下のセクション複数バージョンサポートを参照してください。env
- オプションの環境変数。この属性は、文字列型のキー/値ペアのリストとして環境変数を期待します。envFile
- 環境変数定義を含むファイルへのオプションのパス。以下のセクション外部ファイルから環境変数をロードするを参照してください。console
- プログラムを起動するコンソール (internalConsole
、integratedTerminal
、externalTerminal
)。以下のセクションNodeコンソールを参照してください。outputCapture
-std
に設定されている場合、デバッグポートを介して出力をリッスンする代わりに、プロセスのstdout/stderrからの出力がデバッグコンソールに表示されます。これは、console.*
APIを使用する代わりにstdout/stderrストリームに直接書き込むプログラムやログライブラリに役立ちます。
この属性は、リクエストタイプattach
の起動構成でのみ使用できます
restart
- 終了時に接続を再起動します。セクションデバッグセッションの自動再起動を参照してください。port
- 使用するデバッグポート。セクションNode.jsへのアタッチおよびリモートデバッグを参照してください。address
- デバッグポートのTCP/IPアドレス。セクションNode.jsへのアタッチおよびリモートデバッグを参照してください。processId
- デバッガーはUSR1シグナルを送信した後、このプロセスにアタッチしようとします。この設定により、デバッガーはデバッグモードで起動されていない既に実行中のプロセスにアタッチできます。processId
属性を使用する場合、デバッグポートはNode.jsバージョン(および使用されているプロトコル)に基づいて自動的に決定され、明示的に構成することはできません。したがって、port
属性は指定しないでください。continueOnAttach
- プロセスにアタッチしたときに一時停止している場合に、プロセスを続行するかどうか。このオプションは、--inspect-brk
でプログラムを起動する場合に便利です。
一般的なシナリオの起動構成
launch.json
ファイルでIntelliSense (⌃Space (Windows, Linux Ctrl+Space)) をトリガーして、よく使用されるNode.jsデバッグシナリオの起動構成スニペットを表示できます。
launch.json
エディターウィンドウの右下にある構成の追加...ボタンを使用して、スニペットを表示することもできます。
以下のスニペットが利用可能です
- プログラムの起動: Node.jsプログラムをデバッグモードで起動します。
- npm経由で起動: npmの「デバッグ」スクリプトを介してNode.jsプログラムを起動します。package.jsonに定義されている場合、起動構成からnpmデバッグスクリプトを使用できます。npmスクリプトで使用されるデバッグポートは、スニペットで指定されたポートに対応している必要があります。
- アタッチ: ローカルで実行中のNode.jsプログラムのデバッグポートにアタッチします。デバッグするNode.jsプログラムがデバッグモードで起動されており、使用されているデバッグポートがスニペットで指定されたものと同じであることを確認してください。
- リモートプログラムにアタッチ:
address
属性で指定されたホストで実行されているNode.jsプログラムのデバッグポートにアタッチします。デバッグするNode.jsプログラムがデバッグモードで起動されており、使用されているデバッグポートがスニペットで指定されたものと同じであることを確認してください。VS Codeがワークスペースとリモートホストのファイルシステム間のソースファイルをマッピングできるようにするには、localRoot
とremoteRoot
属性に正しいパスを指定してください。 - プロセスIDでアタッチ: プロセスピッカーを開いて、デバッグするNodeまたはgulpプロセスを選択します。この起動構成では、デバッグモードで起動されていないNodeまたはgulpプロセスにもアタッチできます。
- Nodemonセットアップ: JavaScriptソースが変更されるたびに、nodemonを使用してデバッグセッションを自動的に再起動します。nodemonがグローバルにインストールされていることを確認してください。デバッグセッションを終了しても、デバッグ対象のプログラムは終了しますが、nodemon自体は終了しないことに注意してください。nodemonを終了するには、統合ターミナルでCtrl+Cを押します。
- Mochaテスト: プロジェクトの
test
フォルダーにあるmochaテストをデバッグします。プロジェクトのnode_modules
フォルダーに「mocha」がインストールされていることを確認してください。 - Yeomanジェネレーター: yeomanジェネレーターをデバッグします。スニペットはジェネレーターの名前を指定するように求めます。プロジェクトの
node_modules
フォルダーに「yo」がインストールされており、プロジェクトフォルダーでnpm link
を実行して生成されたプロジェクトがデバッグ用にインストールされていることを確認してください。 - Gulpタスク: gulpタスクをデバッグします。プロジェクトの
node_modules
フォルダーに「gulp」がインストールされていることを確認してください。 - Electron Main: ElectronアプリケーションのメインNode.jsプロセスをデバッグします。このスニペットは、Electron実行可能ファイルがワークスペースの
node_modules/.bin
ディレクトリ内にインストールされていることを前提としています。
Nodeコンソール
既定では、Node.jsデバッグセッションは内部のVS Codeデバッグコンソールでターゲットを起動します。デバッグコンソールはコンソールから入力を読み取る必要があるプログラムをサポートしないため、起動構成のconsole
属性をそれぞれexternalTerminal
またはintegratedTerminal
に設定することで、外部ターミナルを有効にするか、VS Code統合ターミナルを使用できます。既定値はinternalConsole
です。
外部ターミナルでは、terminal.external.windowsExec
、terminal.external.osxExec
、およびterminal.external.linuxExec
の設定を介して、使用するターミナルプログラムを構成できます。
「npm」およびその他のツールに対する起動構成のサポート
Node.jsプログラムをnodeで直接起動する代わりに、起動構成から「npm」スクリプトやその他のタスクランナーツールを直接使用できます。
runtimeExecutable
属性にはPATHで利用可能な任意のプログラム(例: 'npm'、'mocha'、'gulp'など)を使用でき、引数はruntimeArgs
を介して渡すことができます。- npmスクリプトやその他のツールが起動するプログラムを暗黙的に指定している場合、
program
属性を設定する必要はありません。
'npm'の例を見てみましょう。package.json
に「debug」スクリプトがある場合、例えば
"scripts": {
"debug": "node myProgram.js"
},
対応する起動構成は次のようになります
{
"name": "Launch via npm",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "debug"]
}
複数バージョンサポート
Node.jsバージョンの管理に「nvm」(または「nvm-windows」)を使用している場合、特定のNode.jsバージョンを選択するためのruntimeVersion
属性を起動構成に指定できます。
{
"type": "node",
"request": "launch",
"name": "Launch test",
"runtimeVersion": "14",
"program": "${workspaceFolder}/test.js"
}
Node.jsバージョンの管理に「nvs」を使用している場合、runtimeVersion
属性を使用して、特定のバージョン、アーキテクチャ、フレーバーのNode.jsを選択できます。例えば、
{
"type": "node",
"request": "launch",
"name": "Launch test",
"runtimeVersion": "chackracore/8.9.4/x64",
"program": "${workspaceFolder}/test.js"
}
runtimeVersion
属性で使用したいNode.jsバージョンがインストールされていることを確認してください。この機能はバージョンを自動的にダウンロードしてインストールしません。例えば、起動構成に"runtimeVersion": "7.10.1"
を追加する予定がある場合、統合ターミナルからnvm install 7.10.1
またはnvs add 7.10.1
のようなコマンドを実行する必要があります。
マイナーバージョンとパッチバージョンを省略して、たとえば"runtimeVersion": "14"
とすると、システムにインストールされている最新の14.x.y
バージョンが使用されます。
外部ファイルから環境変数をロードする
VS Code Nodeデバッガーは、ファイルから環境変数をロードし、それらをNode.jsランタイムに渡すことをサポートしています。この機能を使用するには、起動構成にenvFile
属性を追加し、環境変数を含むファイルの絶対パスを指定します。
//...
"envFile": "${workspaceFolder}/.env",
"env": { "USER": "john doe" }
//...
env
辞書で指定された環境変数は、ファイルからロードされた変数を上書きします。
.env
ファイルの例は次のとおりです
USER=doe
PASSWORD=abc123
# a comment
# an empty value:
empty=
# new lines expanded in quoted strings:
lines="foo\nbar"
Node.jsへのアタッチ
VS Codeデバッガーを外部のNode.jsプログラムにアタッチしたい場合は、Node.jsを次のように起動します。
node --inspect program.js
または、プログラムの実行を開始せずにデバッガーがアタッチされるのを待つ必要がある場合
node --inspect-brk program.js
デバッガーをプログラムにアタッチするオプション
- すべての潜在的な候補プロセスをリストアップし、1つを選択できる「プロセスピッカー」を開く、または
- すべての構成オプションを明示的に指定する「アタッチ」構成を作成し、F5キーを押します。
これらのオプションを詳しく見てみましょう
Nodeプロセスにアタッチアクション
コマンドパレット (⇧⌘P (Windows, Linux Ctrl+Shift+P)) からのNodeプロセスにアタッチコマンドは、Node.jsデバッガーで利用可能なすべての潜在的なプロセスをリストアップするクイックピックメニューを開きます。
ピッカーにリストされている個々のプロセスは、デバッグポートとプロセスIDを表示します。そのリストでNode.jsプロセスを選択すると、Node.jsデバッガーがそれにアタッチしようとします。
Node.jsプロセスに加えて、ピッカーはさまざまな形式の--inspect
引数で起動された他のプログラムも表示します。これにより、ElectronまたはVS Codeのヘルパープロセスにアタッチすることが可能になります。
「アタッチ」構成のセットアップ
このオプションはより多くの作業を必要としますが、前の2つのオプションとは対照的に、さまざまなデバッグ構成オプションを明示的に構成できます。
最もシンプルな「アタッチ」構成は次のようになります。
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"port": 9229
}
ポート9229
は、--inspect
および--inspect-brk
オプションの既定のデバッグポートです。別のポート(例:12345
)を使用するには、--inspect=12345
および--inspect-brk=12345
のようにオプションに追加し、起動構成のport
属性を一致するように変更します。
デバッグモードで起動されていないNode.jsプロセスにアタッチするには、Node.jsプロセスのプロセスIDを文字列として指定することで可能です。
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"processId": "53426"
}
起動構成に新しいプロセスIDを繰り返し入力するのを避けるために、Nodeデバッグはプロセスピッカー(上記から)を開くコマンド変数PickProcess
をサポートしています。
PickProcess
変数を使用すると、起動構成は次のようになります。
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"processId": "${command:PickProcess}"
}
デバッグを停止する
デバッグ: 停止アクション(デバッグツールバーまたはコマンドパレットから利用可能)を使用すると、デバッグセッションが停止します。
デバッグセッションが「アタッチ」モードで開始された場合(デバッグツールバーの赤い終了ボタンに「プラグ」が重ねて表示されている場合)、停止を押すと、Node.jsデバッガーがデバッグ対象から切断され、デバッグ対象は実行を継続します。
デバッグセッションが「起動」モードの場合、停止を押すと次のようになります。
-
最初に停止を押すと、
SIGINT
シグナルを送信することで、デバッグ対象に正常なシャットダウンが要求されます。デバッグ対象は、このシグナルをインターセプトし、必要に応じてクリーンアップを行ってシャットダウンすることができます。そのシャットダウンコードにブレークポイント(または問題)がない場合、デバッグ対象とデバッグセッションは終了します。 -
ただし、デバッガーがシャットダウンコード内のブレークポイントにヒットした場合、またはデバッグ対象が適切に終了しない場合、デバッグセッションは終了しません。この場合、再度停止を押すと、デバッグ対象とその子プロセスが強制終了されます(
SIGKILL
)。
赤い停止ボタンを押してもデバッグセッションが終了しない場合は、もう一度ボタンを押してデバッグ対象を強制的にシャットダウンしてください。
Windowsでは、停止を押すとデバッグ対象とその子プロセスが強制的に終了します。
ソースマップ
VS CodeのJavaScriptデバッガーは、トランスパイルされた言語(例えばTypeScriptやミニファイ/醜化されたJavaScript)のデバッグに役立つソースマップをサポートしています。ソースマップを使用すると、元のソースをステップ実行したり、ブレークポイントを設定したりすることが可能です。元のソースのソースマップが存在しない場合、またはソースマップが壊れていてソースと生成されたJavaScriptの間で正常にマッピングできない場合、ブレークポイントは未検証(灰色のくぼんだ円)として表示されます。
デフォルトでtrue
に設定されているsourceMaps
属性は、ソースマップ機能を制御します。デバッガーは常にソースマップ(見つけることができる場合)を使用しようとします。その結果、program
属性でソースファイル(例:app.ts)を指定することもできます。何らかの理由でソースマップを無効にする必要がある場合は、sourceMaps
属性をfalse
に設定できます。
ツール構成
ソースマップは常に自動的に作成されるわけではないため、トランスパイラーがそれらを作成するように構成することを確認する必要があります。例えば
TypeScript
TypeScriptの場合、tsc
に--sourceMap
を渡すか、tsconfig.jsonファイルに"sourceMap": true
を追加することで、ソースマップを有効にできます。
tsc --sourceMap --outDir bin app.ts
Babel
Babelの場合、sourceMapsオプションをtrue
に設定するか、コードをコンパイルするときに--source-maps
オプションを渡す必要があります。
npx babel script.js --out-file script-compiled.js --source-maps
Webpack
Webpackには多数のソースマップオプションがあります。最高の結果を得るには、webpack.config.js
でプロパティdevtool: "source-map"
を設定することをお勧めしますが、ビルドの速度低下を引き起こす他の設定を試すこともできます。
また、TypeScriptローダーの使用など、webpackにさらなるコンパイルステップがある場合は、それらのステップもソースマップを生成するように設定されていることを確認してください。そうしないと、webpackが生成するソースマップは、実際のソースではなく、ローダーからのコンパイル済みコードにマッピングされてしまいます。
ソースマップの発見
デフォルトでは、VS Codeはワークスペース全体(node_modules
を除く)でソースマップを検索します。大規模なワークスペースでは、この検索は遅くなる可能性があります。VS Codeがソースマップを検索する場所は、launch.json
のoutFiles
属性を設定することで構成できます。たとえば、この構成ではbin
フォルダー内の.js
ファイルのみのソースマップが検出されます。
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch TypeScript",
"type": "node",
"request": "launch",
"program": "app.ts",
"outFiles": ["${workspaceFolder}/bin/**/*.js"]
}
]
}
outFiles
は、ソースマップファイル(.js
ではなく.map
で終わる場合があります)ではなく、JavaScriptファイルと一致する必要があることに注意してください。
ソースマップの解決
既定では、outFiles
内のソースマップのみが解決されます。この動作は、設定したブレークポイントに依存関係が干渉するのを防ぐために使用されます。例えば、src/index.ts
というファイルがあり、依存関係がwebpack:///./src/index.ts
を参照するソースマップを持っていた場合、それが誤ってソースファイルに解決され、予期せぬ結果につながる可能性があります。
この動作は、resolveSourceMapLocations
オプションを設定することで構成できます。null
に設定すると、すべてのソースマップが解決されます。例えば、この構成では、node_modules/some-dependency
内のソースマップも解決できるようになります。
"resolveSourceMapLocations": [
"out/**/*.js",
"node_modules/some-dependency/**/*.js",
]
スマートステップ
起動構成でsmartStep
属性をtrue
に設定すると、VS Codeはデバッガーでコードをステップ実行する際に「関連のないコード」を自動的にスキップします。「関連のないコード」とは、トランスパイルプロセスによって生成されたコードでありながら、ソースマップでカバーされていないため、元のソースにマッピングされないコードを指します。このコードは、デバッガーでソースコードをステップ実行する際に、デバッガーが元のソースコードと興味のない生成されたコードの間を行き来させるため、邪魔になります。smartStep
は、ソースマップでカバーされていないコードを自動的にステップ実行し、ソースマップで再びカバーされている場所に到達するまで続行します。
スマートステップは、TypeScriptのasync/awaitのダウンコンパイルなど、コンパイラーがソースマップでカバーされていないヘルパーコードを挿入する場合に特に役立ちます。
smartStep
機能は、ソースから生成され、したがってソースマップを持つJavaScriptコードにのみ適用されます。ソースがないJavaScriptの場合、スマートステップオプションは効果がありません。
JavaScriptソースマップのヒント
ソースマップでデバッグする際のよくある問題は、ブレークポイントを設定するとそれが灰色になることです。カーソルを重ねると、「生成されたコードが見つからないためブレークポイントは無視されました(ソースマップの問題ですか?)」
というメッセージが表示されます。さてどうすればよいでしょうか?これにはさまざまな問題が考えられます。まず、Nodeデバッグアダプターがソースマップをどのように処理するかについて簡単に説明します。
app.ts
にブレークポイントを設定すると、デバッグアダプターはapp.js
(TypeScriptファイルのトランスパイル済みバージョンであり、実際にNodeで実行されているもの)へのパスを特定する必要があります。しかし、.ts
ファイルからこれを特定する直接的な方法はありません。代わりに、デバッグアダプターはlaunch.json
のoutFiles
属性を使用して、すべてのトランスパイル済み.js
ファイルを検索し、それらを解析して、関連する.ts
ファイルの場所を含むソースマップを見つけます。
ソースマップを有効にしてTypeScriptでapp.ts
ファイルをビルドすると、app.js.map
ファイルが生成されるか、app.js
ファイルの最後にbase64エンコードされた文字列としてコメント内にインラインでソースマップが生成されます。このマップに関連付けられた.ts
ファイルを見つけるために、デバッグアダプターはソースマップの2つのプロパティ、sources
とsourceRoot
を調べます。sourceRoot
はオプションであり、存在する場合はsources
(パスの配列)内の各パスの前に付加されます。その結果、.ts
ファイルへの絶対パスまたは相対パスの配列が生成されます。相対パスはソースマップを基準に解決されます。
最後に、デバッグアダプターは、この結果の.ts
ファイルリスト内でapp.ts
の完全なパスを検索します。一致するものが見つかれば、app.ts
をapp.js
にマッピングする際に使用するソースマップファイルが見つかったことになります。一致するものがない場合、ブレークポイントをバインドできず、灰色になります。
ブレークポイントが灰色になったときに試すことをいくつか示します。
- デバッグ中に、デバッグ: ブレークポイントの問題を診断コマンドを実行します。このコマンドは、コマンドパレット (⇧⌘P (Windows, Linux Ctrl+Shift+P)) から、問題の解決に役立つヒントを提供するツールを表示します。
- ソースマップを有効にしてビルドしましたか?
.js.map
ファイルが存在するか、.js
ファイルにインラインソースマップが存在することを確認してください。 - ソースマップの
sourceRoot
とsources
プロパティは正しいですか?それらを組み合わせて、.ts
ファイルへの正しいパスを取得できますか? - VS Codeでフォルダーを間違ったケースで開きましたか?コマンドラインから
code FOO
のようにfoo/
フォルダーを開くことが可能ですが、その場合、ソースマップが正しく解決されない可能性があります。 - Stack Overflowで特定のセットアップに関するヘルプを検索するか、GitHubで問題を報告してみてください。
debugger
ステートメントを追加してみてください。そこで.ts
ファイルにブレークしても、その場所でブレークポイントがバインドされない場合は、それはGitHubの問題に含める有用な情報です。
ソースマップパスのオーバーライド
デバッガーはsourceMapPathOverrides
を使用して、カスタムのソースマップからディスクへのパスマッピングを実装します。ほとんどのツールには適切なデフォルトが設定されていますが、高度なケースではカスタマイズが必要になる場合があります。デフォルトのパスオーバーライドは、次のようなオブジェクトマップです。
{
'webpack:///./~/*': "${workspaceFolder}/node_modules/*",
'webpack:////*': '/*',
'webpack://@?:*/?:*/*': "${workspaceFolder}/*",
// and some more patterns...
}
これは、ソースマップ内のパスまたはURLを左から右にマッピングします。パターン?:*
は非欲張り、非キャプチャのマッチングであり、*
は欲張りキャプチャマッチングです。デバッガーは、右側のパターン内の対応する*
を、ソースマップパスからキャプチャされたフラグメントに置き換えます。たとえば、上記の例の最後のパターンは、webpack://@my/package/foo/bar
を${workspaceFolder}/foo/bar
にマッピングします。
ブラウザデバッグの場合、デフォルトのsourceMapPathOverrides
ではworkspaceFolder
の代わりにwebRoot
が使用されることに注意してください。
リモートデバッグ
注: VS Codeには、ユニバーサルなリモート開発機能が搭載されています。リモート開発拡張機能を使用すると、リモートシナリオやコンテナでのNode.js開発は、ローカル環境でのNode.js開発と何ら変わりません。これは、Node.jsプログラムをリモートデバッグする推奨される方法です。始め方セクションとリモートチュートリアルをチェックして、詳細を確認してください。
リモート開発拡張機能を使用してNode.jsプログラムをデバッグできない場合は、ローカルのVS CodeインスタンスからリモートNode.jsプログラムをデバッグする方法のガイドを以下に示します。
Node.jsデバッガーは、別のマシンまたはコンテナーで実行されているプロセスにアタッチするリモートデバッグをサポートしています。address
属性を介してリモートホストを指定します。例えば、
{
"type": "node",
"request": "attach",
"name": "Attach to remote",
"address": "192.168.148.2", // <- remote address here
"port": 9229
}
既定では、VS Codeはデバッグ対象のソースをリモートNode.jsフォルダーからローカルのVS Codeにストリームし、読み取り専用エディターに表示します。このコードはステップ実行できますが、変更はできません。VS Codeでワークスペースから編集可能なソースを開きたい場合は、リモートとローカルの場所の間にマッピングを設定できます。localRoot
とremoteRoot
属性を使用して、ローカルのVS Codeプロジェクトと(リモートの)Node.jsフォルダー間のパスをマッピングできます。これは、同じシステム上でのローカルな場合でも、異なるオペレーティングシステム間でも機能します。コードパスをリモートNode.jsフォルダーからローカルのVS Codeパスに変換する必要がある場合、remoteRoot
パスがパスから削除され、localRoot
に置き換えられます。逆変換の場合、localRoot
パスがremoteRoot
に置き換えられます。
{
"type": "node",
"request": "attach",
"name": "Attach to remote",
"address": "TCP/IP address of process to be debugged",
"port": 9229,
"localRoot": "${workspaceFolder}",
"remoteRoot": "C:\\Users\\username\\project\\server"
}
ロードされたスクリプトへのアクセス
ワークスペースの一部ではないため、通常のVS Codeファイルブラウジングでは簡単に見つけて開くことができないスクリプトにブレークポイントを設定する必要がある場合は、実行とデバッグビューのLOADED SCRIPTSビューを介してロードされたスクリプトにアクセスできます。
LOADED SCRIPTSビューでは、名前を入力してスクリプトをすばやく選択したり、Enable Filter on Typeがオンの場合にリストをフィルタリングしたりできます。
スクリプトは読み取り専用エディターにロードされ、そこでブレークポイントを設定できます。これらのブレークポイントはデバッグセッション間で記憶されますが、デバッグセッションの実行中にのみスクリプトの内容にアクセスできます。
ソース編集時のデバッグセッション自動再起動
起動構成のrestart
属性は、デバッグセッション終了後にNode.jsデバッガーが自動的に再起動するかどうかを制御します。この機能は、ファイル変更時にNode.jsを再起動するためにnodemonを使用する場合に便利です。起動構成属性restart
をtrue
に設定すると、NodeデバッガーはNode.jsが終了した後、Node.jsに自動的に再アタッチを試みます。
コマンドラインでnodemon経由でプログラムserver.js
を次のように起動した場合、
nodemon --inspect server.js
次の起動構成でVS Codeデバッガーをアタッチできます。
{
"name": "Attach to node",
"type": "node",
"request": "attach",
"restart": true,
"port": 9229
}
または、起動構成で直接nodemon経由でプログラムserver.js
を起動し、VS Codeデバッガーをアタッチすることもできます。
{
"name": "Launch server.js via nodemon",
"type": "node",
"request": "launch",
"runtimeExecutable": "nodemon",
"program": "${workspaceFolder}/server.js",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
ヒント: 停止ボタンを押すとデバッグセッションが停止し、Node.jsから切断されますが、nodemon(およびNode.js)は引き続き実行されます。nodemonを停止するには、コマンドラインから強制終了する必要があります(上記のように
integratedTerminal
を使用している場合は簡単に可能です)。
ヒント: 構文エラーの場合、エラーが修正されるまでnodemonはNode.jsを正常に起動できません。この場合、VS CodeはNode.jsへのアタッチを試行し続けますが、最終的に諦めます(10秒後)。これを回避するには、
timeout
属性に大きな値(ミリ秒単位)を追加してタイムアウトを増やすことができます。
フレームを再起動
Nodeデバッガーはスタックフレームでの実行再開をサポートしています。これは、ソースコードで問題を発見し、変更された入力値でコードの一部を再実行したい場合に役立ちます。完全なデバッグセッションを停止して再開するのは時間がかかることがあります。フレームの再起動アクションを使用すると、値の設定アクションで変数を変更した後、現在の関数を再入力できます。
フレームの再起動は関数の外部の状態への変更を元に戻さないため、常に期待通りに動作しない場合があります。
ブレークポイント
条件付きブレークポイント
条件付きブレークポイントは、式が真の値を返した場合にのみ一時停止するブレークポイントです。行番号の横のガターを右クリックし、「条件付きブレークポイント」を選択して作成できます。
ログポイント
コードが特定の場所に到達したときに、一時停止するのではなく、単にメッセージや値をログに記録したい場合があります。これはログポイントで可能です。ログポイントは一時停止せず、ヒットしたときにデバッグコンソールにメッセージをログに記録します。JavaScriptデバッガーでは、中括弧を使用して式をメッセージに補間できます。たとえば、current value is: {myVariable.property}
のようにします。
行番号の横のガターを右クリックし、「ログポイント」を選択して作成できます。例えば、これはlocation is /usr/local
のようなメッセージをログに記録するかもしれません。
ヒットカウントブレークポイント
「ヒットカウント条件」は、ブレークポイントが実行を「中断」するまでに何回ヒットする必要があるかを制御します。ヒットカウントブレークポイントは、行番号の横のガターを右クリックし、「条件付きブレークポイント」を選択し、その後「ヒットカウント」に切り替えることで設定できます。
Node.jsデバッガーがサポートするヒットカウント構文は、整数、または<
、<=
、==
、>
、>=
、%
のいずれかの演算子に続く整数です。
いくつかの例
>10
10回ヒットした後、常にブレークする<3
最初の2回ヒット時のみブレークする10
>=10
と同じ%2
2回に1回ブレークする
トリガーされたブレークポイント
トリガーされたブレークポイントとは、別のブレークポイントに到達すると自動的に有効になるブレークポイントです。これらは、特定の事前条件の後にのみ発生するコードの失敗ケースを診断する際に非常に役立ちます。
トリガーされたブレークポイントは、グリフマージンを右クリックし、トリガーされたブレークポイントの追加を選択し、その後、どの他のブレークポイントがこのブレークポイントを有効にするかを選択することで設定できます。
ブレークポイントの検証
パフォーマンス上の理由から、Node.jsはJavaScriptファイル内の関数を最初のアクセス時に遅延解析します。結果として、Node.jsによってまだ「見られていない」(解析されていない)ソースコード領域ではブレークポイントが機能しません。
この動作はデバッグには理想的ではないため、VS CodeはNode.jsに自動的に--nolazy
オプションを渡します。これにより、遅延解析が防止され、コードを実行する前にブレークポイントが検証されることが保証されます(したがって、それらが「ジャンプ」することはなくなります)。
--nolazy
オプションはデバッグターゲットの起動時間を大幅に増加させる可能性があるため、runtimeArgs
属性として--lazy
を渡すことで簡単に無効にできます。
そうすると、ブレークポイントの中には要求された行に「固定」されず、代わりにすでに解析されたコードの次の可能な行に「ジャンプ」するものがあることに気づくでしょう。混乱を避けるため、VS Codeは常にNode.jsがブレークポイントがあると考えている場所にブレークポイントを表示します。ブレークポイントセクションでは、これらのブレークポイントは要求された行番号と実際の行番号の間に矢印で表示されます。
このブレークポイント検証は、セッションが開始され、ブレークポイントがNode.jsに登録されたとき、またはセッションがすでに実行されており、新しいブレークポイントが設定されたときに発生します。この場合、ブレークポイントは別の場所に「ジャンプ」する可能性があります。Node.jsがすべてのコードを解析した後(例えば、コードを実行することによって)、ブレークポイントセクションヘッダーの再適用ボタンを使用すると、ブレークポイントを要求された位置に簡単に再適用できます。これにより、ブレークポイントは要求された位置に「ジャンプして戻る」はずです。
関連のないコードをスキップする
VS CodeのNode.jsデバッグには、ステップ実行したくないソースコードを避ける機能(「Just My Code」とも呼ばれます)があります。この機能は、起動構成のskipFiles
属性で有効にできます。skipFiles
は、スキップするスクリプトパスのグロブパターンの配列です。
例えば、次のように使用すると、
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"${workspaceFolder}/lib/**/*.js"
]
プロジェクトのnode_modules
およびlib
フォルダー内のすべてのコードがスキップされます。skipFiles
は、console.log
などのメソッドを呼び出したときに表示される場所にも適用されます。デバッグコンソールの出力の横には、スタック内の最初のスキップされない場所が表示されます。
Node.jsの組み込みコアモジュールは、グロブパターンで「マジックネーム」<node_internals>
で参照できます。次の例では、すべての内部モジュールをスキップします。
"skipFiles": [
"<node_internals>/**/*.js"
]
正確な「スキップ」ルールは次のとおりです。
- スキップされたファイルにステップインしても、そこで停止することはありません。スキップされていないファイル内の次に実行される行で停止します。
- スローされた例外でブレークするオプションを設定している場合、スキップされたファイルからスローされた例外は、それらがスキップされていないファイルにバブルアップしない限り、ブレークしません。
- スキップされたファイルにブレークポイントを設定した場合、そのブレークポイントで停止し、それをステップ実行できます。そこからステップアウトすると、通常のスキップ動作が再開されます。
- スキップファイル内のコンソールメッセージの場所は、コールスタック内の最初のスキップされていない場所として表示されます。
スキップされたソースは、コールスタックビューで「薄暗い」スタイルで表示されます。
薄暗いエントリにカーソルを合わせると、スタックフレームが薄暗い理由が説明されます。
コールスタックのコンテキストメニュー項目であるこのファイルのスキップを切り替えるを使用すると、起動構成に追加することなく、実行時にファイルを簡単にスキップできます。このオプションは、現在のデバッグセッションの間のみ有効です。また、起動構成のskipFiles
オプションによってスキップされているファイルのスキップを停止するためにも使用できます。
注:
legacy
プロトコルデバッガーは負のグロブパターンをサポートしていますが、それらは正のパターンの後に続く必要があります。正のパターンはスキップされるファイルのセットに追加し、負のパターンはそのセットから減算します。
以下の(legacy
プロトコルのみの)例では、「math」モジュール以外のすべてがスキップされます。
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"!${workspaceFolder}/node_modules/math/**/*.js"
]
注:
legacy
プロトコルデバッガーは、V8デバッガープロトコルがネイティブでskipFiles
機能をサポートしていないため、これをエミュレートする必要があります。これにより、ステップ実行のパフォーマンスが低下する可能性があります。
WebAssemblyのデバッグ
JavaScriptデバッガーは、DWARFデバッグ情報を含むWebAssemblyコードをデバッグできます。多くのツールチェーンがこの情報の出力に対応しています。
- Emscriptenを使用したC/C++:
-g
フラグを付けてコンパイルし、デバッグ情報を出力します。 - Zig: DWARF情報は「Debug」ビルドモードで自動的に出力されます。
- Rust: RustはDWARFデバッグ情報を出力します。ただし、wasm-packはまだビルド中にそれを保持しません。そのため、一般的なwasm-bindgen/wasm-packライブラリのユーザーは、
wasm-pack build
を実行する代わりに、次の2つのコマンドを使用して手動でビルドする必要があります。- 必要なコマンドラインツールをインストールするために、一度
cargo install wasm-bindgen-cli
を実行します。 - ライブラリをビルドするために、
cargo build --target wasm32-unknown-unknown
を実行します。 - WebAssemblyバインディングを生成するために、
wasm-bindgen --keep-debug --out-dir pkg ./target/wasm32-unknown-unknown/debug/<library-name>.wasm <extra-arguments>
を実行します。<library-name>
はCargo.tomlからの名前に置き換え、必要に応じて<extra-arguments>
を設定します。
- 必要なコマンドラインツールをインストールするために、一度
コードをビルドした後、WebAssembly DWARF Debugging拡張機能をインストールする必要があります。これは、VS Codeコアを「合理化」するために別の拡張機能として提供されています。インストール後、アクティブなデバッグセッションを再起動すると、ネイティブコードがデバッガーにマッピングされるはずです!ソースコードがロードされたソースビューに表示され、ブレークポイントが機能するはずです。
以下の画像では、マンデルブロ集合を生成するC++ソースコードのブレークポイントでデバッガーが停止しています。コールスタックが表示されており、JavaScriptコード、WebAssembly、マッピングされたC++コードからのフレームが含まれています。C++コードの変数も表示され、int32のheight
変数に関連付けられたメモリへの編集も確認できます。
ほぼ同等ですが、WebAssemblyのデバッグは通常のJavaScriptとは少し異なります。
- 変数ビューの変数は直接編集できません。ただし、変数の横にあるバイナリデータを表示アクションを選択して、関連付けられたメモリを編集できます。
- デバッグコンソールと監視ビューでの基本的な式評価は、lldb-evalによって提供されます。これは通常のJavaScript式とは異なります。
- ソースコードにマッピングされない場所は、逆アセンブルされたWebAssemblyテキスト形式で表示されます。WebAssemblyの場合、ソースマップステップを無効にするコマンドを実行すると、デバッガーは逆アセンブルされたコード内でのみステップ実行します。
VS CodeのWebAssemblyデバッグは、Chromiumの作者によるC/C++ Debugging Extensionの上に構築されています。
サポートされているNodeライクなランタイム
現在のVS Code JavaScriptデバッガーは、Nodeバージョン8.x以上、最近のChromeバージョン、および最近のEdgeバージョン(msedge
起動タイプ経由)をサポートしています。
次のステップ
Node.jsセクションをまだ読んでいない場合は、以下をご覧ください。
- Node.js - サンプルアプリケーションを使用したエンドツーエンドのNodeシナリオ
VS Codeでのデバッグの基本に関するチュートリアルを見るには、このビデオをご覧ください。
VS Codeのタスク実行サポートについて学ぶには、以下にアクセスしてください。
- タスク - Gulp、Grunt、Jakeを使用したタスクの実行。エラーと警告の表示
独自のデバッガー拡張機能を作成するには、以下にアクセスしてください。
- デバッガー拡張機能 - モックサンプルからVS Codeデバッグ拡張機能を作成する手順
よくある質問
シンボリックリンクを使用している場合でもデバッグできますか?
はい、npm link
のようにプロジェクト内にフォルダーのシンボリックリンクを作成した場合、Node.jsランタイムにシンボリックリンクされたパスを保持するよう指示することで、シンボリックリンクされたソースをデバッグできます。起動構成のruntimeArgs
属性にnode.exeの--preserve-symlinks
スイッチを使用します。文字列の配列であるruntimeArgs
は、デバッグセッションのランタイム実行可能ファイル(デフォルトはnode.exe)に渡されます。
{
"runtimeArgs": ["--preserve-symlinks"]
}
メインスクリプトがシンボリックリンクされたパス内にある場合、"--preserve-symlinks-main"
オプションも追加する必要があります。このオプションはNode 10以降でのみ利用可能です。
ECMAScriptモジュールをデバッグする方法は?
ECMAScriptモジュールを使用するためにesmを使用している場合、またはNode.jsに--experimental-modules
を渡している場合、これらのオプションをlaunch.json
のruntimeArgs
属性経由で渡すことができます。
"runtimeArgs": ["--experimental-modules"]
- Node v8.5.0以降で実験的なECMAScriptモジュールサポートを使用します。"runtimeArgs": ["-r", "esm"]
- esm ESモジュールローダーを使用します(コンマなしの["-r esm"]
は機能しません)。
NODE_OPTIONSを設定するにはどうすればよいですか?
デバッガーは、アプリケーションでデバッグをセットアップするために特殊なNODE_OPTIONS
環境変数を使用しており、これを上書きするとデバッグが正しく機能しなくなります。上書きするのではなく、追加するようにしてください。例えば、.bashrc
ファイルには次のようなものが含まれるかもしれません。
export NODE_OPTIONS="$NODE_OPTIONS --some-other-option=here"