59

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

然而,当使用大量不同的路径实现生产应用程序时,不难想象这个文件可以增长到多大。因此,我想分解路由,将它们分组并存储在单独的文件中,例如 UserRoutes.js、CartRoutes.js,然后将它们附加到主文件中(添加到服务器对象)。您如何建议将其分开然后添加?

4

7 回答 7

104

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

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

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

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,而不是手动添加路由文件(例如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;
于 2015-01-04T16:28:10.863 回答
15

您应该尝试 Glue 插件:https ://github.com/hapijs/glue 。它允许您模块化您的应用程序。您可以将您的路线放在单独的子目录中,然后将它们作为 Hapi.js 插件包含在内。您还可以在 Glue 中包含其他插件(Inert、Vision、Good),并使用清单对象(或 json 文件)配置您的应用程序。

快速示例:

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 的这篇精彩文章,了解更多详细信息和示例。

于 2015-10-29T07:33:30.320 回答
7

您可以使用require-hapiroutes为您做一些组织和加载。(我是作者,所以有点偏见,我写它是为了让我在管理路线时更轻松)

我是require-directory的忠实粉丝,并且想要一种方法来轻松管理我的路线。这使您可以将模块中的路由和目录中的模块与路由混合和匹配。

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

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

或者,您可以通过分配给模块上的“路由”属性来混合和匹配

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

总是,很高兴有选择。在githubnpmjs站点上有完整的文档。

于 2015-10-19T15:54:52.637 回答
2

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

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]);
}
于 2015-10-20T11:25:45.470 回答
1

看到这么多不同的解决方案很有趣,这是另一个。

全球救援

对于我的最新项目,我决定使用特定名称模式查找文件,然后将它们一个一个地请求到服务器中。

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

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

文件结构

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

我喜欢根据路径来构造路由文件,并用它们的 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) {
        // ...
    }
};

最后的想法

遍历和迭代文件并不是一个特别快的过程,因此根据您的情况,缓存层可能值得在生产构建中进行研究。

于 2016-03-25T10:05:21.973 回答
1

试试hapi-auto-route插件!在您的路由路径中使用和允许前缀非常简单。

完全披露:我是这个插件的作者

于 2017-04-04T08:00:34.620 回答
0

我知道这已经被批准了。我写下了我的解决方案,以防有人想要快速修复和新的 Hapi。

此外,我还包含了一些 NPM,以便 Newbees 可以看到如何在 case ( + )中使用server.registerwith multiple plugingoodhapi-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

干杯

于 2017-08-17T04:43:06.280 回答