WebStorm+Chrome+BrowserSyncでJavaScriptデバッグ


「WebStorm」とJetBrains製品共通のChromeプラグイン「[JetBrains IDE Support](https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji)」を利用すると、ブラウザ上で実行されるJavaScriptでも、本格的なデバッグを行うことができます。

今回はそのデバッグ方法を紹介したいと思います。
使用するWebサーバは最近お気に入りの「[BrowserSync](http://www.browsersync.io/)」を使っています。

<br>

## 今回やる事
* WebStormのコンソールにログを出力
* WebStormのエディタで変数/プロパティの中身をリアルタイム表示
* WebStormでブレークポイントを設定してJavaScriptを一時停止<br>
→　コールスタックを辿ったり、変数/プロパティの中身を調べたり

<br>

## 動作環境
* Windows 7 64bit
* WebStorm 9<br>
→　最近リリースされた最新版
* JetBrains IDE Support 2.0.7<br>
→　Chromeプラグインの最新版

<br>
## 準備

1. [WebStorm](https://www.jetbrains.com/webstorm/)をインストール
1. [JetBrains IDE Support - Chrome ウェブストア](https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji)からプラグインをChromeにインストール
1. BrowserSyncの環境構築<br>
→　以前に「[複数ブラウザ/端末を同期してくれるBrowserSyncが便利](http://qiita.com/yuichiroharai/items/b3daf45ff209f303bf50)」という記事を書いていますので、こちらを参考にしてもらえればと思います。

<br>

## BrowserSyncの起動
デバッグに使用するWebサーバとしてBrowserSyncを起動しておきます。
URLはデフォルトの`http://localhost:3000/`で説明していきます。

<br>

## WebStormの設定
WebStormで任意のプロジェクトを開き、メニューバーから`Run` -> `Edit Configurations...`をクリックし、`Run/Deug Configurations`ダイアログを開きます。
（以下、直訳して「実行/デバッグ構成」と記述します。）


そして、左上の+ボタンを押し、`JavaScript Debug`を選択します。

![WebStorm Sample 1](https://qiita-image-store.s3.amazonaws.com/0/28002/0e251057-c17d-cee7-5624-142ece035a89.jpeg)

<br>
続いて、`Name`の欄には適当な名前を入れ、`URL`に**先ほどのBrowserSyncのサーバURL**、`Browser`はChromeを選択しておきます。

![WebStorm Sample 2](https://qiita-image-store.s3.amazonaws.com/0/28002/aea47570-8593-00f7-949f-c9e2f563a56f.jpeg)

### 設定項目
* Name: BrowserSync Debug
* URL: http://localhost:3000/
* Browser: Chrome
* Remote URLs of local files: 特に設定なし

最後の`Remote URLs of local files`はWebサーバのルートディレクトリがプロジェクトのルートディレクトリと異なる場合に設定します。

この関係が正しく設定されていると、**デバッガ経由でファイルを開いた場合にローカルのファイルを参照してそのまま編集できる**ようになります。
逆に、**正しく設定されていないとWebサーバ上のファイルを読み取り専用で開いてしまいます**ので注意が必要です。

今回は説明を簡略化するためにプロジェクトのルートディレクトリをWebサーバのドキュメントルートと同じにしましたので、特に設定していません。

<br>

## サンプルコード

デバッガを試すためのサンプルコードは以下の通りです。

```js:index.js
// グローバル変数
var global;

$(document).ready(function () {
	console.log("start"); // コンソール出力
	
	// ローカル変数
	var local;

	// set1ボタンクリックで各変数に1を代入
	$("#set1").click(function(){
		local = 1;
		global = 1;
		console.log(global, local); // コンソール出力
	});
	// set2ボタンクリックで各変数に2を代入
	$("#set2").click(function(){
		local = 2;
		global = 2;
		console.log(global, local); // コンソール出力
	});

});
```

HTMLのソースコードは特に載せませんが、idが`set1`と`set2`になっているボタンを配置して、JavaScriptではそのボタンをクリックすると変数`global`と`local`の値を変わるようになっています。

JSファイルは`index.js`という名前でプロジェクトのルートに置いておきます。
また、HTMLファイルは`index.html`という名前で同じくルートに置いておきます。

<br>

## デバッガの起動

次に、WebStormの**画面右上辺りにある虫アイコンのボタンを押してデバッガを起動**します。
左のプルダウンメニューが先ほど作った`BrowserSync Debug`になっている事も念のため確認しておいてください。
今回作ったもの以外に他の「実行/デバッグ構成」も用意している場合はここから選ぶ事になります。

![WebStorm Sample 3](https://qiita-image-store.s3.amazonaws.com/0/28002/994c70ad-7210-2308-72de-c02f979dd054.png)

ちなみに、`Shift+F9`のショートカットを使うと現在の「実行/デバッグ構成」をデバッグモード（虫アイコン）で起動できます。

<br>

Chromeが立ち上がり、先ほど指定したBrowserSyncサーバのサイトが表示されます。

![WebStorm Sample 4](https://qiita-image-store.s3.amazonaws.com/0/28002/01634d27-e99d-b4c7-9369-f8287586b0ef.jpeg)

**WebStormとの接続に成功していると常に黄色いバーが出る**ようになります。

ちなみに、**Chromeのデベロッパーツールを開いてしまうと接続が解除される**ので注意が必要です。
スマホなどのエミュレーターと同時に使用できないのが勿体無いですね。

<br>

## WebStormのコンソールにログを出力
この状態でWebStormの画面左下辺りに目を移すと、デバッガーの`Console`タブに出力したログが表示されています。

![WebStorm Sample 5](https://qiita-image-store.s3.amazonaws.com/0/28002/a01b7fb6-27d7-42af-82d4-38d3f1774d56.png)

また、ログの右側のファイル名+行番号の所をクリックすると、該当するファイルをエディタで開いてくれます。

先ほども説明しましたが、Webサーバのルートディレクトリがプロジェクトのルートディレクトリと異なる場合は`Remote URLs of local files`を正しく設定してないとWebサーバ上のファイルを開いてしまうので注意してください。

ちなみに、Chromeのコンソールと違ってオブジェクトを出力しても中身を展開できないのが残念な所です。

<br>

## WebStormのエディタ上に変数/プロパティの中身をリアルタイム表示
先ほどのサンプルコード(`index.js`)をWebStormで開き、変数の辺りにマウスカーソルを持っていくと現在の値がリアルタイムに表示できます。

![WebStorm Sample 6](https://qiita-image-store.s3.amazonaws.com/0/28002/5e397884-24b1-9074-a180-098aa74e9238.png)

最初は何も入っていないので`undefined`になっています。

ページ内のボタンを押して、変数の中身を変えてみます。

![WebStorm Sample 7](https://qiita-image-store.s3.amazonaws.com/0/28002/cda30099-9e53-ba0d-e0ff-a77a8bf986ba.png)

表示が`1`に変わりました。

サクッと変数/プロパティの中身を確認するのに便利ですね。

<br>

### リアルタイムに中身を表示可能な変数/プロパティ

上の例では分かりやすくグローバル変数を表示させてみましたが、中身を表示できない場合があります。

細かい検証はしてないのですが、ルートのWindowオブジェクトから辿れるプロパティに対する記述箇所であれば中身を表示できるのではと予想をしています。

<br>

例えば、サンプルコードにあるローカル変数の中身は表示できませんでした。

![WebStorm Sample 8](https://qiita-image-store.s3.amazonaws.com/0/28002/8d1668da-6ff7-2509-f04c-b6abf8d71dbc.png)

Windowオブジェクトから辿れないですし、関数の実行前後ではメモリにデータが残ってなさそうです。

<br>
また、いわゆるインスタンス変数もクラスの外側であれば表示可能でしたが、

![WebStorm Sample 9](https://qiita-image-store.s3.amazonaws.com/0/28002/b8966de1-b493-1cb8-0183-d987dc49e68e.png)

クラス内部の記述では`undefined`と表示されていました。

![WebStorm Sample 10](https://qiita-image-store.s3.amazonaws.com/0/28002/65d08b6d-3cc3-a1e4-5887-fbd660dcd2cc.png)

恐らくインスタンスが複数あった時にどの値なのか特定できないからと思われます。

<br>

上記のような変数/プロパティの中身は、この後で説明するブレークポイントを使ってJavaScriptを一時停止すれば中身を確認できるようになります。

<br>

## WebStormでブレークポイントを設定してJavaScriptを一時停止

では、WebStorm上でブレークポイントを設定してJavaScriptを一時停止してみます。

![WebStorm Sample 11](https://qiita-image-store.s3.amazonaws.com/0/28002/398c0e37-225d-28b2-548e-39fed09d7997.png)

エディタ上で停止させたい行の左側をクリックしてブレークポイントを設定します。
ここでは、1個目のボタンのクリック時のコールバック関数の先頭に設定してみました。

<br>

この状態で1個目のボタンを押してみます。

![WebStorm Sample 12](https://qiita-image-store.s3.amazonaws.com/0/28002/c2e7dd55-490c-721f-5c9f-7c1e4ea9c255.jpeg)

JavaScriptの一時停止に伴い、ブラウザ上のページがグレーアウトしました。

ちなみに、画面に表示されている（コマ送りのような）アイコンを押すと、ブラウザ側からもJavaScriptの実行を再開できます。

<br>

WebStormのエディタに目を向けるとブレークポイントの所がハイライトしています。

![WebStorm Sample 13](https://qiita-image-store.s3.amazonaws.com/0/28002/b9cdf5a9-1e7f-5410-aa53-fb7f236d49af.png)

そして、**それぞれの変数の右側に変数名と値が追記**されているのが確認できます。
これは想定外だったので驚きました。さすがですね。

また、先ほどのローカル変数`local`もJavaScriptが一時停止して現在のスコープがはっきりしているためか、中身が(この時点ではまだundefinedですが)ちゃんと表示されています。

<br>

さらに、コンソール出力の時と同様に左下の画面に目を向けると、今度は`Debugger`タブが開いています。

![WebStorm Sample 14](https://qiita-image-store.s3.amazonaws.com/0/28002/3a77a0e8-d368-1476-3c00-33be5ac76940.png)

この画面でコールスタックを辿ったり、プロパティの中身を調べたりする事ができます。

<br>

## 〆

今回は、Chrome+BrowserSyncを例にして説明しましたが、Firefox用のプラグインもあるのでブラウザをFirefoxに変えてみたり、WebサーバもXAMPPなど他のサーバを利用する事もできると思います。
自由に組み合わせが出来るのが良いですね。

また、自分は普段はTypeScriptを使ってるのですが、ソースマップを適切に設定すると同じような事ができるのも確認しています。
まだ、あまり知見が貯まってないのですが、こちらも機会があれば記事にしたいと思います。