從昨天的程式中發現,把程式hard code在一起會造成測試上的不便,所以還是把他做成模組。
模組化的需求
之前在撰寫程式時,把所有的程式碼都放在同一支程式裡面,在撰寫目錄預設index檔的功能時,就發現會有一些測試的困難度。例如設定多個預設index檔時,需要測試先後順序是否影響功能。但是這樣需要每次都改寫evolve.js才能進行測試,非常的不方便。把伺服器程式模組化,就可以解決這樣的問題。
之前已經做的準備
其實之前已經默默地做了一些準備,包括:
把程式碼封裝成一個物件,並用constructor初始化,這樣就可以透過module.exports輸出給其他程式使用。
模組化
至於實做,倒是很簡單,只要把evolve這個constructor指派給module.ports就可以了,像這樣:
var http = require('http'),
fs = require('fs'),
url = require('url'),
mime = require('../deps/mime'),
path = require('path'),
evolve = function(conf) {
var server = http.createServer(function(request, response) {
var urlObj = url.parse(request.url);
var respath = path.join(conf.basedir, urlObj.pathname);
console.log('request: ' + respath);
fs.stat(respath, function(err, stats) {
if(err) {
console.log(respath + ' not exists.');
response.writeHead(404, '');
response.end();
} else {
if(stats.isDirectory()) {
var ic=0;
fs.readFile(path.join(respath, conf.dirindex[ic]), function dih(err, data) {
ic++;
if(err) {
if(ic<conf.dirindex.length) {
fs.readFile(path.join(respath, conf.dirindex[ic]), dih);
} else {
console.log(path.join(respath, conf.dirindex[ic-1]) + ' not exists.');
response.writeHead(404, '');
response.end();
}
} else {
console.log(path.join(respath, conf.dirindex[ic-1]) + ' exists.');
response.writeHead(200, {
"Content-Type": mime.lookup(path.join(respath, conf.dirindex[ic-1])),
"Content-Length": data.length
});
response.end(data);
}
});
} else {
fs.readFile(respath, function(err, data) {
if(err) {
console.log(respath + ' not exists.');
response.writeHead(404, '');
response.end();
} else {
console.log(respath + ' exists.');
response.writeHead(200, {
"Content-Type": mime.lookup(respath),
"Content-Length": data.length
});
response.end(data);
}
});
}
}
});
});
this.listen = function(port, addr) {
server.listen(port, addr);
return this;
};
};
module.exports = evolve;
要使用伺服器時,就利用模組來呼叫他(tests/testserver001.js):
var evolve = require('../lib/evolve'),
instance = new evolve({
basedir: path.join(__dirname, '/../www'),
dirindex: ['index.htm','index.html','default.htm']
});
instance.listen(8443, '127.0.0.1');
console.log('server started.');
跟之前的程式其實只差兩行,拆成兩個檔案。現在目錄結構變成:
evolve
|-- README
|-- deps
| `-- mime
| |-- LICENSE
| |-- README.md
| |-- index.js
| |-- mime.js
| |-- mime.types
| |-- node.types
| |-- package.json
| `-- test.js
|-- index.js
|-- lib
| `-- evolve.js
|-- tests
| |-- testserver001.js
| |-- testserver002.js
| `-- testserver003.js
`-- www
|-- bg.gif
`-- default.htm
多個測試
透過模組化,把伺服器程式與實例分離,要做測試就容易了。例如想要測試目錄index檔,之前要改動伺服器程式的檔案,現在只要寫三個測試用不同的設定啟動伺服器就可以:
testserver002.js:
var evolve = require('../lib/evolve'),
instance = new evolve({
basedir: path.join(__dirname, '/../www'),
dirindex: ['index.htm','default.htm','index.html']
});
instance.listen(8443, '127.0.0.1');
console.log('server started.');
testserver003.js:
var evolve = require('../lib/evolve'),
instance = new evolve({
basedir: path.join(__dirname, '/../www'),
dirindex: ['default.htm','index.htm','index.html']
});
instance.listen(8443, '127.0.0.1');
console.log('server started.');
另外,在evolve根目錄加上index.js,內容很簡單:
module.exports = require('lib/evolve');
這樣只要把evolve放到NODE_PATH環境變數所指的目錄,或是node.js應用程式的node_modules子目錄中,之後就可以透過require('evolve')來使用這個模組。