Intelligent Technology's Technical Blog

株式会社インテリジェントテクノロジーの技術情報ブログです。

Visual Studio Code で Node.js のデバッグ

こんにちは間藤です。

取り上げるネタとして出遅れた感が否めないですが、Visual Studio CodeのNode.jsデバッグ機能を試してみたのでざっくりレポートしてみたいと思います。
とは言っても、マイクロソフトのドキュメントがよく整備されていますので、ほとんどそちらに記載されていることをなぞるだけになると思いますが・・・

今回の実行環境は以下の通りです。

OS OS X Yosemite (10.10.5)
VS Code 0.7.0
Node.js V0.12.7
npm 2.11.3
nvm 0.26.1

まずはインストール

以下に各OSごとの手順が記載されています。

Setting up Visual Studio Code

Macにインストールする際のポイントは、以下のシェル関数を.bash_profile等に定義しておくことです。

code () { VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" --args $* ;}

こうしておくことで、コマンドラインからVS Codeを起動できるようになります。後述しますが、Node.jsアプリケーションの雛形生成は、コマンドラインベースで行うことになりますので、雛形生成後にすぐにVS Codeを起動できて便利です。

Node.jsアプリケーションの生成

ここからしばらくVS Codeとは直接関係のない話が続きます。
まず、(未インストールなら)Node.jsをインストールします。公式サイトからインストーラを入手するか、nvmを利用するといった方法もあります。

次にExpressベースのNode.jsアプリケーションを自動生成します。このあたりの手順については、VS Codeのドキュメントにも記載されています。

Developing Node Applications

とは言え、VS Codeならではの手順というわけではありませんが。
執筆時点では、上記ドキュメントの冒頭に

New! You can use the VS Code Yeoman Generator to quickly scaffold a Node/Express application in either JavaScript or TypeScript. Check out the readme to get started.

と記載されています。こちらはYeoman専用ジェネレータ(generator-code)を利用して、Expressアプリケーションの雛形生成する方式についてのコメントです。こちらについても後述しますが、まずはexpress-generatorを利用する手順をトレースしてみます。

Expressは4系からexpress-generatorを利用して雛形生成をします。express-generatorをグローバルインストールします。

$ npm install -g express-generator

これでexpressコマンドが利用できるようになりました。※私の環境では、nvmでNode.js環境をセットアップしています。

$ which express
/Users/matoh/.nvm/versions/node/v0.12.7/bin/express

作業ディレクトリ(ここではworkとします)に移動して、

$ mkdir work  && cd $_

expressコマンドを実行し、雛形を作成します。

$ express myExpressApp

package.json(これにモジュールの依存関係が記載されている)も自動生成されますので、必要なモジュールを以下のようにしてローカルインストールします。

$ cd myExpressApp
$ npm install

もし、モジュールのインストールで以下のようなエラーになるようであれば、

npm WARN locking Error: EACCES, open '/Users/matoh/.npm/_locks/jade-60517fba8625f185.lock'

一度npmのキャッシュをクリアすると解消されるかもしれません。

$ npm cache clean

要するに、_locksディレクトリの書き込み権が問題になっています。ですから、キャッシュクリアではなくて、ダイレクトに所定ファイルのアクセス権を調整することでも解決できるとは思います。ただ、どうもそれが正解と思えません。npmのドキュメントに、

03 - Fixing npm permissions | npm Documentation

というのがあって、モジュールをグローバルインストールする際のアクセス権問題を解消する方法について触れています。以前私は、グローバルインストールする際は、sudoするようにしていたんですが、それによってnpmのキャッシュ上にrootユーザで_locksディレクトリができてしまい、ローカルインストールの際に問題を引き起こしたようです。とにかく、npmドキュメントに従ってディレクトリ権限を調整することで、グローバルインストール時にsudoを利用しなければ、_locksディレクトリの問題も起きなくなるのではないかと。そもそも、nvmを利用していれば、ディレクトリ権限の調整も不要だと思います。

・・・脱線してしまいましたが、手順に戻ります。

ここまででExpressアプケーションを動かす準備が整いました。package.jsonに起動用コマンドが用意されていますので、以下のようにしてアプリケーションを起動します。

$ npm start

念のため正常に起動しているかを確認してみます。

$ curl http://localhost:3000
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

ここまでが前準備です。次からVS Codeを利用していきます。なお、Expressアプリは、VS Codeから起動しますので、上記コマンドで起動したアプリは停止しておいてください。

VS Codeの利用

上の手順で作成したExpressアプリのディレクトリで以下のコマンドを実行します。

$ code .

これでVS Codeが起動します。VS CodeのEXPLOREには、Expressアプリのファイルが表示されています。

f:id:IntelligentTechnology:20150908162911j:plain

デバッグ機能を試す前に少々寄り道します。
app.jsを開いてみると、2つ警告が出ているのを確認できます。(F8キーで確認できます)

f:id:IntelligentTechnology:20150908163259j:plain

VS Codeは、このように解決できない変数について警告してくれます。ありがたい機能ですが、このケースでは警告しないでもよい箇所にマークがついてしまっています。これを解決するために、TypeScript Definition Manager (TSD) を利用します。

$ npm install -g tsd
$ tsd query node --action install
$ tsd query express --action install

これによりtypingsディレクトリが作成され、配下にTypeScriptのファイルが2つ出来上がります。

f:id:IntelligentTechnology:20150908164930j:plain

これがNode.jsのデフォルトモジュールと、Expressモジュールのプロトタイプ定義になっています。VS Codeは、これを参照することで、定義に沿った実装になっているかをチェックする仕組みになっているようです。さらに、自動補完もされるようになります。ところで、この手順を踏むと、Expressのuse関数のところで警告が表示されるようになってしまいました。

f:id:IntelligentTechnology:20150908165244j:plain

TypeScriptの定義を確認してみましたが、特に問題はないようでしたので、VS Code側の問題かもしれません。
さらに、jsconfig.jsonファイルを作成することで、VS Codeがモジュール機能を理解して自動補完を強化できるとドキュメントにありますが、このファイルがなくてもここに書かれている自動補完は機能しているようでした。VS Code0.7.0は最近リリースされたばかりなので、ドキュメントのほうが追いついていないのかもしれません。

デバッグ機能を試す

まず、Macでデバッグ機能を利用するには、Mono(.NET Frameworkの互換環境)をインストールする必要があるとのことです。Homebrewでインストールします。

$ brew install mono

バージョン4.0.1がインストールされました。

$ mono --version
Mono JIT compiler version 4.0.1 (tarball Mon Apr 27 01:00:48 PDT 2015)

次にlaunch.jsonというファイルを作成します。このファイルにアプリケーションの起動方法を記載します。と言っても、以下の手順で自動生成することができます。

f:id:IntelligentTechnology:20150908181041j:plain

自動生成する際、package.jsonを参照して、アプリ起動用スクリプト(今回の例だと./bin/www)を決めるそうです。
これで準備が整いましたので、起動ボタンを押下してExpressアプリを起動します。VS Codeがやることは、ターミナルを立ち上げて、デバッグモードでExpressアプリを起動することです。以下がそのコマンドです。

$ 'node' '--debug-brk=55565' '--nolazy' '/Users/matoh/work/myExpressApp/bin/www'

launch.jsonに記述したポート番号と異なる値が指定されているのが少々気になりますが、これで問題なく動作するようです。
デバッガの使い方は特に説明は不要と思いますが、せっかくなのでブレークポイントを設定し、想定通りにデバッガが機能するか確認してみます。

f:id:IntelligentTechnology:20150908183239j:plain

そして、http://localhost:3000にアクセスすると、ちゃんとプログラムが所定の箇所で中断されます。Step Intoを選択すれば、Expressモジュールの関数内でステップ実行できます。

f:id:IntelligentTechnology:20150908183817j:plain

なお、これと同等のことは、Node Inspectorでも実現できます。Node Inspectorを利用する場合は、ChromeのDeveloper Toolsでデバッグすることになります。

Yeoman generator

前述したYeomanのジェネレータについても念のため触れておきます。

Yeoman 1.4.8
generator-code 0.0.23

まず、Yeomanを(未インストールであれば)インストールします。

$ npm install -g yo

Micorsoft製ジェネレータgenerator-codeをインストール。

$ npm install -g generator-code

そして、Yeomanで雛形を生成します。アプリケーション名などいくつか問われるので、それに答えると雛形が生成され、さらにnpm installも自動で実行されます。(そのためコマンドが終了するまでしばらく時間がかかります)

$ yo code

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |   Welcome to the Visual  |
   `---------´   |  Studio Code generator!  |
    ( _´U`_ )    '--------------------------'
    /___A___\    
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of application do you want to create? Node/Express application (JavaScript)
? What's the name of your application? expressApp
? Initialize a git repository? No

