使用Hapi时如何将路线存储在单独的文件中?

所有Hapi示例(以及Express中的类似示例)都显示了path在起始文件中的定义:

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); }); 

然而,在用大量不同的路线实施生产应用程序时,不难想象这个文件有多大。 因此,我想分解路由,将它们分组并存储在不同的文件中,如UserRoutes.js,CartRoutes.js,然后将它们附加在主文件(添加到服务器对象)中。 你会如何分开,然后添加?

您可以为用户路由( config/routes/user.js )创build一个单独的文件:

 module.exports = [ { method: 'GET', path: '/users', handler: function () {} }, { method: 'GET', path: '/users/{id}', handler: function () {} } ]; 

与购物车类似。 然后在config/routesconfig/routes/index.js )中创build一个索引文件:

 var cart = require('./cart'); var user = require('./user'); module.exports = [].concat(cart, user); 

然后你可以在主文件中加载这个索引文件并调用server.route()

 var routes = require('./config/routes'); ... server.route(routes); 

或者,对于config/routes/index.js ,不要手动添加path文件(例如cartuser ),您可以dynamic加载它们:

 const fs = require('fs'); let routes = []; fs.readdirSync(__dirname) .filter(file => file != 'index.js') .forEach(file => { routes = routes.concat(require(`./${file}`)) }); module.exports = routes; 

你应该尝试Glue插件: https : //github.com/hapijs/glue 。 它可以让你模块化您的应用程序。 您可以将您的路线放置在不同的子目录中,然后将其包含为Hapi.js插件。 你也可以使用Glue包含其他的插件(Inert,Vision,Good)以及用清单对象(或者json文件)来configuration你的应用程序。

快速浏览:

server.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:

 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:

 { "name": "IndexRoute", "version": "1.0.0" } 

./modules/index/home.js:

 exports.register = function(req, reply) { reply.view('home', { title: 'Awesome' }); }); 

看看Dave Stevens的这篇精彩文章,了解更多细节和例子。

你可以使用require-hapiroutes来为你做一些组织和装载。 (我是作者,所以我有点偏袒,为了让我的生活更容易pipe理路线)

我是require-directory的忠实粉丝,并且希望能够像pipe理我的路由一样简单。 这可以让你混合和匹配你的模块和模块path目录中的路线。

然后你可以做这样的事情…

 var routes = require('./routes'); server.route(routes.routes); 

然后在你的目录中,你可以有一个路线文件,如…

 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'] } }]; 

或者,您可以通过分配模块上的“routes”属性来进行混合和匹配

 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'] } }]; 

总是有好的select。 在github或npmjs网站上有完整的文档。

也可以使用索引文件来加载目录中的所有路由

index.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; 

其他文件在相同的目录中,例如:

 module.exports = [ { method: 'POST', path: '/api/user', config: { } }, { method: 'PUT', path: 'api/user/{userId}', config: { } } ]; 

而不是在你的根/索引

 const Routes = require('./src/routes'); /** * Add all the routes */ for (var route in Routes) { server.route(Routes[route]); } 

有趣的是看到这么多不同的解决scheme,这里是另一个。

全球化的救援

对于我最近的项目,我决定使用特定的名称模式对文件进行匹配,然后逐个将它们请求到服务器中。

在创buildserver对象之后导入路由

 // 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. // ... 

glob模式**/*route*.js将查找指定的当前工作目录之内和之下的所有文件,其名称包含path字,并以后缀.js结尾。

文件结构

在globbing的帮助下,我们在server对象和它的路由之间有一个松散的耦合。 只需添加新的路由文件,下次重新启动服务器时将包含这些文件。

我喜欢根据它们的path来构造path文件,并用它们的HTTP方法命名它们,如下所示:

 server.js routes/ users/ get-route.js patch-route.js put-route.js articles/ get-route.js patch-route.js put-route.js 

示例路由文件routes/users/get-route.js

 module.exports = { method: 'GET', path: '/users', config: { description: 'Fetch users', // ... }, handler: function (request, reply) { // ... } }; 

最后的想法

Globbing和迭代文件并不是一个特别快的过程,因此caching层可能值得在生产环境中进行调查。

尝试hapi-auto-route插件! 这是非常简单的使用,并允许您的路线path前缀。

我知道这已经被批准了。 我放下我的解决scheme,以防有人想要快速解决问题,并向Hapi提出新的解决scheme。

此外,我也包含了一些NPM,所以Newbees可以看到如何使用server.register与多个插件的情况下( good + hapi-auto-route

安装了一些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); }); }); 

在你的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!'); } }, ]; 

现在运行: node server.js

干杯