Как хранить маршруты в отдельных файлах при использовании Hapi?
Все примеры 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, а затем присоединять их в основном файле (добавить к серверному объекту). Как бы вы предложили отделить это, а затем добавить?
Ответы
Ответ 1
Вы можете создать отдельный файл для пользовательских маршрутов (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;
Ответ 2
Вы должны попробовать плагин Glue: https://github.com/hapijs/glue. Это позволяет вам модулировать ваше приложение. Вы можете разместить свои маршруты в отдельных подкаталогах, а затем включить их в качестве плагинов Hapi.js. Вы также можете включить другие плагины (Inert, Vision, Good) с помощью Glue, а также настроить приложение с помощью манифеста (или 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);
});
});
./модули/индекс/index.js:
exports.register = function(server, options, next) {
server.route({
method: 'GET',
path: '/',
handler: require('./home')
});
});
exports.register.attributes = {
pkg: require('./package.json')
};
./модули/индекс/package.json:
{
"name": "IndexRoute",
"version": "1.0.0"
}
./модули/индекс/home.js:
exports.register = function(req, reply) {
reply.view('home', { title: 'Awesome' });
});
Взгляните на эту замечательную статью Дэйва Стивенса за подробностями и примерами.
Ответ 3
Вы можете использовать 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']
}
}];
Всегда, хорошо иметь опции. Существует полная документация по github или npmjs сайт для него.
Ответ 4
или вы можете использовать индексный файл для загрузки всех маршрутов
в каталоге
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]);
}
Ответ 5
Интересно видеть так много разных решений, вот еще один.
Глобус на помощь
В моем последнем проекте я решил погладить файлы с определенным шаблоном имени, а затем потребовал их на сервере один за другим.
Импортировать маршруты после создания объекта 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) {
// ...
}
};
Заключительные мысли
Глобулизация и повторение файлов не является особенно быстрым процессом, поэтому уровень кэширования может стоить исследования в производственных сборках в зависимости от ваших обстоятельств.
Ответ 6
Попробуйте hapi-auto-route плагин! Это очень просто использовать и разрешить префикс в вашем маршруте маршрута.
Ответ 7
Я знаю, что это уже одобрено. Я подавил свое решение на случай, если кто-то захочет быстро исправить ситуацию и принести новую новость Хапи.
Также я включил некоторый 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
Приветствия