Node.jsでhttpサーバを立てた際にCSSが読み取れない場合の対処法について

# 目的
同じ問題に遭遇した方への情報共有および、自分の備忘録として作成します。

# 概要
Node.jsで、以下の方法（httpモジュール）でhttpサーバを立てて、そのサーバにアクセスした際に、CSSが読み取れない場合の対処法を述べます。

```server.js
var http = require('http');
var fs   = require('fs');

var http_server = new http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end(fs.readFileSync('./index.html', 'utf-8'));
}).listen(3000);
console.log('Server running at http://localhost:3000/');

```

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>test</title>
    <link rel="stylesheet" href="css/style.css" type="text/css">
  </head>
  <body>
    <!-- 本文 -->
  </body>
</html>

```

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">覚えたてのHTML5+CSS+JavaScriptの知識を総動員してフロントエンド部を設計。なぜサーバ上だとCSSが適用されない。。 <a href="https://t.co/3etBgysZEv">pic.twitter.com/3etBgysZEv</a></p>&mdash; すいばり@&#39;16年度9試合2勝2敗 (@Suibari_cha) <a href="https://twitter.com/Suibari_cha/status/829705479781642244">2017年2月9日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# 結論
**サーバが、CSSのMIMEタイプ（"text/css"）を読み取れるようになっていないことが原因でした。**

### 問題の対処法
以下の通り server2.js に修正することで、ちゃんとCSSのMIMEタイプを読み取って、クライアントに転送することができます。
コードについて、以下3点をコンセプトとして設計しました。

1. CSSを読み取り可能にする。
2. "index.html"以外も応答可能にする。
3. CSS以外のMIMEタイプも、追記可能なコードにする。(せっかくだから)

```server2.js
var http = require('http');
var fs   = require('fs');
var path = require('path');
var mime = {
  ".html": "text/html",
  ".css":  "text/css"
  // 読み取りたいMIMEタイプはここに追記
};

var http_server = new http.createServer(function(req, res) {
  
  if (req.url == '/') {
    filePath = '/index.html';
  } else {
    filePath = req.url;
  }
  var fullPath = __dirname + filePath;
  
  res.writeHead(200, {"Content-Type": mime[path.extname(fullPath)] || "text/plain"});
  fs.readFile(fullPath, function(err, data) {
    if (err) {
      // エラー時の応答
    } else {
      res.end(data, 'UTF-8');
    }
  });
}).listen(3000);
console.log('Server running at http://localhost:3000/');

```

# 所見
* MIMEタイプについて（というよりサーバの挙動について）理解していなかったため、ブラウザのコンソールでのエラーの意味が分かりませんでした。このため、問題の原因の切り分けができず、ググっては大量の情報に右往左往してしまいました。
* サーバの動作についての知識が不足していましたが、今回応答処理をコーディングしたことで（ちょっとは）理解が深まったと感じます。継続して習得を目指します。

# 参考文献
まず @tatesuke 氏から、以下の記事を紹介して貰い、原因に気づけました。
サーバには"MIMEタイプ"設定があり、サーバが所望のファイルを読み取り可能なように設計していないと、クライアント側にファイルを伝送できないことを知りました。

>[stackoverflow: "Using node.js to serve up basic web page with CSS and JS includes"](http://stackoverflow.com/questions/17478566/using-node-js-to-serve-up-basic-web-page-with-css-and-js-includes)
>" Simple: you're setting the Content-Type header to text/html, always. Also, it will always serve your index.html file. "（抜粋）

以下のページがMIMEタイプの理解の助けになりました。

>[とほほのWWW入門: 拡張子とMIMEタイプ](http://www.tohoho-web.com/wwwxx015.htm)
>" ブラウザが xx.gif というファイルをWEBサーバーに要求する際、WEBサーバーはxx.gifの内容(データ)を「これは image/gif タイプのデータです」と言いながら返却してくれます。これにより、ブラウザは受け取ったデータを正常に処理することができるのです。 "（抜粋）

コードの内容に関しては、以下Qiita記事（@morou氏）が参考になりました。
>[Qiita: node.jsで動作するシンプルなWebサーバ](http://qiita.com/morou/items/6a1b9d09a8500f2f62e4)

### Node.jsマニュアル・ドキュメンテーション

* [fs.stat(path, [callback])](http://nodejs.jp/nodejs.org_ja/docs/v0.4/api/fs.html#fs.stat)
* [path.extname(p)](http://nodejs.jp/nodejs.org_ja/docs/v0.4/api/path.html#path.extname)
* [response.writeHead(statusCode, [statusMessage], [headers])](http://nodejs.jp/nodejs.org_ja/api/http.html#http_response_writehead_statuscode_statusmessage_headers)
* [response.end([data], [encoding])](http://nodejs.jp/nodejs.org_ja/api/http.html#http_response_end_data_encoding)