利用connect建立前端开发服务器
2013-08-12 13:12 Justany_WhiteSnow 阅读(3190) 评论(4) 编辑 收藏 举报对于前后端完全分离的系统,开发时候我们需要给前端配置服务器,当然我们可以选择Nginx之类的服务器进行配置,但我们也能使用NodeJS构建高自由度的前端开发服务器。
简单静态服务器
下面是一个简单的静态服务器:
var http = require('http'), url = require('url'), fs = require('fs') path = require('path'); function getContentType(_path){ var contentType, ext = path.extname(_path); switch(ext){ case '.html': case '.htm': contentType = 'text/html'; break; case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.gif': contentType = 'image/gif'; break; case '.jpg': contentType = 'image/jpeg'; break; case '.png': contentType = 'image/png'; break; case '.ico': contentType = 'image/icon'; break; default: contentType = 'application/octet-stream'; } return contentType; } function httpService(req, res){ var reqUrl = req.url, pathName = url.parse(reqUrl).pathname, filePath; if(Path.extname(pathName) === ""){ pathName += "/"; } if(pathName.charAt(pathName.length - 1) === "/"){ pathName += "index.html"; } filePath = path.join('./', pathName); fs.exists(filePath, function(exists){ if(exists){ res.writeHead(200, {'Content-Type': getContentType(filePath)}); var stream = fs.createReadStream(filePath, {flags : "r", encoding : null}); stream.on('error', function(){ res.writeHead(404); res.end('<h1>404 Read Error</h1>'); }); stream.pipe(res); }else{ res.writeHead(404, {'Content-Type': 'text/html'}); res.end('<h1>404 Not Found</h1>'); } }); } var webService = http.createServer(httpService); webService.on('error', function(error){ console.log('[WebService][error] ' + error); }); webService.listen(300, function(){ console.log('[WebService][Start] running at http://127.0.0.1:' + 3000 + '/'); });
可以发现一个静态服务器也要写很多行代码才能完成,但是如果我们使用connect,会发现这一切只要几行代码。
Connect?
connect是高性能NodeJS Web中间件框架,提供了二十余个中间件,并有众多第三方中间件支持。connect使用非常简单,例如上面的静态服务器,在connect中只需:
var connect = require('connect'); var app = connect() .use(connect.static('public')) .listen(3000);
安装connect
我们只要在命令行中输入:
npm install connect
便可以安装了。
模型
connect的模型非常简单,通过use注册中间件,每个中间件接收request和response,如果发现request是该中间件处理的,那么处理完后通过response.end输出,否则通过next交给下一个中间件处理。
需求
OK,现在我们看看需求是怎样的:
- 由于前后端是分离的,所以开发的时候前后端也是分离的,那么前端和后端做交互就会跨域,所以首先要能反向代理到后端。
- 可以简单配置静态服务器(我们假设前端的文件全是静态的)。
- 可以在前端模拟数据交互,也就是在特定的文件夹存储模拟的数据,然后对应返回。
- 力求简便,通过json配置。
路径结构:
/static:静态服务路径与后端交互
/prototype/static:原型路径与模拟数据交互
/prototype/static/mockup-data/:模拟数据路径
代码
static.js:
module.exports = (function(){ "use strict" var connect = require('connect'), http = require('http'), url = require('url'), path = require('path'), proxy = require('proxy-middleware'), fs = require('fs'), pkg = JSON.parse(fs.readFileSync('./package.json')); // 通过后缀名得到content type function _getType(extname){ switch(extname){ case '.json': return 'application/json'; case '.xhtml': case '.html': return 'text/html'; default: return 'application/json'; } } // 使用connect var app = connect() // 使用logger中间件 .use(connect.logger('dev')) // 用static中间件处理静态服务 .use(pkg.static.path, connect.static(pkg.static.root, {maxAge: pkg.maxAge})) .use(pkg.prototype.path + '/static/mockup-data', function(req, res, next){ // 如果是GET方法,交由下面的中间件处理 if(req.method === 'GET') return next(); var urlObj = url.parse(pkg.prototype.root + req.originalUrl.replace(pkg.prototype.path, '')), filePath = urlObj.protocol + urlObj.pathname, contentType = _getType(path.extname(urlObj.pathname)), method = req.method.toLowerCase(), // 得到与方法名对应的模拟文件路径,例如原来文件路径是1.json,在POST方法中变成1.post.json methodFilePath = filePath.replace(/(\.xhtml|\.html|\.json)$/, '.' + method + '$1'); fs.exists(methodFilePath, function(exist){ // 如果方法名对应的模拟文件存在 if(exist){ // 替换文件路径 filePath = methodFilePath; } // 读取文件 fs.readFile(filePath, function(err, data){ if(err) return next(err); res.writeHead(200, {'Content-Type': contentType}); res.statuCode = 200; res.end(data); }); }); }) // 用static中间件处理原型的静态服务 .use(pkg.prototype.path, connect.static(pkg.prototype.root, {maxAge: pkg.maxAge})) // 使用proxy-middleware中间件进行反向代理 .use(proxy(url.parse(pkg.proxy))) .listen(pkg.port, function(){console.log('Connect with: http://127.0.0.1:' + pkg.port)}); })();
package.json:
{ "maxAge": 3600, "port": 80, "proxy": "http://192.168.10.202:8080", "prototype": { "path": "/prototype", "root": "C:/Users/Desktop/manggis/manggis_web/src/main/webapp/prototype" }, "static": { "path": "/manggis_web/static", "root": "C:/Users/Desktop/manggis/manggis_web/src/main/webapp/static" }, "devDependencies": { "connect": "~2.8.4", "proxy-middleware": "~0.4.0" } }