MQTT.js と TypeScript で Node.js と Web ブラウザの両方をサポートする MQTT クライアントを実装する。


* [MQTT.js](https://www.npmjs.com/package/mqtt)は、[Paho.js](https://www.npmjs.com/package/mqtt)と異なり、標準TCPソケットをサポートしているため、Node.jsでも利用できる。
* ただし、npmモジュールとして提供されており、Node.js用のcommonjs形式のため、そのままではWebブラウザでは利用できない。
* 本記事では、MQTT.jsをAMD形式に変換し、Node.jsだけでなくWebブラウザでも利用できるようにする。
* 本対応により、WebブラウザとNode.jsで兼用のクライアントコードを作成できる。

# TypeScriptによるMQTTクライアント

* MQTT.jsを使うと、Node.js向けとWebブラウザ向けで実装は共通にできる。
* 違いはURL。
	* 通常のMQTT接続（mqtt://・・・）は、TCPソケットが必要のため、Node.jsのみ有効。
	* MQTT over Websocket接続（「ws://・・・」）の場合、Node.jsとWebブラウザ両方で利用できる。
* 以下はNode.js向け。動作確認後、Webブラウザ向けも掲載する。

```src/index.ts
import * as mqtt from 'mqtt'
let client  = mqtt.connect('mqtt://test.mosquitto.org')
client.on('connect', () => {
  client.subscribe('presence')
  client.publish('presence', 'Hello mqtt')
})
 
client.on('message', (topic:String, message:Buffer) => {
  // message is Buffer 
  console.log(message.toString())
  client.end()
})
```

# npm モジュールをインストールする

* [mqtt](https://www.npmjs.com/package/mqtt)がMQTTクライアントライブラリ。
* 「@types/mqtt」はTypeScript用の型定義ファイルを生成する。TypeScriptからmnqtt.jsをインストールする際に必要。
* typescript、webpackは後でビルドに利用する。
	* ライブラリの配布しやすさを考慮すると、typescriptはグローバルにインストールするのではなくpackage.jsonに依存ライブラリとして追記した方がよい。利用する側がNode.jsをインストールしておけば、それ以外はすべてnpmで取れるようになる。

```
npm install mqtt --save
npm install @types/mqtt --save-dev
npm install typescript --save-dev
npm install webpack --save-dev
```

* package.jsonは以下の通り。

```package.json
{
  "main": "dist/index.js",
  "dependencies": {
    "mqtt": "^2.1.3"
  },
  "devDependencies": {
    "@types/mqtt": "0.0.32",
    "typescript": "^2.1.4",
    "webpack": "^1.14.0"
  }
}
```

# TypeScriptソースコードをビルドする

* UMD形式のモジュールを指定しておくと、Node.jsとWebブラウザ兼用にできる。
* Webブラウザの互換性を考慮し、ES5として出力する。

```tsconfig.json
{
    "compilerOptions": {
        "module": "umd",
        "target": "ES5",
        "noImplicitAny": true,
        "noImplicitReturns": true,
        "outDir": "./dist"
    },
    "exclude": [
        "node_modules"
    ]
}
```

# Node.jsで実行する

* MQTTで接続できる。

```
$ $(npm bin)/tsc -p .
$ node .
Hello mqtt
```

* ソースコードを以下のようにMQTT over Websocketに変更しても、Nodeで実行可能。
* ws://の場合、ポート番号を明記する必要あり。

```src/index.ts
import * as mqtt from 'mqtt'
let client  = mqtt.connect('ws://test.mosquitto.org:8080')
client.on('connect', () => {
  client.subscribe('presence')
  client.publish('presence', 'Hello mqtt')
})
 
client.on('message', (topic:String, message:Buffer) => {
  // message is Buffer 
  console.log(message.toString())
  client.end()
})
```

* ビルドして、Nodeで実行できることを確認する。

```
$ $(npm bin)/tsc -p .
$ node .
Hello mqtt
```

# WebpackでMQTT.jsをWebブラウザ用（AMD形式）にビルドする

* MQTT.jsはnpmモジュールであり、commonjs形式のため、そのままではWebブラウザで使えない。
* WebpackでAMD形式に変換して使う。
* Webpackの設定ファイルとして以下を用意する。

```webpack.config.js
module.exports = {
  entry: {
    mqtt: __dirname + '/node_modules/mqtt/mqtt.js',
  },
  output: {
    path: __dirname + '/dist',
    filename: "[name].bundle.js",
    libraryTarget: "amd"
  }
};
```

* npm install でMQTT.jsの依存モジュールを一通り取得しておく。
* webpackを実行し、依存モジュールを含めて1個のファイルにまとめる。Webブラウザから参照することを考慮して、AMD形式にしている。
* 出力先ファイルは mqtt.bundle.js になる。

```
$ npm install node_modules/mqtt
$ $(npm bin)/webpack
```

# Webブラウザで実行する

* MQTT.jsをブラウザで参照するにはrequre.jsの設定ファイルが必要。
* 参照先はAMD形式にまとめたMQTT.js。拡張子の記載は不要。

```src/requre_config.js
var require = {
  paths: {
    mqtt: '../dist/mqtt.bundle'
  }
};
```

* Webブラウザから前掲のindex.jsを参照するには、冒頭でrequre_config.jsを参照しておく。
* 次にdata-mainにindex.jsをインクルードし、srcとしてrequire.jsを指定する。詳細は[require.js](http://requirejs.org/)を参照。


```index.html
<html>
<head>
  <title>test Ws mqtt.js</title>
</head>
<body>
<script src="./src/require_config.js"></script>
<script data-main="./dist/index.js" src="http://requirejs.org/docs/release/2.3.2/minified/require.js"></script>
</body>
</html>
```

index.htmlを開くとコンソールログが出力されている。