dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

npm installしたパッケージをVSCodeでデバッグする

npmでインストールしたパッケージが期待通りに動かず内部の動作を確認したい、となったときの話。

これまでは該当のスクリプトconsole.log() とか直接書いてデバッグしてたんですが、あまりにも効率が悪いのでもうちょっと良いやり方を見つけたい。
VSCodeでbreakpoint置きつつ変数の中身を見たりステップ実行したい。
と思ったので調べました。

ここではデバッグするパッケージの例として Storybook を取り上げてみます。
Storybookはたいていpackage.json

"scripts": {
  "storybook": "start-storybook -p 6006 -s ./assets"
}

のようなスクリプトを書いて実行することが多いと思います。
このとき、start-storybookというコマンド内部で何が行われているかを調査します。


手順

1. start-storybookコマンドで実行されるファイルを特定する

まずは、start-storybookコマンドによって実行されるファイルを見つけます。
npm scriptにコマンドで書けるということは node_modules/.bin 以下に該当のコマンドがあるはずなので探すと、

$ ls -l node_modules/.bin | grep start-storybook
lrwxr-xr-x  1 yamazaki  staff  32  6 20 22:37 start-storybook@ -> ../@storybook/react/bin/index.js

ということで、今回の場合 node_modules/@storybook/react/bin/index.js を見ればいいことがわかります。

また、VSCodeの場合シンボリックリンクはマウスオーバーでリンク先がわかります。

f:id:dackdive:20190620230331g:plain

(もうちょっと良い表示方法ないのかな)

別の方法として、対象のnpmパッケージのpackage.jsonbinを見るという方法もあります。

見つけたファイルの冒頭にbreakpointを置いておきます。
今回の @storybook/react/bin/index.js は @storybook/react/dist/server/index.js を読み込んでいるだけだったので、そちらの先頭にbreakpointをつけました。

f:id:dackdive:20190620230941p:plain


2. デバッグ用の設定ファイル(launch.json)を作る

次は、VSCode上でデバッグを行うために必要な設定ファイルを作ります。 コマンドパレット(Macならcmd+shift+P)で

Debug: Open launch.json

を実行します。または、直接.vscode/ディレクトリ下にlaunch.jsonというファイルを作成してもいいです。

コマンドパレットから作成した場合は

{
  // 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",
      "program": "${workspaceFolder}/index.js"
    }
  ]
}

という雛形が作成されているかと思います。


3. デバッグしたいコマンドをprogramに記載する

作成したlaunch.jsonprogramという値が、デバッグ実行されるコマンドです。
なので、ここにnpm scriptとして書かれていたコマンドをコピーしてきます。

注意事項としては

  • npm scriptにstart-storybookと書いていた場合、programには${workspaceFolder}/node_modules/.bin/start-storybookと書く
    • ${workspaceFolder}は必須っぽいです
  • 引数がある場合、programではなくargsという属性に配列で記載する

という点があります。

なので、今回の場合

{
  // 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": "debug start-storybook",
      "program": "${workspaceFolder}/node_modules/.bin/start-storybook",
      "args": ["-p 6006", "-s ./assets"]
    }
  ]
}

となります。

なおnameは識別しやすい好きな名前に変えていいです。


4. デバッグ実行する

ここまでで準備はできたので、コマンドを実行します。
左側のDebugアイコンか、Macだとcmd+shift+Dデバッグ用のパネルが表示されます。

f:id:dackdive:20190620232929p:plain

パネル上部にnameで指定したコマンドが表示されます。目的のコマンドを選んで▶をクリックします。

f:id:dackdive:20190620233142p:plain

無事、最初にbreakpointを置いた箇所で止まってくれました。
左側のパネルのVARIABLES、WATCH、CALL STACK、BREAKPOINTSなどはだいたいブラウザのDeveloper Toolsと同じ機能です。

というわけで、無事やりたいことが実現できました。


よくわかっていないこと

公式ドキュメントによると、launch.jsonconfigurationsの書き方は何種類かあるようです。

そのうちの1つに Launch via NPM というのがあるので、npm scriptはこっちを使えばいいのかと思ってましたがうまく起動できませんでした。
(エラーにはならないが何も起きない)


リファレンス

VSCodeでのデバッグ方法については、公式ドキュメントにかなり多くの情報が載っています。

自分もまだ完全には理解できてません。