在我问app.router之前,我想我至少应该解释一下我认为在使用中间件时会发生什么。要使用中间件,需要使用的函数是app.use()。当中间件正在执行时,它将使用next()调用下一个中间件,或者使它不再调用更多的中间件。这意味着我放置中间件调用的顺序很重要,因为一些中间件依赖于其他中间件,而靠近末尾的一些中间件甚至可能不被调用。

Today I was working on my application and had my server running in the background. I wanted to make some changes and refresh my page and see the changes immediately. Specifically, I was making changes to my layout. I couldn't get it to work so I searched Stack Overflow for the answer and found this question. It says to make sure that express.static() is beneath require('stylus'). But when I was looking at that OP's code, I saw that he had his app.router call at the very end of his middleware calls, and I tried to figure out why that was.

当我做我的express. js应用程序(3.0.0rc4版),我使用命令express app -sessions -css stylus和在我的app.js文件的代码来设置与我的app.router以上的express.static()和要求('stylus')调用。所以看起来,如果它已经这样设置了,那么它应该保持这样。

在重新安排我的代码,这样我就可以看到我的手写笔的变化,它看起来像这样:

app.configure(function(){
  //app.set() calls
  //app.use() calls
  //...
  app.use(app.router);
  app.use(require('stylus').middleware(__dirname + '/public'));
  app.use(express.static(__dirname + '/public', {maxAge: 31557600000}));
});

app.get('/', routes.index);

app.get('/test', function(req, res){
  res.send('Test');
});

So I decided that the first step would be to find out why it is important to even have app.router in my code. So I commented it out, started my app and navigated to /. It displayed my index page just fine. Hmm, maybe it worked because I was exporting the routing from my routes file (routes.index). So next I navigated to /test and it displayed Test on the screen. Haha, OK, I have no idea what app.router does. Whether it is included in my code or not, my routing is fine. So I am definitely missing something.

所以我的问题是:

谁能解释一下app.router是做什么的,它的重要性,以及我应该把它放在中间件调用的哪里?如果我能得到一个关于express.static()的简要解释,那就太好了。据我所知,express.static()是我的信息的缓存,如果应用程序找不到所请求的页面,它将检查缓存,看看它是否存在。


注意:这描述了Express在版本2和3中的工作方式。有关特快4的信息,请参阅本文末尾。


Static只是从磁盘上提供文件(静态资源)。您给它一个路径(有时称为挂载点),它为该文件夹中的文件提供服务。

例如,express.static('/var/www')将提供该文件夹中的文件。因此,向您的Node服务器请求http://server/file.html将提供/var/www/file. html。

路由器是运行路由的代码。当你执行app.get('/user', function(req, res){…});,实际上是路由器调用回调函数来处理请求。

将信息传递给app.use的顺序决定了每个中间件处理请求的顺序。例如,如果你在静态文件夹中有一个名为test.html的文件和一个路由:

app.get('/test.html', function(req, res) {
    res.send('Hello from route handler');
});

哪一个被发送到请求http://server/test.html的客户端?首先使用哪个中间件。

如果你这样做:

app.use(express.static(__dirname + '/public'));
app.use(app.router);

然后提供磁盘上的文件。

如果你用另一种方法,

app.use(app.router);
app.use(express.static(__dirname + '/public'));

然后路由处理程序得到请求,“Hello from route handler”被发送到浏览器。

通常,您希望将路由器置于静态中间件之上,以便意外命名的文件不能覆盖您的路由之一。

注意,如果你没有显式地使用路由器,它会在你定义路由时被Express隐式地添加(这就是为什么你的路由仍然可以工作,即使你注释掉了app.use(app.router))。


一位评论者提出了另一个关于静态和路由器的顺序的观点,这是我没有提到的:对应用程序整体性能的影响。

使用路由器而不是静态路由器的另一个原因是优化性能。如果你把静态放在第一位,那么你就会在每次请求时都去硬盘上查看文件是否存在。在一个快速测试中,我发现在一个未加载的服务器上,这个开销总计约为1ms。(在负载情况下,这个数字很可能更高,因为请求将争夺磁盘访问。)

