[ JavaScript ] HTMLページを動かす簡易サーバをつくってみた
HTMLやCSS、JSをローカルホストで見れるサーバがほしくて、「JSファイル1つ」でつくったので、気づきなどをまとめておこうと思います。
前提
- node: v12.18.3
構成
以下のようにファイル構成してみました。
$ tree
.
├── index.html
├── index.css
└── server.js
0 directories,, 3 files
サーバ用スクリプトの作成
以下がファイルの全体像です。
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function(request, response){
console.log('request ', request.url);
var filePath = '.' + request.url;
if (filePath == './') {
filePath = './index.html'
}
var extname = String(path.extname(filePath)).toLowerCase();
var mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css'
};
var contentType = mimeTypes[extname] || 'application/octet-stream';
fs.readFile(filePath, function(error, content){
if (error) {
if (error.code == 'ENOENT') {
fs.readFile('./404.html', function(){
response.writeHead(200, {'Content-Type': contentType});
response.end(content, 'utf-8');
});
} else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: ' + error.code + '..\n');
response.end();
}
} else {
response.writeHead(200, {'Content-Type': contentType});
response.end(content, 'utf-8');
}
});
}).listen(3002);
console.log('Server running at http://127.0.0.1:3002');
順番に説明していきます。
モジュール呼び出し部分
このサーバはNode.jsで動かすので
var http = require('http');
のように「require」でモジュールを呼び出しています。
※今回は関係ないですが、この「require」をクライアントサイドで実行する場合、Webpackなどで依存解決する必要があるようです
サーバの定義、起動ロジック
サーバの主要ロジックは
http.createServer(function(request, response){ ... }).listen(<待受ポート番号>);
で定義しています。
http.createServer()内で定義したサーバを指定のポートで待ち受けさせます。
パスの判定ロジック
アクセスがあったURLパスを判定するときは
var filePath = '.' + request.url;
if (filePath == './') {
filePath = './index.html'
}
で判定しています。
URLパスなしでアクセスされたらプロジェクトルート直下のindex.htmlを表示します。
もしスクリプトのどこかで、アクセスされたファイルの拡張子を文字列で抽出したい場合
String(path.extname(<ファイル名>))
で取得可能です。末尾に「.toLowerCase()」とすれば、取得した拡張子文字列を全部小文字に変換できます。
レスポンスの判定ロジック
リクエストされたファイルをfsモジュールで読み取って、以下のようにレスポンスの表示に利用しています。
fs.readFile(filePath, function(error, content){
if (error) {
if (error.code == 'ENOENT') {
fs.readFile('./404.html', function(){
response.writeHead(200, {'Content-Type': contentType});
response.end(content, 'utf-8');
});
} else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: ' + error.code + '..\n');
}
} else {
response.writeHead(200, {'Content-Type': contentType});
response.end(content, 'utf-8');
}
});
HTTPレスポンスヘッダーは、
response.writeHead(<ステータスコード>, {'Content-Type': <コンテンツタイプ>});
でセットしています。response.writeHeadの引数はそれぞれ
- 第1引数にステータスコード
- 第2引数にその他のヘッダーのキーと値
を渡しますが、この例ではオブジェクト化した「mimeTypes」から、アクセスされたURLパスの拡張子をキーにContent-Typeを取り出し、writeHeadの第二引数に渡しています。
mimeTypesの中にない拡張子でアクセスされたら、デフォルトで「application/octetstream」になるようにしています。
HTTPレスポンスボディに文字列を出力する点では
- response.write(str)
- response.end(str)
は役割が似ていますが、後者は同時にEOF(ファイルの終端)も出力するようになっています。
また、エラーの場合
- 404: 「./404.html」を探し404エラーページを表示
- 500: エラーメッセージを表示
で対策しています。
なにもなければステータスコード200でレスポンスヘッダをセットし、読み取ったファイルをレスポンスボディに書き込んで返します。
ターミナルから起動
サーバ用スクリプトができたら、ターミナル上で
$ node ./server.js
と入力しましょう。すると
$ node server.js
Server running at http://127.0.0.1:3002
のようにサーバが待ちになるので、ブラウザからアクセスすればOKです。
ちなみにリクエストを受け付けると
$ node server.js
Server running at http://127.0.0.1:3002
request /
request /favicon.ico
と続けて出力されるようになっています。
最後に
簡単にHTML、CSS、JSの動く環境がほしくなったので「これ一個で動くサーバ」を組んでみましたが、ライブリロード機能がないなど最低限のため、既成の環境に及ばない点は否めないです。
ちゃんと開発に使いたいのであれば、npmやyarnでプロジェクトをたてたほうがよさそうです。
ですが、自分で仕組みを見ながら作ってみるのも勉強になるので、とりあえずやってみるのもアリだと思ったのでした。
では、このへんで!
参考:
モジュール化(importとrequireの違い) | わくわくBank
node.jsに入門してみる。2 ~基本的な機能に触れてみる編~ | pxt.jp