node.js 使用 Hapi 时如何将路由存储在单独的文件中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27766623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to store routes in separate files when using Hapi?
提问by Centurion
All of the Hapi examples (and similar in Express) shows routes are defined in the starting file:
所有 Hapi 示例(和 Express 中的类似)都显示了在起始文件中定义的路由:
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 8000 });
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Hello, world!');
}
});
server.route({
method: 'GET',
path: '/{name}',
handler: function (request, reply) {
reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
}
});
server.start(function () {
console.log('Server running at:', server.info.uri);
});
However, it's not hard to image how large this file can grow when implementing production application with a ton of different routes. Therefore I would like to break down routes, group them and store in separate files, like UserRoutes.js, CartRoutes.js and then attach them in the main file (add to server object). How would you suggest to separate that and then add?
然而,当使用大量不同的路由实现生产应用程序时,不难想象这个文件可以增长到多大。因此,我想分解路由,将它们分组并存储在单独的文件中,例如 UserRoutes.js、CartRoutes.js,然后将它们附加到主文件中(添加到服务器对象)。您建议如何将其分开然后添加?
回答by Gergo Erdosi
You can create a separate file for user routes (config/routes/user.js):
您可以为用户路由创建一个单独的文件 ( config/routes/user.js):
module.exports = [
{ method: 'GET', path: '/users', handler: function () {} },
{ method: 'GET', path: '/users/{id}', handler: function () {} }
];
Similarly with cart. Then create an index file in config/routes(config/routes/index.js):
与购物车类似。然后在config/routes( config/routes/index.js) 中创建一个索引文件:
var cart = require('./cart');
var user = require('./user');
module.exports = [].concat(cart, user);
You can then load this index file in the main file and call server.route():
然后,您可以在主文件中加载此索引文件并调用server.route():
var routes = require('./config/routes');
...
server.route(routes);
Alternatively, for config/routes/index.js, instead of adding the route files (e.g. cart, user) manually, you can load them dynamically:
或者,对于config/routes/index.js,您可以动态加载它们,而不是手动添加路由文件(例如cart,user):
const fs = require('fs');
let routes = [];
fs.readdirSync(__dirname)
.filter(file => file != 'index.js')
.forEach(file => {
routes = routes.concat(require(`./${file}`))
});
module.exports = routes;
回答by coquin
You should try Glue plugin: https://github.com/hapijs/glue. It allows you to modularize your application. You can place your routes in separate subdirectories and then include them as Hapi.js plugins. You can also include other plugins (Inert, Vision, Good) with Glue as well as configure your application with a manifest object (or json file).
您应该尝试使用 Glue 插件:https: //github.com/hapijs/glue。它允许您模块化您的应用程序。您可以将您的路由放在单独的子目录中,然后将它们作为 Hapi.js 插件包含在内。您还可以使用 Glue 包含其他插件(Inert、Vision、Good),并使用清单对象(或 json 文件)配置您的应用程序。
Quick exapmple:
快速示例:
server.js:
服务器.js:
var Hapi = require('hapi');
var Glue = require('glue');
var manifest = {
connections: [{
port: 8080
}],
plugins: [
{ inert: [{}] },
{ vision: [{}] },
{ './index': null },
{
'./api': [{
routes: {
prefix: '/api/v1'
}
}]
}
]
};
var options = {
relativeTo: __dirname + '/modules'
};
Glue.compose(manifest, options, function (err, server) {
server.start(function(err) {
console.log('Server running at: %s://%s:%s', server.info.protocol, server.info.address, server.info.port);
});
});
./modules/index/index.js:
./modules/index/index.js:
exports.register = function(server, options, next) {
server.route({
method: 'GET',
path: '/',
handler: require('./home')
});
});
exports.register.attributes = {
pkg: require('./package.json')
};
./modules/index/package.json:
./modules/index/package.json:
{
"name": "IndexRoute",
"version": "1.0.0"
}
./modules/index/home.js:
./modules/index/home.js:
exports.register = function(req, reply) {
reply.view('home', { title: 'Awesome' });
});
Have a look at thiswonderful article by Dave Stevens for more details and examples.
查看Dave Stevens 撰写的这篇精彩文章,了解更多详细信息和示例。
回答by Brian ONeil
You can use require-hapiroutesto do some of the organization and loading for you. (I am the author so I am a little biased, I wrote it to make my life easier in managing routes)
您可以使用require-hapiroutes为您做一些组织和加载。(我是作者所以我有点偏见,我写它是为了让我在管理路线时更轻松)
I am a big fan of require-directoryand and wanted a way to manage my routes just as easily. This lets you mix and match routes in your modules and modules in directories with routes.
我是require-directory 的忠实粉丝,并且想要一种方法来同样轻松地管理我的路由。这使您可以混合和匹配模块中的路由以及带有路由的目录中的模块。
You can then do something like this...
然后你可以做这样的事情......
var routes = require('./routes');
server.route(routes.routes);
Then in your directory you could have a route file like...
然后在您的目录中,您可以有一个路由文件,例如...
module.exports = [
{
method : 'GET',
path : '/route1',
handler : routeHandler1,
config : {
description: 'my route description',
notes: 'Important stuff to know about this route',
tags : ['app']
}
},
{
method : 'GET',
path : '/route2',
handler : routeHandler2,
config : {
description: 'my route description',
notes: 'Important stuff to know about this route',
tags : ['app']
}
}];
Or, you can mix and match by assigning to a "routes" property on the module
或者,您可以通过分配给模块上的“路由”属性来混合和匹配
module.exports.routes = [
{
method : 'GET',
path : '/route1',
handler : routeHandler1,
config : {
description: 'my route description',
notes: 'Important stuff to know about this route',
tags : ['app']
}
},
{
method : 'GET',
path : '/route2',
handler : routeHandler2,
config : {
description: 'my route description',
notes: 'Important stuff to know about this route',
tags : ['app']
}
}];
Always, good to have options. There is full documentation on the githubor npmjssite for it.
回答by Whisher
or you can use a index file to load all the routes in the directory
或者您可以使用索引文件加载目录中的所有路由
index.js
索引.js
/**
* Module dependencies.
*/
const fs = require('fs');
const path = require('path');
const basename = path.basename(__filename);
const routes = fs.readdirSync(__dirname)
.filter((file) => {
return (file.indexOf('.') !== 0) && (file !== basename);
})
.map((file) => {
return require(path.join(__dirname, file));
});
module.exports = routes;
other files in the same directory like:
同一目录中的其他文件,例如:
module.exports = [
{
method: 'POST',
path: '/api/user',
config: {
}
},
{
method: 'PUT',
path: 'api/user/{userId}',
config: {
}
}
];
and than in your root/index
而不是在你的根/索引中
const Routes = require('./src/routes');
/**
* Add all the routes
*/
for (var route in Routes) {
server.route(Routes[route]);
}
回答by Fredric
Interesting to see so many different solutions, here is another one.
看到这么多不同的解决方案很有趣,这是另一个。
Globbing to the rescue
扑救
For my latest project I settled on globbing for files with a particular name pattern and then requiring them into the server one by one.
对于我的最新项目,我决定对具有特定名称模式的文件进行通配,然后要求将它们一个一个地放入服务器。
Import routes after having created the serverobject
创建server对象后导入路由
// Construct and setup the server object.
// ...
// Require routes.
Glob.sync('**/*route*.js', { cwd: __dirname }).forEach(function (ith) {
const route = require('./' + ith);
if (route.hasOwnProperty('method') && route.hasOwnProperty('path')) {
console.log('Adding route:', route.method, route.path);
server.route(route);
}
});
// Start the server.
// ...
The glob pattern **/*route*.jswill find all files within and below the specified current working directory with a name that contains the word routeand ends with the suffix .js.
glob 模式**/*route*.js将查找指定当前工作目录内和下的所有文件,其名称包含单词route并以后缀.js结尾。
File structure
文件结构
With the help of globbing we have a loose coupling between the serverobject and its routes. Just add new route files and they will be included the next time you restart your server.
在 globbing 的帮助下,我们在server对象和它的路由之间实现了松散耦合。只需添加新的路由文件,它们将在您下次重新启动服务器时包含在内。
I like to structure the route files according to their path and naming them with their HTTP-method, like so:
我喜欢根据路径构建路由文件,并使用 HTTP 方法命名它们,如下所示:
server.js
routes/
users/
get-route.js
patch-route.js
put-route.js
articles/
get-route.js
patch-route.js
put-route.js
Example route file routes/users/get-route.js
示例路由文件 routes/users/get-route.js
module.exports = {
method: 'GET',
path: '/users',
config: {
description: 'Fetch users',
// ...
},
handler: function (request, reply) {
// ...
}
};
Final thoughts
最后的想法
Globbing and iterating over files is not a particularly fast process, hence a caching layer may be worth investigating in production builds depending on your circumstances.
Globbing 和迭代文件并不是一个特别快的过程,因此缓存层可能值得在生产构建中根据您的情况进行研究。
回答by sitrakay
Try hapi-auto-routeplugin! It's is very simple to use and allow prefix in your route path.
试试hapi-auto-route插件!使用起来非常简单,并允许在您的路由路径中使用前缀。
Full disclosure: I am the author of this plugin
完全披露:我是这个插件的作者
回答by Mr H
I know this is already approved. I put down my solution in case someone wants a quick fix and new to Hapi.
我知道这已经被批准了。如果有人想要快速修复并且不熟悉 Hapi,我会放下我的解决方案。
Also I included some NPM too so Newbees can see how to to use the server.registerwith multiple plugin in the case ( good+ hapi-auto-route)
我还包括了一些 NPM,以便 Newbees 可以看到如何server.register在案例 ( good+ hapi-auto-route) 中使用多个插件
Installed some npm packages:
安装了一些 npm 包:
npm i -S hapi-auto-route
npm i -S good-console
npm i -S good
// server.js
'use strict';
const Hapi = require('hapi');
const Good = require('good');
const AutoRoute = require('hapi-auto-route');
const server = new Hapi.Server();
server.connection(
{
routes: { cors: true },
port: 3000,
host: 'localhost',
labels: ['web']
}
);
server.register([{
register: Good,
options: {
reporters: {
console: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{
response: '*',
log: '*'
}]
}, {
module: 'good-console'
}, 'stdout']
}
}
}, {
register: AutoRoute,
options: {}
}], (err) => {
if (err) {
throw err; // something bad happened loading the plugin
}
server.start((err) => {
if (err) {
throw err;
}
server.log('info', 'Server running at: ' + server.info.uri);
});
});
In your routes/user.js
在你的 routes/user.js
module.exports =
[
{
method: 'GET',
path: '/',
handler: (request, reply) => {
reply('Hello, world!');
}
},
{
method: 'GET',
path: '/another',
handler: (request, reply) => {
reply('Hello, world again!');
}
},
];
Now run: node server.js
现在运行: node server.js
Cheers
干杯

