Node-RED で遊んでみる第一歩: Web ページを表示してみる

とある勉強会に参加し、[Node-RED](https://nodered.org/) を初体験！なかなか面白いな、と感じましたのでご紹介します。

初心者向けサンプルを幾つか眺めたのですが「Webページを表示するサンプル」がシンプルで理解し易いですし、私の得意分野なのでご紹介します。

# 簡単な始め方

[IBM Cloud カタログ](https://console.bluemix.net/catalog/) にアクセスし、「スターターキット」にある「Node-RED Starter」をクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/1e9a6411-4fea-0c29-572f-f084baebb766.png)

「アプリ名」と「ホスト名」にユニークな名前を入力して「作成」ボタンを押せばok。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/3e2a6ed8-1153-3295-39fa-58e14e027cce.png)

アプリが実行中であることを確認して、「アプリURLにアクセス」でNode-REDアプリを起動します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/d5ddb7f3-b37f-bc0f-fb80-3c6f70215e53.png)

最初の起動時にはパスワードの設定ができますので、設定しておくと良いでしょう。

無料(ライト)アカウントの方は、他に起動しているアプリがあったら先に終了しておかないと、メモリ不足でエラーになります。

# IDやパスワードを忘れた場合

もし設定したパスワードを忘れてしまった場合は [コチラの動画](https://www.youtube.com/watch?v=2jMZXcUjj6k) を参照してください。

…と書いていましたが、動画だとわかりにくい、というご意見がありましたので簡単に説明しておきます。

まずIBM Cloudダッシュボードで作成したNode-REDアプリケーションを開き、左の「ランタイム」メニューを選択した後、「環境変数」を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/0e057ee8-ab34-ce89-4283-f921becd441c.png)

そして下にある「ユーザー定義」のところでIDとパスワードを設定すると、こちらでの設定が優先されるようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/0c0fb54f-de12-3b3d-6899-5a28fcc69472.png)

NODE_RED_USERNAME にログインIDを、NODE_RED_PASSWORD にパスワードを指定します。指定した後はアプリを再起動させたほうが良さそうですね。

# まずはWebページを作成してみる

Node-REDアプリを開始すると、真ん中に空っぽの作業エリアが表示されるとおもいます。左側のノード置き場から、以下の3つのノードをドラッグして、作業エリアに配置してみましょう。

* 「入力」エリアにある「http」ノード
* 「機能」エリアにある「template」ノード
* 「出力」エリアにある「http response」ノード

左上からこれらのノードを順に並べると、以下のようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/fe1f38af-198c-a570-cf5e-cdf6b3c18208.png)

なお出力の「http response」ノードは、作業エリア上では「http」と表示されるので注意が必要です。ノードの形状で入力の「http」ノードと見分けます。

次に、これらのノードを繋いでみましょう。小さな灰色の **□** がコネクタで、ドラッグすることで繋ぐことができます。

「http」ノードと「template」ノード、そして「template」ノードと「http response」ノードを繋ぐと、以下のようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/ee158136-034d-3893-ef94-162968b1be1a.png)

入力の「http」ノードの上に赤い三角が表示されていて、これは何か設定に問題があることを示しています。ダブルクリックでノードの編集画面を開き、URL欄にWebページの表示用のアドレス (今回は "/page1") を入力して、「完了」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/5fb55f04-1681-f719-ef8d-3a8013d56889.png)

必要な値が入力されたので、さきほどの赤い三角マークが消えています。また入力の「http」ノードの表記が入力した内容に変わりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/ec8c8ad0-ef9c-4599-4c8a-4ca77cb896b3.png)

これで問題なさそうなので、右上の「デプロイ」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/3ddb6c65-313b-7be3-0c5f-9b0df5d7125b.png)

「デプロイが完了しました」というメッセージが表示されればokです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/7c099933-c182-c28f-504e-858bfa89e363.png)

Node-REDアプリを起動している同じサーバー上で、さきほど設定した /page1 URLにアクセスしてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/ce59566e-7f7e-ffea-c630-786ab29eb17f.png)

上記のようにちょっと謎なメッセージが表示されれば、問題なく動作しています。

