Node.js / Express.js – app.router如何工作?
在我问及app.router
之前,我想我应该至less解释一下我在使用中间件时会发生什么。 要使用中间件,要使用的函数是app.use()
。 当中间件被执行时,它将使用next()
调用下一个中间件,或者使其不再调用中间件。 这意味着我放置中间件的顺序是很重要的,因为有些中间件依赖于其他中间件,有些中间件甚至可能不会被调用。
今天我正在处理我的应用程序,并让我的服务器在后台运行。 我想做一些改变,刷新我的网页,立即看到变化。 具体来说,我正在改变我的布局。 我无法得到它的工作,所以我search堆栈溢出的答案,并发现这个问题 。 它说确保express.static()
在require('stylus')
之下。 但是当我看着OP的代码的时候,我看到他在中间件调用的最后有他的app.router
调用,我试图找出原因。
当我制作了我的Express.js应用程序(版本3.0.0rc4)时,我使用了命令express app --sessions --css stylus
并在我的app.js文件中使用我的app.router
安装了express.static()
并require('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'); });
所以我决定,第一步是找出为什么在我的代码中甚至有app.router
是非常重要的。 所以我评论说,开始我的应用程序,并导航到/
。 它显示我的索引页面很好。 嗯,也许它工作,因为我从我的路线文件(routes.index)导出路由。 所以接下来我导航到/test
并在屏幕上显示testing。 哈哈,好的,我不知道app.router
是做什么的。 无论是否包含在我的代码中,我的路由都很好。 所以我肯定错过了一些东西。
所以这里是我的问题:
有人可以解释一下app.router
作用,它的重要性,以及我应该把它放在我的中间件调用中? 如果我对express.static()
有一个简单的解释,那也是很好的。 据我所知, express.static()
是我的信息的caching,如果应用程序找不到请求的页面,它将检查caching,看看它是否存在。
注意:这里描述了Express如何在版本2和3中工作。有关Express 4的信息,请参阅本文的结尾部分。
static
只是从磁盘提供文件( 静态资源)。 你给它一个path(有时称为挂载点),它提供该文件夹中的文件。
例如, express.static('/var/www')
将提供该文件夹中的文件。 因此,向您的节点服务器请求http://server/file.html
将服务于/var/www/file.html
。
router
是运行你的路由的代码。 当你做app.get('/user', function(req, res) { ... });
,实际调用callback函数来处理请求的是router
。
您将事情传递给app.use
的顺序决定了每个中间件有机会处理请求的顺序。 例如,如果在静态文件夹中有一个名为test.html
的文件,并且有一个路由:
app.get('/test.html', function(req, res) { res.send('Hello from route handler'); });
哪一个被发送到请求http://server/test.html
的客户端? 无论哪个中间件首先被use
。
如果你这样做:
app.use(express.static(__dirname + '/public')); app.use(app.router);
然后在磁盘上的文件被送达。
如果你这样做,
app.use(app.router); app.use(express.static(__dirname + '/public'));
然后,路由处理程序获取请求,并将“来自路由处理程序的Hello”发送到浏览器。
通常情况下,你想把路由器放在静态中间件的上面 ,这样一个意外命名的文件就不能覆盖你的一个路由。
请注意,如果您没有明确use
router
,则在您定义路由的时候,Express会隐式添加该router
(这就是为什么即使您注释掉了app.use(app.router)
您的路由仍然有效的原因)。
一位评论者提出了另一个关于我没有提到的static
和router
顺序的问题:对应用程序整体性能的影响。
use
static
router
另一个原因是为了优化性能。 如果你先把static
,然后你会在每一个请求中的硬盘驱动器,看看是否存在一个文件。 在一个快速testing中 ,我发现这个开销在卸载的服务器上达到了〜1ms。 (这个数字很有可能在负载下更高,在那里请求将争夺磁盘访问。)
router
首先匹配一条路由的请求永远不必击中磁盘,节省宝贵的毫秒。
当然,有办法来减轻static
的开销。
最好的select是将所有的静态资源放在一个特定的文件夹下。 (IE /static
)然后你可以把static
path挂载到那个path上,以便它只在path以/static
开头时运行:
app.use('/static', express.static(__dirname + '/static'));
在这种情况下,你会把这个router
。 这避免了处理其他中间件/路由器,如果一个文件存在,但说实话,我怀疑你会得到那么多。
你也可以使用staticCache
,它在内存中caching静态资源,所以你不必为通常请求的文件点击磁盘。 ( 警告: staticCache
将来显然会被删除 。)
但是,我不认为staticCache
caching否定的答案(当文件不存在时),所以如果您将staticCache
放在router
而不将其挂载到path上,则无法帮助您。
与所有有关性能的问题一样, 衡量和testing真实世界的应用程序 (负载下),看看瓶颈真正在哪里。
快递4
Express 4.0 删除 app.router
。 所有中间件( app.use
)和路由( app.get
等)现在都按照添加的顺序进行处理。
换一种说法:
所有路由方法将按照它们出现的顺序添加。 你不应该做
app.use(app.router)
。 这消除了Express的最常见问题。换句话说,混合
app.use()
和app[VERB]()
将按照它们被调用的顺序完全工作。app.get('/', home); app.use('/public', require('st')(process.cwd())); app.get('/users', users.list); app.post('/users', users.create);
阅读有关Express 4更改的更多信息。
路由意味着确定应用程序如何响应客户端对特定端点的请求,这是一个URI(或path)和特定的HTTP请求方法(GET,POST等)。 每个路由可以有一个或多个处理函数,当路由匹配时执行。
在Express 4.0路由器中,我们在定义路由时比以前有更多的灵活性。
express.Router()使用多次来定义路由组。
用作中间件来处理请求的路由。
用作中间件的路由使用“.param()”validation参数。
app.route()用作路由器的快捷方式来定义路由上的多个请求
当我们使用app.route()时,我们将我们的应用程序与该路由器相连接。
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') })