在路由器优先的情况下,匹配路由的请求不需要访问磁盘,从而节省了宝贵的毫秒。

当然,有一些方法可以减轻静电的开销。

最好的选择是把你所有的静态资源放在一个特定的文件夹下。(IE /static)然后你可以将static挂载到该路径,这样它只在路径以/static开头时运行:

app.use('/static', express.static(__dirname + '/static'));

在这种情况下,你应该把这个放在路由器上面。如果文件存在,这避免了处理其他中间件/路由器,但说实话,我怀疑你能得到那么多。

您还可以使用staticCache,它将静态资源缓存到内存中,这样您就不必在磁盘上查找常见请求的文件。(警告:staticCache将来会被移除。)

然而,我不认为staticCache缓存否定答案(当文件不存在时),所以如果你把staticCache放在路由器上面而没有挂载到一个路径上,它是没有帮助的。

就像所有关于性能的问题一样,测量和基准测试你真实的应用程序(在负载下),看看瓶颈到底在哪里。


表达4

Express 4.0删除了app.router。所有中间件(app.use)和路由(app.get等)现在都按照它们被添加时的顺序被精确地处理。

换句话说:

所有路由方法将按照它们出现的顺序添加。你不应该使用app.use(app.router)。这消除了Express最常见的问题。 换句话说,混合使用app.use()和app[VERB]()将完全按照它们被调用的顺序工作。 app.get (' / ',); app.use(/公众,需要(“圣”)(process.cwd ())); app.get(' /用户,users.list); app.post(' /用户,users.create);

阅读更多关于快车4的变化。

Routing means determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on). Each route can have one or more handler functions, which are executed when the route is matched. In Express 4.0 Router, we are given more flexibility than ever before in defining our routes. express.Router() is use multiple times to define groups of routes. route used as middleware to process requests. route used as middleware to validate parameters using ".param()". app.route() used as a shortcut to the Router to define multiple requests on a route when we are using app.route(), we are attaching our app with that router.

var express = require('express'); //used as middleware
var app = express(); //instance of express.
app.use(app.router);
app.use(express.static(__dirname + '/public')); //All Static like [css,js,images] files are coming from public folder
app.set('views',__dirname + '/views'); //To set Views
app.set('view engine', 'ejs'); //sets View-Engine as ejs
app.engine('html', require('ejs').renderFile); //actually rendering HTML files through EJS. 
app.get('/', function (req, res) {
  res.render('index');  
})
app.get('/test', function (req, res) {
  res.send('test')
})

在express版本4中,我们可以很容易地以以下方式定义路由:

server.js:

const express = require('express');
const app = express();
const route = require('./route');

app.use('/route', route);
// here we pass in the imported route object

app.listen(3000, () => console.log('Example app listening on port 3000!'));

route.js:

const express = require('express');
const router = express.Router();

router.get('/specialRoute', function (req, res, next) {
     // route is now http://localhost:3000/route/specialRoute
});

router.get('/', function (req, res, next) {
    // route is now http://localhost:3000/route
});

module.exports = router;

在server.js中,我们导入了route.js文件的router对象,并在server.js中以以下方式应用它:

app.use('/route', route);

现在route.js中的所有路由都有以下基本URL:

http://localhost:3000/route

为什么采用这种方法:

采用这种方法的主要优点是,现在我们的应用程序更加模块化。某个路由的所有路由处理程序现在都可以放在不同的文件中,这使得一切都更易于维护和更容易找到。

@kelyvinn在2016年发表的一篇文章旨在演示模块化,其中包括以下代码:

/ /控制器/ api /狗/ index.js 常量 Express = require(' Express '), dogService = require('../../../services/dogs'); let router = express.Router(); 路由器。get (' / ', dogService.getDogs); 路由器。得到(/:id, dogService.getDogWithId); 模块。出口=路由器;