Node.jsでWebもGUIツールも同時に開発する

目的
----

Node.jsからBLEを操作しようと思っていて、せっかくだからnode-webkitでデスクトップツールにしようと調査がてら途中まで作ってみました。作り方に工夫が入りますが、Browserrifyを使えばexpressのアプリをそのままnode-webkitにすることができます。
ちなみに今回データバインディングフレームワークのVue.jsを使ってみましたがなかなか調子良いです。あと今回はやってないですがBrowserifyを使うとフロントでもrequireが使えるのでNode.jsのモジュールをフロントの世界に持ち込むことができます。これは本当にすごいですね。Node.jsがフロントの世界を逆に食っちゃったというか。

前提
----

* Node.jsがインストールされている
* node-webkitがインストールされている
* nuwk!がインストールされている

手順
----

### nuwk!でアプリの雛形を作る

nuwk!はnode-webkitの便利ツールです。今回はble-consoleというアプリ名にしました。鉛筆マークを押下するとエディタ（自分の環境だとSublime Text）が開きます。

![nuwk_.png](https://qiita-image-store.s3.amazonaws.com/939/39813/b0396d0f-4bd1-cb40-fa20-5393d02b2b57.png)

この時点で下記のようなアプリケーション構成になっています。Appの中にファイルを作成していきます。

```
$ ls -l
total 0
drwxr-xr-x  8 takayukii  staff  272 11 30 00:26 App
drwxr-xr-x  2 takayukii  staff   68 11 29 22:33 Build
drwxr-xr-x  4 takayukii  staff  136 11 29 22:33 Resources
```

### expressで動作させる

下記に作成したアプリケーションをコミットしています。
https://github.com/takayukii/BLE-Console

このブランチです。
https://github.com/takayukii/BLE-Console/tree/express-nodewebkit

```bash
$ rm -Rf App
$ git clone https://github.com/takayukii/BLE-Console
$ mv BLE-Console App
$ git fetch
$ git branch -a
$ git checkout -b express-nodewebkit remotes/origin/express-nodewebkit
```

express、Browserify、Gruntをインストールします。

```bash
$ npm install
```

もしかしたら下記も実行する必要があるかも…。

```bash
$ npm install -g browserify
$ npm install -g grunt-cli
```

アプリケーションをexpressで実行します。

```bash
$ grunt browserify
$ node app.js
```

下記へアクセスします。
http://localhost:3000 

延々とログが流れるというイメージになっています（ログはダミー）。Clearボタンを押すとログが消えます。

![BLE-CONSOLE.png](https://qiita-image-store.s3.amazonaws.com/939/39813/32eb79cc-76c7-be22-40b4-e37af1f8501e.png)

### アプリケーションの内容の整理①

#### Vue.jsを利用したデータバインディング

今回、Vue.jsは初めてまともに触ったんですが、データバインディングの良さがよく分かりました。今回、延々とsetIntervalでログを流してるんですが、jQueryのようにDOMを意識したコーディングがなくなりました。

やったのはHTMLを下記のように用意しておき、

```html:index.html
<!DOCTYPE html>
<html id="ble-console">
  <head>
    <title>{{title}}</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="./css/main.css" media="all">
  </head>
  <body>

    <div class="ble-console" >

      <div class="console">
        <ul class="custom-ul">
          <li v-repeat="logs">
            <p class="log-content">{{content}}</p>
            <p class="log-date">{{date}}</p>
          </li>
        </ul>
      </div>

      <div class="command">
        <p id="title">{{title}}</p>
        <button class="custom-btn" id="clear" v-on="click: clear( this )">Clear</button>
      </div>

    </div>
  </body>
</html>

<script type="text/javascript" src="./js/vue.min.js"></script>
<script type="text/javascript" src="./bundle.js"></script>
```

下記のようなオブジェクト操作だけでログの垂れ流しと消去ができました。これは気持ち良い。

```js:main.js
var Log = require( './log' );

var vm = new Vue({
    el: '#ble-console',
    data: {
        title: 'BLE-CONSOLE',
        counter : 0,
        logs: []
    },
    created: function() {
      var self = this;
      console.log("initialized!");
      setInterval(function(){
        self.logs.push(new Log(self.counter ++));
      }, 3000);
    },
    methods: {
        clear: function () {
            this.logs = [];
        }
    }
});

```

### デスクトップアプリとして動作させる

node-webkitとして実行します。

```bash
$ /Applications/node-webkit.app/Contents/MacOS/node-webkit .
```

するとアプリケーションが起動します。

![BLE-CONSOLE.png](https://qiita-image-store.s3.amazonaws.com/939/39813/60170424-57fe-3134-cc54-33259f6c1734.png)

nuwk!でBuild Applicationを行うとそのまま単体で実行可能なAppファイルがビルドされます。このバイナリはnode-webkitが入ってない環境でもデスクトップアプリケーションとして動作します。

### アプリケーションの内容の整理②

#### Browserifyを利用してフロントのJSもモジュール化する

フロントのJavaScriptでは、Node.jsでは当たり前に使っているrequireが利用できません。そのため、本来フロントとNode.jsで少し作り方を変える必要があります。ですが、Browserifyを使用すると、requireを使っていてもフロントで動かすコードに変換することができます。今回はBrowerifyを利用しているので、フロントでもnode-webkitでも同じコードで動作させることができました。

```js:main.js
var Log = require( './log' );

var vm = new Vue({
    el: '#ble-console',
    data: {
        title: 'BLE-CONSOLE',
        counter : 0,
        logs: []
    },
    created: function() {
      var self = this;
      console.log("initialized!");
      setInterval(function(){
        self.logs.push(new Log(self.counter ++));
      }, 3000);
    },
    methods: {
        clear: function () {
            this.logs = [];
        }
    }
});
```

```log.js
module.exports = function(content){

  this.content = content;
  this.date = new Date();

  this.isOld = function(){

    var now = new Date();
    var diff = now.getTime() - this.date.getTime();

    // 1分以上経ってる
    if((diff / (1000 * 60)) > 1){
      return true;
    }else{
      return false;
    }
  };

  console.log(this.date, this.content);

};
```

__Browserifyの実行__

下記で、bundle.jsにmain.jsがrequireしているものも含めて結合されたbundle.jsが作成されます。

```bash
$ browserify js/main.js -o bundle.js
```

ただ、毎回マニュアルで実行するのは手間になるため、通常はGruntやGulpなどで自動化されるようです。今回はGruntを使ってみました。下記を実行すると変更を検知し変更があれば新しくbundle.jsが作られるようになっています。

```bash
$ grunt
```

参考
----

http://qiita.com/airtoxin/items/c028bd913ded1d04ad1e
http://yutapon.hatenablog.com/entry/2014/03/09/205231