目的
同じ問題に遭遇した方への情報共有および、自分の備忘録として作成します。
概要
Node.jsで、以下の方法(httpモジュール)でhttpサーバを立てて、そのサーバにアクセスした際に、CSSが読み取れない場合の対処法を述べます。
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/');
<!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>
覚えたてのHTML5+CSS+JavaScriptの知識を総動員してフロントエンド部を設計。なぜサーバ上だとCSSが適用されない。。 pic.twitter.com/3etBgysZEv
— すいばり@'16年度9試合2勝2敗 (@Suibari_cha) 2017年2月9日
結論
サーバが、CSSのMIMEタイプ("text/css")を読み取れるようになっていないことが原因でした。
問題の対処法
以下の通り server2.js に修正することで、ちゃんとCSSのMIMEタイプを読み取って、クライアントに転送することができます。
コードについて、以下3点をコンセプトとして設計しました。
- CSSを読み取り可能にする。
- "index.html"以外も応答可能にする。
- CSS以外のMIMEタイプも、追記可能なコードにする。(せっかくだから)
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"
" Simple: you're setting the Content-Type header to text/html, always. Also, it will always serve your index.html file. "(抜粋)
以下のページがMIMEタイプの理解の助けになりました。
とほほのWWW入門: 拡張子とMIMEタイプ
" ブラウザが xx.gif というファイルをWEBサーバーに要求する際、WEBサーバーはxx.gifの内容(データ)を「これは image/gif タイプのデータです」と言いながら返却してくれます。これにより、ブラウザは受け取ったデータを正常に処理することができるのです。 "(抜粋)
コードの内容に関しては、以下Qiita記事(@morou氏)が参考になりました。