さて、謎のメッセージをちゃんとしたコンテンツに変更してみましょう。こんどは機能の「template」ノードをダブルクリックして編集画面を開き、形式を「平文」に、構文を「HTML」に変更して、その下の入力欄に適当なHTMLコンテンツを入力してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/47ec6012-e50b-7f8c-e3ff-b0b4a5355533.png)

再び「デプロイ」ボタンをクリックしてWebページを確認すると、表示内容が「template」ノードで設定したものに置き換わっているのが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/421517ad-5dea-b8ab-2d8a-d632037918a3.png)

これでWebページの公開ができました！3つのノードを並べて繋ぎ、入力ノードに表示用のURLを設定し、機能ノードに表示するHTMLを設定しただけでWebページ作成が完了したわけです。

簡単でいいですね！

# Node.js的にサンプルを理解してみる

Node.js + Express な環境で同様なWebページを表示するサンプルコードは以下になります。

```js
app.get('/page1', function(req, res) {
  var contents = '<h1>Hello Node-RED</h1><p>This content is in a template node.</p>';
  res.send(contents);
});
```

app.get の行が入力「http」ノードに対応します。最初の引数 '/page1' がノードに指定した値と同じですよね。この行の役割は、'/page1' というURLに対するWeb表示リクエスト(GETリクエスト)を、以降の処理と結びつけることです。

次の var contents の行が機能「template」ノードに対応します。表示する内容(コンテンツ)を定義する役割があって、変数に代入している内容は、ノードに設定したHTMLコードと同じですよね。

次の行の res.send の行が出力「http response」に対応する部分です。生成されたコンテンツをブラウザに返して表示させる役割があります。

Node.js はイベント駆動に適したプログラミング環境ですが、Node-REDはそれをうまくビジュアル化し、利用できる環境なのだな、とちょっと感心してみたり。

# ページを追加してみる

Webページを追加してみましょう。URLは '/page2' とします。

まずはさきほどと同様、入力「http」ノードと、機能「template」ノードを配置します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/488129be-7bbb-4e64-6f23-f63150749570.png)

そしてノードを繋ぐわけですが、最後の出力「http response」ノードは特別な設定をしていないので、さきほどのものを流用します。以下のような感じです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/ae4f9859-aab3-6241-54c3-7db653d5b8ba.png)

そして入力「http」ノードにURLを設定し、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/d8e85627-e131-94a1-4686-669af9081672.png)

機能「template」ノードにコンテンツの内容を設定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/d97b6093-4338-b483-2c61-5c1aefdb4e4b.png)

すると以下のようになりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/08f95603-83bc-c14b-8034-31f468ef2b71.png)

※ ノードの位置をちょっと動かして見栄えを調整しています

「デプロイ」して新しい '/page2' ページが公開されたことを確認しましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/33be547f-6eec-ca36-bd29-b6054715da0c.png)

# ちょっと機能を足してみる

新しく作成した '/page2' ですが、元のページとあまり変わらず面白みに欠けますね。ありがちなネタですが、日付けを追加表示してみましょう。

さきほど追加した「http」ノードと「template」ノードの間に、処理用のノードを追加します。まずは両ノードの接続を削除(接続している線をクリックして選択し、DELキーで削除)した後、ノードの位置を動かして空きスペースをつくります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/5eda00ca-81f3-63a1-684f-892246832b35.png)

左のパレットの「機能」欄にある「function」ノードを空きエリアに配置し、左右のノードと接続します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/4b235ca5-1f99-b7f4-6be1-4f9213255b50.png)

機能「function」ノードをダブルクリックして編集画面を開くと、「コード」欄に最初から以下のようなコードが記載されています。

```js
return msg;
```

その前に以下のように2行を追加します。

```js
var d = new Date();
msg.mydate = d.toISOString().substring(0,10);
return msg;
```

こんな感じです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/979c5b6e-e4d9-1900-b0a5-b35c529a765f.png)

さて、ここで「デプロイ」して実行しても、'/page2' Webページの表示は変わりません。上記の追加したコードでは 'mydate' に値をセットしていますが、この値をどこに表示するか、をまだ指示していないので、結果に影響を与えないわけです。

