var fs = require("fs"), path = require("path"), http = require("http"); var MIME = { '.css':'text/css', '.js':'application/javascript' } /** *合并文件 * @param {Object} pathnames * @param {Object} callback */ function combinFiles(pathnames,callback){ var output = []; (function next(i,len){ if(i<len){ fs.readFile(pathnames[i],function (err,data){ if(err){ callback(err) }else{ output.push(data); next(i+1,len) } }); }else{ callback(null,Buffer.concat(output)); } }(0,pathnames.length)); } /** *主函数 * @param {Object} argv */ function main(argv){ //var config = require('./config.json'), var config = JSON.parse(fs.readFileSync(argv[0],'utf-8')), root = config.root || '.', port = config.port || 8080; http.createServer(function (req,resp){ var urlInfo = parseURL(root,req.url); combinFiles(urlInfo.pathnames,function (err,data){ if(err){ resp.writeHead(404); resp.end(err.message); }else{ resp.writeHead(200,{ "Content-Type":urlInfo.mine }); resp.end(data); } }); }).listen(port); } /** *解析url地址 */ function parseURL(root,url){ var base,pathnames,parts; if(url.indexOf("??") === -1){ url = url.replace("/","/??"); } parts = url.split("??"); base = parts[0]; pathnames = parts[1].split(",").map(function(value){ return path.join(root,base,value); }); return { mime:MIME[path.extname(pathnames[0])] || 'text/plan', pathnames:pathnames } } main(process.argv.slice(2));
config.json
{“port”:“8080”}
启动服务
node server.js config.json
浏览器测试
http://localhost:8080/??server.js,temp.js
优化版的server.js
var fs = require("fs"), path = require("path"), http = require("http"); var MIME = { '.css': 'text/css', '.js': 'application/javascript' } /** *合并文件 * @param {Object} pathnames * @param {Object} callback */ function combinFiles(pathnames, callback) { var output = []; (function next(i, len) { if (i < len) { fs.readFile(pathnames[i], function(err, data) { if (err) { callback(err) } else { output.push(data); next(i + 1, len) } }); } else { callback(null, Buffer.concat(output)); } } (0, pathnames.length)); } /** *主函数 * @param {Object} argv */ function main(argv) { var config = JSON.parse(fs.readFileSync(argv[0], 'utf-8')), root = config.root || '.', port = config.port || 8080; http.createServer(function(req, resp) { var urlInfo = parseURL(root, req.url); validateFiles(urlInfo.pathnames, function(err, pathnames) { if (err) { resp.writeHead(404); resp.end(err.message); } else { resp.writeHead(200, { "Content-Type": urlInfo.mime }); outputFiles(pathnames, resp); } }); }).listen(port); } /** *输出文件 */ function outputFiles(pathnames, writer) { (function next(i, len) { if (i < len) { var reader = fs.createReadStream(pathnames[i]); reader.pipe(writer, { end: false }); reader.on("end", function() { next(i + 1, len); }) } else { writer.end(); } }) (0, pathnames.length); } /** * 验证文件 */ function validateFiles(pathnames, callback) { (function next(i, len) { if (i < len) { fs.stat(pathnames[i], function(err, stats) { if (err) { callback(err); } else if (!stats.isFile()) { callback(new Error()); } else { next(i + 1, len); } }) } else { callback(null, pathnames); } })(0, pathnames.length); } /** *解析url地址 */ function parseURL(root, url) { var base, pathnames, parts; if (url.indexOf("??") === -1) { url = url.replace("/", "/??"); } parts = url.split("??"); base = parts[0]; pathnames = parts[1].split(",").map(function(value) { return path.join(root, base, value); }); return { mime: MIME[path.extname(pathnames[0])] || 'text/plan', pathnames: pathnames } } main(process.argv.slice(2));