呵呵,项目做完了,连路由的几种实现方式都没搞明白,够丢人,节后第一天上班心情沉重捏,就简单参考总结下吧。能力有限,不正确之处请大拿指摘。
1、express模版app.js默认形式,所有路由都写在app.js中(基于express 3.x)
app.js
var express = require('express'); var routes = require('./routes'); var user = require('./routes/user'); var http = require('http'); var path = require('path');
var app = express();
// all environments app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public')));
// development only if ('development' == app.get('env')) { app.use(express.errorHandler()); }
app.get('/', routes.index); app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
|
标红色的两句的顺序非常重要当静态页面与动态路由请求同时存在时,哪个是真实路由:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
此种写法是express官方推荐的,先查找是否有匹配的路由,如果没有就去读写磁盘查找文件。
顺序颠倒的话,会先查找磁盘文件,在去匹配路由,查找磁盘文件必然造成不必要的效率浪费。
缺点:随着路由的增多,app.js会可读性越来越差,杂乱等。所以有了路由拆分的说法既第二种
2、将路由实现从app.js中拆分出去(express4.x实现)
特点:将路由的实现拆开,拆分位置可以根据自己业务需要进行划分,不在需要app.use(app.router)。例子如下(app.js 与rounte/index.js):
app.js
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var routes = require('./routes/index'); var users = require('./routes/users'); var app = express(); var http = require('http').Server(app); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); // uncomment after placing your favicon in /public //app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes); app.use('/users', users); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); http.listen(3000,function(){ console.log('listening on 3000') }); module.exports = app; |
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res) { res.render('index', { title: 'Express' }); }); |
express 3.x实现
app.js var routes = require('./routes'); app.get('/',routes.index);
routes/index.js exports.index=function(req,res){ res.render('index',{title:'Express'}); } |
3 最佳路由写法
app.js
/** * Module dependencies. */ var express = require('express'); var routes = require('./routes'); var http = require('http'); var path = require('path'); var staticCache = require('express-static-cache'); var app = express(); var favicon = require('static-favicon'); var Cluster = require('cluster2'); var numCPUs = require('os').cpus().length-1; app.set('view engine', 'ejs'); app.set('view cache', true); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.favicon(path.join(__dirname, '/public/images/common/favicon.ico'), {})); app.use(express.json()); app.use(express.urlencoded()); app.use(express.methodOverride()); //内存存储session app.use(express.cookieParser('keyboard cat')); app.use(express.session()); app.use(app.router); app.use(express.compress()); app.use(express.responseTime()); app.use('/public', staticCache(path.join(__dirname, 'public')), { maxAge: 24 * 60 * 60 }); app.use('/css', express.static(path.join(__dirname, 'public/css'))); app.use('/js', express.static(path.join(__dirname, 'public/js'))); app.use(function (req, res) { res.render('common/404'); }); app.use(function (error, req, res, next) { console.log('error:' + error); if (error.name.indexOf('CastError') > -1) { res.render('common/404'); } else { console.log('error:' + error); res.render('common/500'); } }); // development only if ('development' == app.get('NODE_ENV')) { app.use(express.errorHandler()); } routes(app); var c = new Cluster({ port:8080, cluster: true, noWorkers:numCPUs }); c.on('died', function(pid) { console.log('Worker ' + pid + ' died'); }); c.on('forked', function(pid) { console.log('Worker ' + pid + ' forked'); }); c.on('SIGKILL', function() { console.log('Got SIGKILL'); }); c.on('SIGTERM', function(event) { console.log('Got SIGTERM - shutting down'); }); c.on('SIGINT', function() { console.log('Got SIGINT'); }); c.listen(function(cb){ cb(app); }); |
rounte/index.js
module.exports = function(app){ app.get('/',function(req,res){ res.render('index', { title: 'Express' }); }); app.get('/login', function(req, res) { res.render('login', { title: '会员登录', }); }); }; |
还可以将rounte/index.js继续拆分根据业务需要将路由实现逻辑进行拆分,每个业务调用自己模块(文件夹)下的路由实现,工程目录更清晰(文章找文章目录,广告找广告目录)
代码片段如下:
app.js同上
rounte.js
var category = require('./controllers/category'); var user = require('./controllers/user'); var advertisement = require('./controllers/advertisement'); module.exports = function (app) { // 方案下级 app.get('/category/solution/air/nextCate/queryArticle/:id',category.solution);//航旅 app.get('/category/solution/digital/nextCate/queryArticle/:id',category.solution);//数娱 app.get('/category/solution/education/nextCate/queryArticle/:id',category.solution);//教育 app.get('/category/solution/insurance/nextCate/queryArticle/:id',category.solution);//保险 app.get('/category/solution/logistics/nextCate/queryArticle/:id',category.solution);//快消 app.get('/category/solution/telecom/nextCate/queryArticle/:id',category.solution);//电信 app.get('/category/solution/fund/nextCate/queryArticle/:id',category.solution);//基金 app.get('/category/solution/finance/nextCate/queryArticle/:id',category.solution);//互联网金融 app.get('/category/solution/Spot/nextCate/queryArticle/:id',category.solution);//现货 } |
exports.solution = function (req, res) { var name = req.param('id'); var cpath; var title = name; var positionC; var conditionsArt; var result = {'title': 1, 'brief': 1, 'content': 1, 'cpath': 1, 'url': 1, 'retime': 1}; var conArt = {'_id': name}; var keyAndDescript ={'_id': name}; var keyresult ={'keyword':1,'description':1}; // 菜单 category.showMenuLevlOne(function (cat) { category.showMenu(function (cate) { // 查询name下文章 Article.showAllSomeArticle(1, conArt, result, function (err, ac) { if (err) { res.render('common/404'); } else { ac.forEach(function (a) { cpath = a.cpath; positionC = a.title; conditionsArt = {'cpath': cpath, 'display': true}; Article.showAllSomeArticle(1, conditionsArt, result, function (err, articleUnderCategory) { // 查询公告 Article.showAllSomeArticle(-1, {'articletype': '公告', 'cpath': { $regex: '公告', $options: 'i' }, 'display': true}, {'title': 1, 'brief': 1, 'content': 1, 'id': 1, 'url': 1, 'retime': 1, 'cpath': 1}, function (err, annce) { //查询关键字 category.showSomeCategory(keyAndDescript,keyresult,function(err,keyAndDec) { res.render('common/article_detail', { cat: cat, cate: cate, ac: ac, auc: articleUnderCategory, imgServer: config.imgServer, name: '行业方案', positionP: '行业方案', positionC: positionC, firstTab: positionC, currentTab: cpath.split('/')[2], annce: annce, keyAndDec:keyAndDec, time: '', level1: urlConfig.industrySolution, level2: urlConfig.air, title: 'xxxx' }); }); }); }); }); } }); }); }); } |