生成された雛形を見てみると、express-generatorで生成した場合に比べてファイルが増えています。気づいた点を以下に列挙します。

  • typings以下にファイルが作成されています。(tsdを手動で実行しなくて済みます)
  • mochaのテストスクリプトが作成されています。(package.jsonにtestエントリが追加されています)
  • gulpのスクリプトが作成されています。(Lessの自動コンパイルなどがすぐに利用可能になります)

gulpを試しに使ってみます。gulpをグローバルインストールしていなければ、ローカルインストールされたものを利用します。
生成されたgulpfile.jsを見てみると、いくつかタスクが定義されていますので、これらを使ってみます。
まずは、watchタスクを動かしてみます。

$ ./node_modules/.bin/gulp watch

これでstyles配下のstyle.lessファイルを更新すると、public/stylesheets配下のstyle.cssが自動更新されるようになります。
次にbrowser-syncタスクも試してみます。(Google Chromeをインストールしておく必要があります)

$ ./node_modules/.bin/gulp browser-sync

すると、Expressアプリが起動され、さらにChromeも起動して、Expressアプリを表示します。

f:id:IntelligentTechnology:20150909135730j:plain

そして、views/index.jadeに変更を加えて保存してみます。例えば、最後の行に、

  p Update!

と書き加えて保存します。
すると、Chromeで表示しているページのほうも自動的に更新されます。

f:id:IntelligentTechnology:20150909140202j:plain

というように、generator-codeを利用すると、いろいろとお膳立てをしてくれます。


Node.jsのデバッグ機能にフォーカスするつもりでしたが、それ以外のことに随分と文面を割いてしまいました。
それにしても、マイクロソフトのプロダクトをMacで利用するというのは新鮮に感じます。上に紹介したマイクロソフトのドキュメント、画面キャプチャがMacのものなんですね。マイクロソフトがよりオープンになっていくというのは、エンジニアとしては有難いことですが、それを追いかけて行くのもまた大変。それを楽しめるようでないとやってけないのかなと感じた次第です。

(追記)
この記事を書き終わったタイミングで、Node.jsのv4.0.0(安定版)がリリースされました。

node/CHANGELOG.md at master · nodejs/node · GitHub

記事を書くタイミング、悪かったみたいです。。。