Tous les exemples Hapi (et similaires dans Express) montrent que les routes sont définies dans le fichier de départ:
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);
});
Cependant, il n'est pas difficile d'imaginer la taille de ce fichier lors de l'implémentation d'une application de production avec une tonne de routes différentes. Par conséquent, je voudrais décomposer les itinéraires, les regrouper et les stocker dans des fichiers séparés, comme UserRoutes.js, CartRoutes.js, puis les attacher dans le fichier principal (ajouter à l'objet serveur). Comment proposeriez-vous de séparer cela, puis d'ajouter?
Vous pouvez créer un fichier séparé pour les itinéraires utilisateur (config/routes/user.js
):
module.exports = [
{ method: 'GET', path: '/users', handler: function () {} },
{ method: 'GET', path: '/users/{id}', handler: function () {} }
];
De même avec le chariot. Créez ensuite un fichier d'index dans config/routes
(config/routes/index.js
):
var cart = require('./cart');
var user = require('./user');
module.exports = [].concat(cart, user);
Vous pouvez ensuite charger ce fichier d'index dans le fichier principal et appeler server.route()
:
var routes = require('./config/routes');
...
server.route(routes);
Alternativement, pour config/routes/index.js
, Au lieu d'ajouter manuellement les fichiers de route (par exemple cart
, user
), vous pouvez les charger dynamiquement:
const fs = require('fs');
let routes = [];
fs.readdirSync(__dirname)
.filter(file => file != 'index.js')
.forEach(file => {
routes = routes.concat(require(`./${file}`))
});
module.exports = routes;
Vous devriez essayer le plugin Glue: https://github.com/hapijs/glue . Il vous permet de modulariser votre application. Vous pouvez placer vos itinéraires dans des sous-répertoires séparés, puis les inclure en tant que plugins Hapi.js. Vous pouvez également inclure d'autres plugins (Inert, Vision, Good) avec Glue ainsi que configurer votre application avec un objet manifeste (ou fichier json).
Exemple rapide:
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' });
});
Jetez un oeil à this merveilleux article de Dave Stevens pour plus de détails et d'exemples.
Vous pouvez utiliser require-hapiroutes pour faire une partie de l'organisation et du chargement pour vous. (Je suis l'auteur donc je suis un peu biaisé, je l'ai écrit pour me faciliter la vie dans la gestion des itinéraires)
Je suis un grand fan de require-directory et je voulais un moyen de gérer mes itinéraires tout aussi facilement. Cela vous permet de mélanger et de faire correspondre des routes dans vos modules et des modules dans des répertoires avec des routes.
Vous pouvez alors faire quelque chose comme ça ...
var routes = require('./routes');
server.route(routes.routes);
Ensuite, dans votre répertoire, vous pourriez avoir un fichier d'itinéraire comme ...
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']
}
}];
Ou, vous pouvez mélanger et assortir en attribuant à une propriété "routes" sur le 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']
}
}];
Toujours bien d'avoir des options. Il existe une documentation complète sur le site github ou npmjs pour cela.
ou vous pouvez utiliser un fichier d'index pour charger toutes les routes du répertoire
/**
* 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;
d'autres fichiers dans le même répertoire comme:
module.exports = [
{
method: 'POST',
path: '/api/user',
config: {
}
},
{
method: 'PUT',
path: 'api/user/{userId}',
config: {
}
}
];
et que dans votre racine/index
const Routes = require('./src/routes');
/**
* Add all the routes
*/
for (var route in Routes) {
server.route(Routes[route]);
}
Essayez hapi-auto-route plugin! Il est très simple à utiliser et autorise le préfixe dans le chemin de votre itinéraire.
Intéressant de voir autant de solutions différentes, en voici une autre.
Pour mon dernier projet, j'ai opté pour la globalisation des fichiers avec un modèle de nom particulier, puis les exiger sur le serveur un par un.
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.
// ...
Le motif glob **/*route*.js
trouvera tous les fichiers dans et sous le répertoire de travail actuel spécifié avec un nom qui contient le mot route et se termine par le suffixe . js.
Avec l'aide du globbing, nous avons un couplage lâche entre l'objet server
et ses routes. Ajoutez simplement de nouveaux fichiers de route et ils seront inclus la prochaine fois que vous redémarrerez votre serveur.
J'aime structurer les fichiers de route en fonction de leur chemin et les nommer avec leur méthode HTTP, comme ceci:
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) {
// ...
}
};
La globalisation et l'itération sur les fichiers ne sont pas un processus particulièrement rapide, donc une couche de mise en cache peut valoir la peine d'être étudiée dans les builds de production selon vos circonstances.
Je sais que cela est déjà approuvé. J'ai déposé ma solution au cas où quelqu'un voudrait une solution rapide et nouveau pour Hapi.
J'ai également inclus du NPM pour que les Newbees puissent voir comment utiliser le server.register
avec plusieurs plugins dans le cas (good
+ hapi-auto-route
)
Installation de certains 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);
});
});
Dans votre 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!');
}
},
];
Exécutez maintenant: node server.js
À votre santé