Node.js　簡易掲示板　備忘録

Node.jsの勉強がてら簡易掲示板のようなものを作ったので自分様にまとめ。
使用したmoduleは**http**、**fs**、**ejs**、**querystring**の4つ。

# httpモジュール
httpモジュールはその名の通り、HTTPサーバやHTTPクライアントとしての機能を構築するためのモジュール。
# fsモジュール
fsモジュールはファイル操作する時に使用するモジュール。
第一引数に読み込みたいファイルのパスを指定する。
第二引数に文字コードを指定する。
第三引数にファイルを読み込んだ後に実行したい関数を指定する。

fsモジュールには2つのメソッドが用意されている。
> readFile() 非同期処理
readFileSync() 同期処理

# ejsモジュール（テンプレートエンジンと呼ぶ）
> webサービスやブログの様に全体のヘッダー、フッターが共通していて、内容だけ違う様なケースに使用するパッケージ。共通するところはそのまま使って、切り替えるところだけ切り替えることを実現してくれるパッケージ。

[Node.jsのテンプレートエンジンejsを使ってみた](https://www.tech-tech.xyz/nodejs-ejs.html)

# querystringモジュール
クエリ文字列をオブジェクト形式に変換するモジュール。
クエリ文字列とはWEBアプリケーションなどで、クライアントからサーバーにパラメータを渡すのに使われる表記法。
URLの末尾に?を付けて、続けて「名前=値」の形式で記述する。値が複数あるときは「&」で区切る。

例) `http://example.com/foo/var.php?name1=value1&name2=value2`

# 全体のコード
サーバとしてのコードが記述されているserver.jsファイル

```js:server.js
var http = require('http'),
    fs = require('fs'),
    ejs = require('ejs'),
    qs = require('querystring');
var settings = require('./settings.js');
var server = http.createServer();
var template = fs.readFileSync(__dirname + '/todolist/bbs.ejs', 'utf-8');
var posts = [];
function renderForm(posts, res){
    var data = ejs.render(template, {
        posts: posts
    });
    res.writeHead(200, {'content-Type': 'text/html'});
    res.write(data);
    res.end();
}
server.on('request', function(req, res){
    
        if(req.method === 'POST'){
            req.data = "";
            req.on("data", function(chunk){
                req.data += chunk;
            });
            req.on("end", function(){
                var query = qs.parse(req.data);
                posts.push(query.name);
                renderForm(posts,res);
            });
        }else{
            renderForm(posts, res);
        }
   
});
server.listen(settings.port, settings.host);
console.log("server listening...");
 
```
ブラウザで表示するinputタグと、inputタグに書き込んだデータを表示するコードが記述されているhello.ejsファイル

```js:hello.js
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>hello</title>
    <meta charset="utf-8">
</head>
<body>
    <form method="post">
        <input type="text" name="name">
        <input type="submit" value="Post!">
        <ul>
            <% for (var i = 0; i < posts.length; i++) {%>
            <li><%= posts[i] %></li>

            <% } %>
        </ul>
    </form>
</body>
</html>

```
webサーバーとして機能する様にportとhost IPを設定したsetting.jsファイル

```js:setting.js
exports.port = 1337; // 任意
exports.host = '126.0.0.2'; // 任意
```

# server.jsファイルでしていること

```js:server.js
// サーバーとして必要なモジュールを読み込む
var http = require('http'),
    fs = require('fs'),
    ejs = require('ejs'),
    qs = require('querystring');
// サーバーとして必要な設定を記述してファイルを読み込む
var settings = require('./settings.js');

// createServerメソッドを呼び出してhttp.serverオブジェクトを作成する。此奴がNode.jsのサーバとなる部分
var server = http.createServer();

// 同期的に（同期処理で)テンプレートコードが記述されているを読み込む
var template = fs.readFileSync(__dirname + '/todolist/hello.ejs', 'utf-8');

// postされてきたデータを格納するための配列を定義。こいつをhello.jsでfor文を回し表示する。
var posts = [];

// http.serverオブジェクトがクライアントからリクエストを受け取った時に発火する処理を記述
function renderForm(posts, res){

    // 上記で読み込んだテンプレートのレンダリングを行う。レンダリングの説明は最後に。
    // 第一引数にはテンプレートデータを指定、第二引数にはオプションを指定してあげる。
    var data = ejs.render(template, {
      // hello.jsファイルのliタグ内で記述されているpostsを示している。
        posts: posts
    });

    // writeHeadメソッドはresponseオブジェクトのメソッドでヘッダー情報をレスポンスに書き出すもの。
　　// これでレスポンスで書き出される内容がhtmlだよって指定してあげる。(head情報)
    res.writeHead(200, {'content-Type': 'text/html'});

    // writeメソッドはresponseオブジェクトのメソッド。
    // ここでは上記のdata変数の値を「書き出し」をしてくれてる。(body内の情報)
    res.write(data);

    // 処理終了メソッド
    res.end();
}

// http.Serverオブジェクトがクライアントからのリクエストを受け取ったときに発生するイベント。
// ブラウザからサーバにアクセスした時のサーバの処理を記述。
// 第一引数にイベント名、第二引数に関数を指定。
server.on('request', function(req, res){
    
        // requestのmethod(hello.jsのformのメソッド)がpostだった場合の処理。
        if(req.method === 'POST'){

           // こいつを設定しないとinputタグに入力した値が表示されない。
           // ちなみにreq.dataの中身は、 data: [Function: bound socketOnData]。
           // postされたデータのハンドリングをする際に使用されると思ってる。
            req.data = "";

           // 受信したpostデータの受け取りはonメソッドからデータイベント処理を作ることで可能になる。
           // 引数のchunkに受信したpostデータが含まれている。
            req.on("data", function(chunk){
               // 引数で与えられている段階のchunkは、以下の16進数?で帰ってきている様子。
               // こいつ → <Buffer 6e 61 6d 65 3d 72 79 6f 6d 61>　
               // req.dataに追加された段階で
                req.data += chunk;
            });

           // コンテンツの書き出しが完了したら、最後にresponseの「end」を呼び出してコンテンツ出力を完了する
           // 今回は引数に書き出すコンテンツを指定して、書き出した後にrenderForm()を呼び出して処理を完了する。
            req.on("end", function(){

               // ここでデータの処理をしやすくするためにparseしている。
                var query = qs.parse(req.data);

               // parseしたデータのnameキーを指定して値をposts配列へpush。
                posts.push(query.name);
           
               // 上記のfunction renderFormを呼び出して引数にposts配列とresponseを指定する。
                renderForm(posts,res);
            });
        }else{
            renderForm(posts, res);
        }
   
});

// サーバーとして読み込んだファイルのportとhostのデータをlistenしてあげる。
// http.serverオブジェクトの準備が整ったらlistenメソッドが実行されるよ
server.listen(settings.port, settings.host);
console.log("server listening...");
 
```

# まとめ
ただのinputタグに入力した値をブラウザ上に表示するだけの処理だけど、学びが多かったです。
**ちなみにレンダリングとはwebブラウザがサーバから受け取ったファイルを整形して表示してくれる処理のことです。**

# 参考にしたサイト
[Node.jsのスクリプトの基本を覚えよう (1/5)](https://www.tuyano.com/index3?id=1126003)
とてつもなくわかり易かった。