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

# やること
[Visual Studio Code](https://code.visualstudio.com/) (以下 VSCode ) を使って [Express](http://expressjs.com/ja/) の開発を始めるまでの手順を記します。

# 環境
事前にインストール済のアプリは次の通りです。
今回は、これを書いている時点の最新バージョンで試しました。

- [Node.js](https://nodejs.org/ja/) (v7.10.0)
- [VSCode](https://code.visualstudio.com/) (1.12.2)

ローカル環境に複数のプロジェクトがある場合はNode.jsのバージョンを切り替えたりしている人もいらっしゃると思いますが、ここではその話は割愛します。

また、私はふだん開発をMacで行っているのでMacのコマンドを叩いた例になっていますが、Windowsのような他のOSの場合は適宜読み替える必要のところがあるかも知れません。ご了承下さい。

# プロジェクト作成
## expressプロジェクトのひな形を作ります。
[express-generator](https://github.com/expressjs/generator) を使います。

express-generatorはglobalにインストールするのがお約束のようですので、そのようにします。
今回は、作成するプロジェクトのディレクトリ名を `qiita_sakura_20170529` にしました。お好みにより変更して下さい。（お気づきかも知れませんが、これを書いている日は肉の日です。終わったら肉を食べます。）
プロジェクトのディレクトリを作成したらそこに移動して次のように進めます。

```bash
$ mkdir qiita_sakura_20170529
$ cd qiita_sakura_20170529
$ npm install -g express-generator
$ express --view=pug .
```

Express はデフォルトのテンプレートエンジンに Jade を使っていますが、[JadeはPugと言う名前になって開発が続けられています](https://github.com/pugjs/pug#rename-from-jade)ので、デフォルトのテンプレートエンジンを [Pug](https://pugjs.org/) に変更するオプションを指定しています。

これでプロジェクトのひな形が作られたので、起動してみます。

```bash
$ npm install
$ npm start
```

デフォルトではポート3000番で待ち受けていますので、 http://localhost:3000/ にアクセスし、　**Express** Welcome to Express と表示されれば成功です！

次に進む前に、一度、ctrl+cで起動したサーバを終了させましょう。


# VSCodeを使ってみます
## その前にAutomatic Type Acquisition (ATA)の話
公式の資料は[ここ](https://code.visualstudio.com/docs/languages/javascript#_automatic-type-acquisition)にあります。
簡単にまとめてしまうと、npm install したパッケージの型定義ファイルを自動的にダウンロードしてIntelliSenseが効くようにしてくれる機能です。
そのためVSCodeを起動して、app.jsを開いた際にダウンロードが実行されて補完が効くようになります。

しかし、ここで問題が発生しました。
私は普段の開発環境では　[ndenv](https://github.com/riywo/ndenv) を用いてプロジェクトごとのNode.jsのバージョン切り替えを行っているのですが、そのため、VSCodeがnpmのコマンドを見つけられずに、ATAの際に下記のようなエラーが発生して型定義ファイルのダウンロードに失敗します。

![スクリーンショット 2017-05-29 16.56.38.png](https://qiita-image-store.s3.amazonaws.com/0/83996/b84e85db-7d33-2bb1-d446-bd51fceb59a3.png)

ちなみにNode.jsのバージョン切り替えに[nvm](https://github.com/creationix/nvm)を利用している人は[こちら](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_common-questions)にある方法で解決できそうです。(わたしはnvm使ってないので試してはいません。)

## 解決策
問題に当たらなかった人はここは読み飛ばしても大丈夫です。
次の2つの方法で回避できるのを確認しました。どちらかをお試し下さい。

### パスを指定してからVSCodeを起動する
v7.10.0のnpmは、私の環境では実際には次のパスにインストールされていました。

- `ls ~/.anyenv/envs/ndenv/versions/v7.10.0/bin`

VSCodeをターミナルから起動した場合は起動元の環境変数を引き継いでいるようなので、パスを設定してからVSCodeを起動します。

```bash
$ export PATH=~/.anyenv/envs/ndenv/versions/v7.10.0/bin/:$PATH
$ code .
```

### 自動ダウンロードを諦める

手動で必要な型定義ファイルをダウンロード（インストール）します。
`package.json`の`dependencies`に記載されているパッケージがインストール対象です。
型定義ファイルがどのパッケージでインストールされるかは[TypeSearch](https://microsoft.github.io/TypeSearch/)から検索できます。

ここでは次のように型定義ファイルをインストールします。

```bash
$ npm install --save @types/node
$ npm install --save @types/body-parser
$ npm install --save @types/cookie-parser
$ npm install --save @types/debug
$ npm install --save @types/express
$ npm install --save @types/morgan
$ npm install --save @types/pug
$ npm install --save @types/serve-favicon
```

手動でインストールするとローカルディレクトリの`node_modules`内に型定義ファイルがインストールされますが、VSCodeはここの型定義ファイルの情報も利用してくれるので、こちらの方法でも型を解決することができます。


# VSCodeを起動してみます

下記のように`code .`でVSCodeを起動します。見つからないとエラーが出る場合は設定が必要なのでやってしまいましょう。[こちら](https://code.visualstudio.com/docs/setup/setup-overview#_cross-platform)の各OSのリンク先に詳細があります。
`.` の部分は作業ディレクトリを指定します。この場合はカレントディレクトリを指定しています。

```bash
$ code .
```

まずは、app.jsを開いてみてください。

おもむろにconsole.等と打つと後に続く候補が自動的に表示されたと思います。
IntelliSenseです！すばらしいです！!
![スクリーンショット 2017-05-29 17.56.23.png](https://qiita-image-store.s3.amazonaws.com/0/83996/948b8091-41db-1cab-8fe3-f80ca2e0922d.png)

また、　`__dirname` にカーソルを合わせてみましょう。これをstringとして認識しており型が分かっています。
__dirnameはNode.jsで定義されているObjectですがこれが分かっていると言うことはNode.jsの型が解決できていると言うことです。
![スクリーンショット 2017-05-29 17.58.05.png](https://qiita-image-store.s3.amazonaws.com/0/83996/a1ab950a-26fa-c6f5-9ed7-96becc5907ac.png)

ついでに、`app.use`のところにカーソルを合わせてみます。こちらも型情報が解決できています。こちらはExpressのオブジェクトなので、Node.js以外も解決できていることが分かります。
![スクリーンショット 2017-05-29 18.03.06.png](https://qiita-image-store.s3.amazonaws.com/0/83996/507f61a0-63ef-b40b-faaf-168c2157fcc9.png)

# デバグしてみます
左のパネルから虫NG的なボタンを選んでください。
![スクリーンショット 2017-05-29 18.08.44.png](https://qiita-image-store.s3.amazonaws.com/0/83996/0b27661b-e46d-9636-c25a-f3b41b5c46d0.png)

いまはなにも設定されていませんので、設定ボタンから設定を行います。
![vscode_express_start_debug.gif](https://qiita-image-store.s3.amazonaws.com/0/83996/3e01891b-c8d1-d8b1-e872-6a0e27346d32.gif)

`.vscode`ディレクトリ（VSCodeのワークスペース用の設定ファイルが格納される）の中に`launch.json`が生成されました。`package.json`の`scripts.start`の設定を読んでくれるので、そのままでいい感じになっており、このまま起動します。
しかし、Node.jsのv7.7.0で`legacy debugger`は[deprecatedされました](https://nodejs.org/en/docs/guides/debugging-getting-started/#legacy-debugger)が、VSCodeのデフォルトの設定では[こちら](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_supported-nodelike-runtimes)の`protocol`の説明を見る限りではデフォルトは`auto`になっておりNode.jsのバージョンが`8.0`以上の時に`inspector`を使うと書いてあります。このままでは、いま試しているv7.10.0では`legacy debugger`で接続してしまうため、明示的に`protocol`を指定したいと思います。
`launch.json`は全体として次のようになります。

```js
{
    // 使用できる Node.js デバッグ属性を学ぶために、インテリセンスを使用してください。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "program": "${workspaceRoot}/bin/www",
            "protocol": "inspector"
        }
    ]
}
```

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

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

![vscode_express_add_breakpoint.gif](https://qiita-image-store.s3.amazonaws.com/0/83996/df29ff94-3188-7e33-5b06-fcee756b8f90.gif)

ブラウザで`http://localhost:3000/`にアクセスするとブレークポイントで止まるのが確認できると思います。
もちろん、コールスタックや変数の中身も覗くことができますので、デバグがはかどります。

## 既に起動中のプロセスへAttachしてみます。

特定の環境でしか発生しないバグのようにローカルでデバグできない場合もあります。
その場合は別のプロセスへAttachしてデバグすることもできます。

そのためにはまず、Node.jsのプロセス自体をデバグで接続できるように起動する必要があります。
まずは、`package.json`をひらいてください。`scripts`のところに`"start": "node ./bin/www"`と言う記載があると思います。その下に、`"debug": "node --inspect=9222 ./bin/www"`と追記してください。
`scripts`全体では次のようになります。

```js
  "scripts": {
    "start": "node ./bin/www",
    "debug": "node --inspect=9222 ./bin/www"
  },
```

これで、次のようにデバグで起動するようになりましたので、起動させておいてください。

```bash
$ npm run debug
```

次はVSCodeのデバッガの設定をします。先ほど作成した`launch.json`にAttachするための設定を追加します。
`launch.json`の`configurations`のところに次の設定を追記してください。

```json
        {
            "type": "node",
            "request": "attach",
            "name": "Attach",
            "port": 9222,
            "address": "localhost",
            "protocol": "inspector"
        }
```

左の虫NGのボタンからデバグの画面を表示すると、再生ボタンの右のドロップダウンから`プログラムの起動`か`Attach`が選べるようになっています。今回は`Attach`を選んで再生ボタンを押すと、先ほど起動したプロセスに接続してデバグが行えるようになります！！
これでさらにいろいろはかどりそうですね！！🤓


# おまけ
## ファイルタイプに応じたアイコンを表示する
[vscode-icons](https://marketplace.visualstudio.com/items?itemName=robertohuertasm.vscode-icons)というExtensionをインストールします。

1. こちらのボタンをクリックして拡張機能の表示に切り替えてください。![スクリーンショット 2017-05-29 18.55.29.png](https://qiita-image-store.s3.amazonaws.com/0/83996/8cc326ab-fe40-c57a-17c5-8c2e5ee338c1.png)

2. 検索ボックスに先ほどの`vscode-icons`を入力します。
3. おそらく先頭にヒットしますのでインストールします。
4. 再読み込みが必要なので、`再読み込む`（あるいは英語表示の場合は `reload`）を行います。

ファイルアイコンのテーマを、Codes（またはファイル） > 基本設定 > ファイルアイコンのテーマ から切り替えられます。
![スクリーンショット 2017-05-29 19.01.36.png](https://qiita-image-store.s3.amazonaws.com/0/83996/99031962-1359-1260-6754-ff8986927ff7.png)

こちらの設定を`VSCode icons`にするとファイル拡張子ごとのアイコンが表示されるようになります。
パグのアイコンがかわいいですね。🐶
![スクリーンショット 2017-05-29 19.06.58.png](https://qiita-image-store.s3.amazonaws.com/0/83996/d67e3909-2330-92a1-802b-c14d30bf8bca.png)


# まとめ
今回はVSCodeでExpressを開発するとどんな感じかやってみました。
私は普段フロントエンドの開発をしていますが、Expressはローカルで開発する際のモックサーバとしてよく利用していますので、その際に非常に便利につかえそうだと感じました。