Visual Studio CodeでExpressの開発環境を作ってみます

- 2017/05/30追記
    -  [こちら](http://qiita.com/t-mimura/items/048bf2e3baa15daf30d8)に新しく同じ目的の記事を書き直しましたので、現在ではこちらをご覧下さいませ。
    -  http://qiita.com/t-mimura/items/048bf2e3baa15daf30d8

- 2016/03/28追記
    - 文中では `tsd` を利用していますが、現在は `typings` を使うことが推奨されていますので、そちらをご利用ください。取り急ぎ注記のみで申し訳ありません。（タイミングがあれば書き直します...）


# はじめに

この記事は [さくらインターネット Advent Calendar 2015](http://qiita.com/advent-calendar/2015/sakura) 18日目の記事です。
クリスマスまであと1週間です。たぶん。

普段はフロントエンドの開発をしていますが、今回はExpressのことを書きたいと思います。

# やること

Visual Studio Code (以下 VSCode) を使ってExpressの開発を始めるまでを流してみます。


# 環境

スタート地点は次の2点がインストールされている状態です。
- Node.js 5.2.0
- VSCode 0.10.3

Node.jsのインストールは、macなら[ndenv](https://github.com/riywo/ndenv)、windowsなら[nodist](https://github.com/marcelklehr/nodist)のようなバージョン管理の仕組みを使うと便利かと思います。
私は開発では主にMacを利用していますので、以下、ndenvのコマンドを記載しますが、他のバージョン管理を使っていてもおおよそ同じ感じのはずです。

例えば、Node.js v5.2.0のインストールは次の通り。

```bash
$ ndenv install v5.2.0
```


# プロジェクト作成

## expressプロジェクトのひな形を作ります。

express-generatorを使います。
プロジェクト間の、パッケージのバージョン管理の点から、なるべくグローバルにインストールしたくないので作業用ディレクトリを作成します。

```bash
$ mkdir working
$ cd working
$ ndenv local v5.2.0
$ npm init --yes
$ npm install express-generator@4.13.1
$ ./node_modules/express-generator/bin/express ../qiita_sakura_20151218
$ cd ..
```

これでプロジェクトのひな形ができました。

`express-generator`を使った作業用ディレクトリはもう不要なので消してしまいます。

```bash
$ rm -rf working
```

## 起動してみます

```bash
$ cd qiita_sakura_20151218
$ ndenv local v5.2.0
$ npm install
$ npm start
```

ブラウザで `http://localhost:3000/` にアクセスし、 **Express** Welcome to Express と表示されれば成功です！

## VSCodeを使ってみます

一度、`ctrl+c`で起動したサーバを終了させましょう。
下記のように`code .`でVSCodeを起動します。見つからないとエラーが出る場合は設定が必要なのでやってしまいましょう。(`.`の部分は作業ディレクトリを指定します。この場合はカレントディレクトリを指定しています。)
[設定方法](https://code.visualstudio.com/docs/editor/setup)

```bash
$ code .
```

まずは、`app.js`を開いてみてください。
おもむろに`console.`等と打つと後に続く候補が自動的に表示されたと思います。
`IntelliSense`です！

## 型情報の解決

これでもだいぶ便利ですが、`__dirname`など、Node.jsの持ち物が解釈できていないためにWarningがでています。
これを解決したいと思います。

TypeScriptの仕組みになりますが、利用しているパッケージ/外部モジュールの型情報を知るための仕組みで [`TypeScript Definition Files`](http://definitelytyped.org/) と言うものがあります。

これは、簡単に言うとTypeScriptで型定義されたファイルを、JavaScriptのパッケージ(モジュール/ライブラリ)ごとに作成しておき、それを参照して解決する仕組みです。定義されている型情報のファイルは[リポジトリ](https://github.com/DefinitelyTyped/DefinitelyTyped)に登録されており、そこから取得すれば利用可能です。

ここでは、型定義のファイルを取得(インストール)するのに[TSD](http://definitelytyped.org/tsd/)を利用します。

### インストールしたdefinition fileの保持について

操作が煩雑になってしまうため、いったんTSDをグローバルにインストールしてdefinition fileのインストールを行ってみたいと思います。

```bash
$ npm install -g tsd
$ ndenv rehash
```

下記コマンドを実行すれば必要なdefinition fileがインストールできますが、、、(まだやらないでください)

```bash
$ tsd query node　--action install
$ tsd query express　--action install
$ tsd query serve-static --action install
$ tsd query mime --action install
```

または

```bash
$ tsd query node express serve-static mime --action install
```

ここでは、ソースコードをgit等のバージョン管理に登録することを想定し、あとで環境が再現できることを考えて、インストールしたファイルを覚えておくようにしたいと思います。
TSDもnpmやbower等のようにインストールしたファイルを覚えておく仕組みがあります。まずは、TSDの設定ファイルを生成します。

```bash
$ tsd init
```

これで作業ディレクトリ直下に`tsd.json`が生成されました。すでに必要な設定は記載されているので、特に編集の必要はありません。
このままdefinition fileのインストールを続けます。

```bash
$ tsd query node express serve-static mime --action install --save
```

実行すると、typings ディレクトリ内にdefinition fileがインストールされたとともに、tsd.jsonファイルにインストールしたdefinition fileが記されたと思います。

いったん削除して同じdefinition fileがインストール可能かやってみたいと思います。
手動で消します。。

```bash
$ tsd purge
$ rm -rf typings
```

消しました。tsd.jsonをもとに再インストールします。

```bash
$ tsd reinstall
```

またtypingsディレクトリが作成されて、その中にdefinition fileがインストールされたはずです。これで、tsd.jsonファイルがちゃんと作成できたのが確認できたので、次は、これを簡単に復元できるように、`npm install`を行った後に自動でインストールするようにしたいと思います。
下記のように`package.json`の`scripts`のところに`postinstall`を追加してください。

```json:package.json
{
  "name": "qiita_sakrua_20151218",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www",
    "postinstall": "tsd reinstall"
  },
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0"
  },
  "devDependencies": {}
}
```

`npm`コマンド経由の場合は`node_modules`がパスに含まれるため、グローバルじゃなくても大丈夫になりましたのでローカルへインストールし直したいと思います。

```bash
$ npm uninstall --global tsd
$ ndenv rehash
$ npm install --save-dev tsd
```

いちおう正しく動作するか確認しましょう。
一度削除して、インストールします。

```bash
$ rm -rf node_modules typings
$ npm install
```

Nodeのパッケージもdefinition fileもインストールされれば成功です。

## 型解決の確認

VSCodeに戻ってみましょう。
`__dirname`からWarningが消えていると思います。これは作業フォルダの中の型定義ファイルをVSCodeが読み込んでくれた結果です。
`__dirname`にマウスカーソルを当ててみるとツールチップが表示され、`string`と認識しているようです。
エディタのカーソルを`__dirname`において`F12`を押すと定義に飛ぶことができます。正しく認識しているようです。（ **ctrl** + **-** で元の場所に戻れます。)

![vs_code___dirname_jump.gif](https://qiita-image-store.s3.amazonaws.com/0/83996/2a66a65e-6068-4341-960c-c7d2f5a43c9b.gif)

これでコーディングもはかどりそうです！

## jsconfig.json

ところで、ここでおもむろに`let hoge = 'hoge';`とか入力してみるとエラーになりました。
エラーメッセージを見ると

> ES6でしか使えないよ！`jsconfig.json`ファイルを作ってターゲットに`ES6`を指定してね。

という感じになっていると思います。
Node.jsは多くのES6の機能をサポートしている [^1] ので、`jsconfig.json`ファイルを作ってES6の構文でエラーにならないようにしたいと思います。

[^1]: ざっくり感想を言ってしまいました。詳しくは[こちら](https://nodejs.org/en/docs/es6/)。

下記内容で作業ディレクトリ直下にファイルを作成してください。

```json:jsconfig.json
{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs"
    }
}
```

これでOKです。エラーが消えたでしょうか。


## デバグしてみます

VSCode上からNode.jsのアプリケーションを簡単にデバッグすることができるので試してみましょう。
まず、VSCodeの左のボタンから虫を駆除している感じのアイコンを押してください。いまは何も設定されていませんので、設定ボタンから設定を行います。

![vs_code_debug_setting_start.gif](https://qiita-image-store.s3.amazonaws.com/0/83996/32513c3f-af43-2c37-6ddc-a529e449a76c.gif)

すると、`.vscode`ディレクトリ（VSCodeのワークスペース用の設定ファイルが格納される）の中に`launch.json`が生成されました。`package.json`の`scripts.start`の設定を読んでくれるので、そのままでいい感じになっているはずです。

再生ボタンを押してアプリケーションを起動してみましょう。（あるいは`F5`を押下）
Debug Consoleが開いて起動しました。が、このままではよく分かりませんので、ブレークポイントを設定してみます。

ブラウザでアクセスしたときの処理がわかりやすいと思いますので、`routes/index.js`を開き、`/`のGET処理でブレークを設定します。

![vs_code_set_break_point.gif](https://qiita-image-store.s3.amazonaws.com/0/83996/1b5fd1f9-72d3-167d-e208-430fdcb583ea.gif)

ブラウザで`http://localhost:3000/`にアクセスするとブレークに止まるのが確認できると思います。
Local変数の状態やCall Stackなど一通り必要なものはそろっています。気づきにくいですが、Debug Consoleの下に（Consoleですので）入力欄があります。ここで変数の値を書き換えたりとかいろいろできます。便利です。


# まとめ

今回はVSCodeでExpressを開発するとどんな感じかやってみました。

私は普段はフロントエンドの開発を行っており、いまは TypeScript + AngularJS のプロジェクトを主にやっているためVSCodeをつかっていますが、Node.jsのデバグは、GulpやMock Serverなどをコーディングしているときにも有効なのでこれからは積極的に利用していきたいです。

Happy Hacking! :christmas_tree: