使用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/routes
( config/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文件(例如cart
, user
),您可以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
干杯