WindowsでNode.jsから仮想環境作って動かす

※コチラの記事は<a href="https://qooga.jb-jk.net/wp/run-node-js-in-windows/">ブログ</a>からのほぼ転載です。
<h3>インストール</h3>
ざっくり動かすまでの方法書くと、『<a href="http://nodejs.org/" target="_blank">本家</a>』から、Windowsのbitの合ってるものをDLして、インストールで完了。
余談だが『<a href="https://github.com/nullivex/nodist" target="_blank">nullivex/nodist</a>』を使うとバージョン管理に便利らしい。

解りやすい説明サイトがあったから、ここ参照したらいいと思います。
『<a href="https://qiita.com/KOJI-YAMAMOTO/items/4d189b2e44b5ffe5827a" target="_blank">Windows上でNode.jsを実行してHello worldをブラウザに表示する方法 - Qiita</a>』


<h3>Node.js使ってみる</h3>
コマンドプロンプトとかコマンド実行できるもの(以下：コマンド)を使っていく。

```
node -v
```
これが上手く動かなかった場合、パスが通っていない可能性がある。

通していない場合、使うとき(※windowsの場合の例)

```
C:/Program Files/nodejs/node.exe D:/aaa/ex.js
```
または

```
cd C:\Program Files\nodejs\
node.exe D:\aaa\ex.js
```
めんどくさいので、パス通すことをオススメする。

通せば、1度作業ディレクトリ(今回の場合D:\aaa)に移動してしまえば、下記のようにシンプルになる。

```
node ex.js
```


<h3>サーバーを構築して動かす</h3>
サーバを試しに動かすのに、最適だった、本家でも使っていた『node_chat』は、もはや過去の産物だから使えぬ。
諦めて別の方法でサーバを動かしていく。



<h3>WEBサーバー起動で、単純な表示させてみる</h3>
『hello.js』作る。仮にポートは900とした。

```
const http = require('http');
const PORT = 900;
const server = http.createServer((req, res)=>{
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World!!');
});
server.listen(PORT);
console.log(`Server running at http://localhost:${PORT}/`);
```

作ったらコマンドから

```
node hello.js
```

するとブラウザから、下記のどれでもアクセス出来る。

- http://localhost:900
- http://127.0.0.1:900
- http://【ipconfigして取得したPCのIPv4アドレス】:900

localhostは近年ブラウザに嫌われてるから、個人的にオススメしたくない。

他の仮想環境起動してようが、Apache起動してようが、関係ない。
ただ他のとこから、Node.jsで使用しているポート(今回の場合は900)だけは、使わないように注意する。

一応書くと、PORTの設定を80にするなら、URLにポートの指定は不要。
動かし方はこれでOK。


<h3>WEBサーバー起動して、外部ファイルを読み込ませてみよう</h3>
読み込ませるファイルは下記の状態。

- 読み込むファイルは『/test/index.html』
- index.htmlと同じ階層に『js.js』『css.css』『hk.png』を置き、index.html内で使用
- ポートは900

ファイルの位置関係はこんな感じ。
<pre>
./処理.js
./test/index.html
./test/js.js
./test/css.css
./test/hk.png
</pre>



<h3>外部ファイル読み込み１：単純ファイル名指定</h3>
『load.js』とした。

```
const http = require("http");
const PORT = 900;
const fs = require("fs");

const server = http.createServer((req, res) => {
  fs.readFile("./test/index.html", function(err, data) {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end(data, "utf-8");
  });
});
server.listen(PORT);
console.log(`Server running at http://localhost:${PORT}/`);
```
そしてコマンドで呼び出す　※以下同様

```
node load.js
```

読み込み対象ファイルがない場合、真っ白画面が表示される。
createServerでwriteHeadされているので、何も内容のないhtmlページがあるのだから、Not Findにはならない。



<h3>外部ファイル読み込み２：参照ファイルも読み込ませる</h3>
読み込み対象のCSSとかJSが読まれていない。階層違うからね。
不満なので、読み込むように処理を変更させる。
『app.js』とした。

『<a href="https://qiita.com/723ch/items/68ee87a64c9aeb60dd1b" target="_blank">Node.jsで書いたWebサーバでJSやCSSを読み込む - Qiita</a>』を基本にしてるが、1個1個全て設定はメンドウ。
file-typeモジュール使えるとこは、使うことにした。

```
npm install --save file-type
```

file-typeモジュール対象外であれば『undefined』を返してくる。

```
const http = require("http");
const fs = require("fs");
const PORT = 900;
const filetype = require("file-type");
// ファイル保存場所
const dirpath = "./test"; // 相対
//const dirpath = __dirname + "/test"; // 絶対

const server = http.createServer(function(req, res) {
  var url = req.url; // リクエストからURL取得
  if (url == "/") {
    // ディレクトリのみ指定の場合は『index.html』固定
    url = "/index.html";
  }
  var path = dirpath + url; // リクエストURLを実際のパスに加工
  console.log(path);

  var tmp = path.split("."); //『.』区切りで配列にする
  var ext = tmp[tmp.length - 1]; // tmp配列の最後の要素(拡張子)を取得
  try {
    var buf = fs.readFileSync(path); // encoding指定しなければBuffer取得
  } catch (error) {
    console.log('not find!');
    return false;
  }
  var type = filetype(buf);
  console.log(type);

  // 拡張子判定
  switch (ext) {
    case "js": // .js = JavaScript
      fs.readFile(path, function(err, data) {
        res.writeHead(200, { "Content-Type": "text/javascript" });
        res.end(data, "utf-8");
      });
      break;
    case "css": // .css = StyleSheet
      fs.readFile(path, function(err, data) {
        res.writeHead(200, { "Content-Type": "text/css" });
        res.end(data, "utf-8");
      });
      break;
    case "html": // .html = html
      fs.readFile(path, function(err, data) {
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(data, "utf-8");
      });
      break;
    default:
      // 他はfiletypeの自動判定
      fs.readFile(path, function(err, data) {
        res.writeHead(200, { "Content-Type": type.mime });
        res.end(data);
      });
      break;
  }
});
server.listen(PORT);
console.log(`Server running at http://localhost:${PORT}/`);
```

読み込み対象ファイルがない場合、その旨メッセージ出すようにした。
じゃないとnode.jsが強制終了しちゃうから…

readFileSyncはエンコードを指定すれば、Bufferでなくファイル内容を読める。

```
var file = fs.readFileSync(path,{encoding: "utf-8"});
```
ファイルが無ければ止まるから注意。



<h3>外部ファイル読み込み３：Expressモジュールを使う</h3>
先に書いた本家が使ってたchatで、Expressモジュール使ってみる。

Expressモジュール使おうと思ったら、標準で入ってなかったので、入れる必要がある。

```
npm install --save express
```

因みにアンインストール時は

```
npm uninstall express --save
```

今回は『exp.js』とする。

```
const express = require("express");
const app = express();
const PORT = 900;

const server = app.listen(PORT, function(){
    var host = server.address().address;
    var port = server.address().port;
    console.log('Server running at http://%s:%s', host, port);
});

// 同ディレクトリ内と判断する
app.use(express.static("test")); // 相対
// app.use(express.static(__dirname + '/test'));   // 絶対
```
app.get()と戦っていたが、ファイルがあって、処理をさせるでもなければ、不要だった。
シンプルだし、早い。

ファイルがない場合は、
<pre>Cannot GET /index.html</pre>
と見つからなかったファイル情報が表示される。



<h3>まとめ</h3>
モジュールって便利っすね！