VSCode で Electron のアプリをデバッグするときの launch.json runtimeExecutable について

分かったら一瞬だけど、分からないとずっと悩む奴です。

Electron を実行しようとすると、macOSLinuxだと、

node_modules/.bin/electron

を実行すれば良いのですが、 Windows では、

node_modules/.bin/electron.cmd

を実行しなければなりません。そのため、 .vscode/launch.json を下記のように設定すると、 Windows ではデバッグできません。

// この launch.json では Windows ではデバッグが出来ません!
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "program": "${workspaceRoot}/app/index.js",
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
      "runtimeArgs": [
        "--enable-logging"
      ],
      "args": [
        "."
      ]
    }
  ]
}

console によるターミナル設定

実は、 launch.json には、 console というパラメータがあり、それによって、実行ファイル(runtimeExecutable)をどうやって実行するかを選択することが出来ます。この値が、既定では、internalConsoleになっているようです。

そして、その場合、Windowsでは、node_modules/.bin/electron がそのまま実行されることになるのですが、このファイルはシェルスクリプトなので、Windows では実行できず、実行に失敗します。

そこで、 consoleの設定を、integratedTerminal もしくは、 externalTerminal に設定すると、「デバッグ」はうまく動くようになります。

どうしてこのような違いが起きるのかというと、 integratedTerminal もしくは、 externalTerminal に設定すると、内部的に、 cmd.exe を挟んで起動されるために、 electron というファイルではなく、Windows で実行可能な、 electron.exeelectron.cmd を探してくれるようになるからです。

ただし、externalTerminal にすると、デバッグ終了時に、無駄に開いたコマンドウィンドウを閉じないといけない羽目になって、面倒なので、 integratedTerminal を指定する方が良さげです。

従って、launch.json は次のように書くべきでしょう:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "program": "${workspaceRoot}/app/index.js",
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
      "runtimeArgs": [
        "--enable-logging"
      ],
      "args": [
        "."
      ],
      "console":"integratedTerminal"
    }
  ]
}

プラットフォーム毎の固有設定

また、意外と言及されてないのは、launch.jsonには、 windowsosxlinux といったトップレベル要素が用意されており、パラメータを環境毎に切り替えられるようになっていると言うことです。なので、書こうと思えば、次の例のように、Windows 用の実行ファイルを別に設定することが可能です。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "node",
            "request": "launch",
            "cwd": "${workspaceRoot}",
            "program": "${workspaceRoot}/app/index.js",
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            "runtimeArgs": [
                "--enable-logging"
            ],
            "args": [
                "."
            ],
            "windows": {
                "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
            },
            "console":"integratedTerminal"
        }
    ]
}