'/page2' 用の「template」ノードをダブルクリックで編集状態にし、形式を「Mustacheテンプレート」に変更のうえ、テンプレート部分のHTMLを修正します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/875cdb6c-22d5-344e-a812-0197e28bfd02.png)

修正したHTMLは以下です。

```html
<h1>Page2</h1>
<p>Today is {{mydate}}.</p>
```

最終的なノードの状態は以下になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/d46bc9ac-929f-72a3-91c1-5fecfb86cbb4.png)

「デプロイ」してページを表示すると、今日の日付けが表示されていることがわかります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/6c653694-ba13-d21d-7e2e-2656424f7bfb.png)

# Mustacheテンプレートって何？

「Mustache」って耳慣れない言葉ですね。日本語で言えば「口ひげ・口髭」だそうで。以下のまとめがわかりやすいです。

* [mustache記法について簡単にまとめてみた](https://qiita.com/sengok/items/1d958348215647a5eaf0)

今回は一番最初に説明されている、

```
{{key}}
keyで受け取った値に置換します
```

を利用しています。「function」ノードで mydata という変数に設定した日付テキストを、この方法で置換して、HTML表示に埋め込んでいるわけです。

※ 次のノードに渡したい変数を var mydata = ... と宣言せずに、msg.mydata = ... と定義するのは、Node-RED 固有のお作法です

上記のまとめを読むと、{{{key}}}でHTMLエスケープしないで置換、Listの中身を列挙、などいろいろな機能があり、応用範囲は広そうです！

# 今回のサンプル

作成したフローはメニューの「書き出し -> クリップボード」からJSON形式での保存が可能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/5772e42d-71fb-3fc5-cdcc-cb5acabbd926.png)

今回作成したフローのJSONを以下に貼っておきますね。

```json
[{"id":"45574109.100fb","type":"http in","z":"c3623e04.bebe9","name":"","url":"/page1","method":"get","upload":false,"swaggerDoc":"","x":90,"y":40,"wires":[["aeea9253.4648f"]]},{"id":"aeea9253.4648f","type":"template","z":"c3623e04.bebe9","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"plain","template":"<h1>Hello Node-RED</h1>\n<p>This content is in a template node.</p>","output":"str","x":420,"y":40,"wires":[["97e1fe31.a4838"]]},{"id":"97e1fe31.a4838","type":"http response","z":"c3623e04.bebe9","name":"","statusCode":"","headers":{},"x":570,"y":40,"wires":[]},{"id":"2484fc4b.d0f414","type":"http in","z":"c3623e04.bebe9","name":"","url":"/page2","method":"get","upload":false,"swaggerDoc":"","x":90,"y":100,"wires":[["d6a29b0e.ba1598"]]},{"id":"56c6a312.188d3c","type":"template","z":"c3623e04.bebe9","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<h1>Page2</h1>\n<p>Today is {{mydate}}.</p>","output":"str","x":420,"y":100,"wires":[["97e1fe31.a4838"]]},{"id":"d6a29b0e.ba1598","type":"function","z":"c3623e04.bebe9","name":"","func":"var d = new Date();\nmsg.mydate = d.toISOString().substring(0,10);\nreturn msg;","outputs":1,"noerr":0,"x":250,"y":100,"wires":[["56c6a312.188d3c"]]}]
```

利用は同じくメニューで「読み出し -> クリップボード」から可能ですので、自身の編集画面に配置していろいろ遊んでみてください。

# おわりに

Node-RED は簡単に操作でき、見た目もわかりやすい、非常に良いビジュアル志向のロジックの記述環境だとおもいます。

Webページを表示すること、は必ずしも Node-RED が得意とする分野では無いとおもいますが…

* たった3ノードで表示ロジックを記述できるシンプルさ
* 作成と同じWebブラウザで確認できる手軽さ
* 変更が見た目でわかる納得感

という面から、最初にいろいろ試してみる土台としては、個人的にお勧めしたいサンプルです。

[続編](https://qiita.com/yamachan360/items/795095a77a45766ebdec) も投稿しましたので、こちらも読んでいただけると嬉しいです。

ではでは。