VS Code での Node.js デバッグ
Visual Studio Code エディターには、Node.js ランタイムの組み込みデバッグサポートがあり、JavaScript、TypeScript、および JavaScript にトランスパイルされる他の多くの言語をデバッグできます。Node.js デバッグ用のプロジェクトのセットアップは簡単で、VS Code は適切な起動構成のデフォルトとスニペットを提供します。
VS Code で Node.js プログラムをデバッグするには、いくつかの方法があります。
- VS Code の統合ターミナルで実行するプロセスをデバッグするには、自動アタッチを使用します。
- 統合ターミナルの使用と同様に、JavaScript デバッグターミナルを使用します。
- 起動構成を使用してプログラムを開始するか、VS Code の外部で起動されたプロセスにアタッチします。
自動アタッチ
自動アタッチ機能が有効になっている場合、Node デバッガーは、VS Code の統合ターミナルから起動された特定の Node.js プロセスに自動的にアタッチします。この機能を有効にするには、コマンドパレットから[自動アタッチの切り替え]コマンド(⇧⌘P (Windows、Linux Ctrl+Shift+P))を使用するか、すでにアクティブになっている場合は、[自動アタッチ]ステータスバー項目を使用します。
自動アタッチには 3 つのモードがあり、結果のクイックピックとdebug.javascript.autoAttachFilter設定で選択できます。
smart
- スクリプトをnode_modules
フォルダー外で実行するか、mocha や ts-node などの一般的な「ランナー」スクリプトを使用すると、プロセスがデバッグされます。[自動アタッチスマートパターン]設定 (debug.javascript.autoAttachSmartPattern
) を使用して、「ランナー」スクリプトの許可リストを構成できます。always
- 統合ターミナルで起動されたすべての Node.js プロセスがデバッグされます。onlyWithFlag
---inspect
または--inspect-brk
フラグを指定して起動されたプロセスのみがデバッグされます。
[自動アタッチ]を有効にしたら、ターミナルの右上にある ⚠ アイコンをクリックしてターミナルを再起動するか、新しいターミナルを作成する必要があります。その後、デバッガーは 1 秒以内にプログラムにアタッチする必要があります。
自動アタッチがオンの場合、自動アタッチ
項目が VS Code ウィンドウの下部にあるステータスバーに表示されます。これをクリックすると、自動アタッチモードを変更したり、一時的にオフにしたりできます。一時的に自動アタッチをオフにすることは、デバッグする必要のない 1 回限りのプログラムを実行しているが、機能を完全に無効にしたくない場合に役立ちます。
追加の構成
その他の起動構成プロパティ
debug.javascript.terminalOptions設定で、通常 launch.json にある他のプロパティを自動アタッチに適用できます。たとえば、node internals を 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 デバッグターミナル
自動アタッチと同様の方法で、JavaScript デバッグターミナルは、その中で実行するすべての Node.js プロセスを自動的にデバッグします。デバッグターミナルを作成するには、コマンドパレットから[デバッグ: JavaScript デバッグターミナルの作成]コマンド (kbs(workbench.action.showCommands)
) を実行するか、ターミナルスイッチャードロップダウンから[JavaScript デバッグターミナルの作成]を選択します。
追加の構成
その他の起動構成プロパティ
debug.javascript.terminalOptions設定で、通常 launch.json にある他のプロパティをデバッグターミナルに適用できます。たとえば、node internals を skipFiles に追加するには、ユーザーまたはワークスペースの設定に次を追加できます。
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**"
]
},
起動構成
起動構成は、VS Code でデバッグを設定する従来の方法であり、複雑なアプリケーションを実行するための最も多くの構成オプションを提供します。
このセクションでは、より高度なデバッグシナリオの構成と機能について詳しく説明します。ソースマップを使用したデバッグ、外部コードのステップオーバー、リモートデバッグなどの手順について説明します。
入門ビデオをご覧になりたい場合は、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
- Node.js バージョンの管理に "nvm" (または "nvm-windows") または "nvs" が使用されている場合、この属性を使用して特定のバージョンの 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 の「debug」スクリプトを介して 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 テストをデバッグします。プロジェクトに 'mocha' がnode_modules
フォルダーにインストールされていることを確認してください。 - Yeoman ジェネレーター: yeoman ジェネレーターをデバッグします。スニペットは、ジェネレーターの名前を指定するように求めます。プロジェクトに 'yo' が
node_modules
フォルダーにインストールされており、生成されたプロジェクトがプロジェクトフォルダーでnpm link
を実行してデバッグ用にインストールされていることを確認してください。 - Gulp タスク: gulp タスクをデバッグします。プロジェクトに 'gulp' が
node_modules
フォルダーにインストールされていることを確認してください。 - Electron メイン: 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」) を使用している場合は、起動構成で runtimeVersion
属性を指定して、特定のバージョンの Node.js を選択できます。
{
"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 プロセスへのアタッチアクション
コマンドパレットの[Node プロセスへのアタッチ]コマンド (⇧⌘P (Windows、Linux Ctrl+Shift+P)) は、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 やミニファイ/uglify 化された JavaScript) のデバッグに役立つソースマップをサポートしています。ソースマップを使用すると、元のソースをシングルステップ実行したり、ブレークポイントを設定したりできます。元のソースのソースマップが存在しない場合、またはソースマップが壊れていて、ソースと生成された JavaScript を正常にマッピングできない場合、ブレークポイントは未検証として表示されます (灰色の空洞の円)。
デフォルトで true
に設定されている sourceMaps
属性は、ソースマップ機能を制御します。デバッガーは常にソースマップを使用しようとし (見つかった場合)、その結果、program
属性でソースファイル (たとえば、app.ts) を指定することもできます。何らかの理由でソースマップを無効にする必要がある場合は、sourceMaps
属性を false
に設定できます。
ツール構成
ソースマップは常に自動的に作成されるとは限らないため、トランスパイラーを構成してソースマップを作成するようにする必要があります。例:
TypeScript
TypeScript の場合、--sourceMap
を tsc
に渡すか、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"
を設定して結果の忠実度を最大限に高めることをお勧めしますが、ビルドの速度低下を引き起こす他の設定を試すことができます。
また、Webpack で TypeScript ローダーを使用するなど、追加のコンパイルステップがある場合は、これらのステップがソースマップを生成するように設定されていることを確認する必要もあります。そうしないと、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 ソースマップのヒント
ソースマップを使用したデバッグでよくある問題は、ブレークポイントを設定すると、それが灰色になることです。カーソルを合わせると、"Breakpoint ignored because generated code not found (source map problem?)"
というメッセージが表示されます。さて、どうすればよいでしょうか?これにはさまざまな原因が考えられます。まず、Node デバッグアダプターがソースマップをどのように処理するかを簡単に説明します。
app.ts
にブレークポイントを設定すると、デバッグアダプターは、TypeScript ファイルのトランスパイルバージョンであり、Node で実際に実行されている app.js
へのパスを特定する必要があります。しかし、.ts
ファイルから始めてこれを特定する簡単な方法はありません。代わりに、デバッグアダプターは launch.json
の outFiles
属性を使用して、トランスパイルされたすべての .js
ファイルを見つけ、それらを解析してソースマップを探します。ソースマップには、関連付けられた .ts
ファイルの場所が含まれています。
ソースマップを有効にして TypeScript で app.ts
ファイルをビルドすると、app.js.map
ファイルが生成されるか、app.js
ファイルの下部にあるコメントに base64 エンコードされた文字列としてインライン化されたソースマップが生成されます。このマップに関連付けられた .ts
ファイルを見つけるために、デバッグアダプターはソースマップの sources
と sourceRoot
という 2 つのプロパティを調べます。sourceRoot
はオプションです。存在する場合、sources
内の各パスの先頭に追加されます。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 で issue を提出してみてください。
debugger
ステートメントを追加してみてください。そこで.ts
ファイルにブレークした場合、その場所のブレークポイントがバインドされない場合は、GitHub issue に含めるのに役立つ情報です。
ソースマップパスのオーバーライド
デバッガーは、カスタムのソースマップからディスクへのパスマッピングを実装するために 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 には、ユニバーサル リモート開発機能 が追加されました。Remote Development 拡張機能を使用すると、リモートシナリオおよびコンテナでの Node.js 開発は、ローカルセットアップでの Node.js 開発と変わりません。これが、Node.js プログラムをリモートでデバッグするための推奨される方法です。詳細については、はじめに セクションと リモートチュートリアル を参照してください。
Remote Development 拡張機能を使用して 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 ファイルブラウジングでは簡単に見つけて開くことができないスクリプトにブレークポイントを設定する必要がある場合は、実行とデバッグ ビューの ロードされたスクリプト ビューからロードされたスクリプトにアクセスできます。
ロードされたスクリプト ビューでは、名前を入力してスクリプトをすばやく選択したり、タイプでフィルターを有効にする がオンになっている場合はリストをフィルタリングしたりできます。
スクリプトは読み取り専用エディターにロードされ、そこでブレークポイントを設定できます。これらのブレークポイントはデバッグセッション間で記憶されますが、デバッグセッションが実行されている間のみスクリプトコンテンツにアクセスできます。
ソースが編集されたときにデバッグセッションを自動的に再起動する
起動構成の restart
属性は、デバッグセッションが終了した後、Node.js デバッガーが自動的に再起動するかどうかを制御します。この機能は、ファイル変更時に Node.js を再起動するために nodemon を使用する場合に役立ちます。起動構成属性 restart
を true
に設定すると、Node.js デバッガーは Node.js が終了した後、自動的に Node.js に再アタッチしようとします。
プログラム server.js
をコマンドラインで nodemon 経由で次のように起動した場合
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 回ヒットするごとにブレーク
トリガーされたブレークポイント
トリガーされたブレークポイントは、別のブレークポイントがヒットすると自動的に有効になるブレークポイントです。特定の前提条件の後でのみ発生するコードの障害ケースを診断する場合に非常に役立ちます。
トリガーされたブレークポイントは、グリフマージンを右クリックし、トリガーされたブレークポイントを追加 を選択してから、どの他のブレークポイントがブレークポイントを有効にするかを選択することで設定できます。
ブレークポイントの検証
パフォーマンス上の理由から、Node.js は JavaScript ファイル内の関数を最初のアクセス時に遅延解析します。その結果、ブレークポイントは Node.js によってまだ認識 (解析) されていないソースコード領域では機能しません。
この動作はデバッグには理想的ではないため、VS Code は --nolazy
オプションを Node.js に自動的に渡します。これにより、遅延解析が防止され、コードの実行前にブレークポイントを検証できることが保証されます (したがって、もはや「ジャンプ」しません)。
--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 Debugger Protocol がネイティブにサポートしていないため、skipFiles
機能をエミュレートする必要があります。これにより、ステップ実行のパフォーマンスが低下する可能性があります。
WebAssembly のデバッグ
JavaScript デバッガーは、DWARF デバッグ情報が含まれている場合、WebAssembly にコンパイルされたコードをデバッグできます。多くのツールチェーンがこの情報の出力に対応しています。
- Emscripten を使用した C/C++: デバッグ情報を出力するには、
-g
フラグを指定してコンパイルします。 - Zig: DWARF 情報は、「Debug」ビルドモードで自動的に出力されます。
- Rust: Rust は DWARF デバッグ情報を出力します。ただし、wasm-pack はビルド中にまだ保持していません (未対応)。そのため、
wasm-pack build
を実行する代わりに、一般的な wasm-bindgen/wasm-pack ライブラリのユーザーは、次の 2 つのコマンドを使用して手動でビルドする必要があります。- 必要なコマンドラインツールをインストールするために
cargo install wasm-bindgen-cli
を 1 回実行します。 - ライブラリをビルドするために
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.js のようなランタイム
現在の 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 モジュールをデバッグするにはどうすればよいですか?
esm を使用するか、ECMAScript モジュールを使用するために 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"