Hoe routes in aparte bestanden opslaan bij gebruik van Hapi?

Alle Hapi-voorbeelden (en soortgelijke in Express) laten zien dat routes zijn gedefinieerd in het startbestand:

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

Het is echter niet moeilijk om je voor te stellen hoe groot dit bestand kan worden bij het implementeren van een productietoepassing met een heleboel verschillende routes. Daarom wil ik routes opsplitsen, groeperen en opslaan in aparte bestanden, zoals UserRoutes.js, CartRoutes.js en ze vervolgens bijvoegen in het hoofdbestand (toevoegen aan serverobject). Hoe zou je voorstellen om dat te scheiden en vervolgens toe te voegen?


Antwoord 1, autoriteit 100%

U kunt een apart bestand maken voor gebruikersroutes (config/routes/user.js):

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

Vergelijkbaar met winkelwagen. Maak vervolgens een indexbestand in config/routes(config/routes/index.js):

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

U kunt dit indexbestand vervolgens in het hoofdbestand laden en server.route():

aanroepen

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

Als alternatief, voor config/routes/index.js, in plaats van de routebestanden (bijv. cart, user) handmatig toe te voegen, kan ze dynamisch laden:

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

Antwoord 2, autoriteit 14%

Probeer de Glue-plug-in: https://github.com/hapijs/glue. Hiermee kunt u uw toepassing modulair maken. U kunt uw routes in afzonderlijke submappen plaatsen en ze vervolgens als Hapi.js-plug-ins opnemen. U kunt ook andere plug-ins (Inert, Vision, Good) toevoegen aan Glue en uw toepassing configureren met een manifest-object (of json-bestand).

Snel voorbeeld:

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

Bekijk ditprachtige artikel van Dave Stevens voor meer details en voorbeelden.


Antwoord 3, autoriteit 7%

U kunt require-hapiroutesgebruiken om een ​​deel van de organisatie en het laden voor u te doen . (Ik ben de auteur, dus ik ben een beetje bevooroordeeld, ik heb het geschreven om mijn leven gemakkelijker te maken bij het beheren van routes)

Ik ben een grote fan van require-directoryen wilde een manier om mijn routes net zo gemakkelijk. Hiermee kun je routes in je modules mixen en matchen en modules in mappen met routes.

Je kunt dan zoiets doen…

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

Dan zou je in je directory een routebestand kunnen hebben zoals…

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

Of je kunt mixen en matchen door een eigenschap “routes” op de module toe te wijzen

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

Altijd goed om opties te hebben. Er is volledige documentatie over de githubof npmjs-site ervoor.


Antwoord 4, autoriteit 2%

of je kunt een indexbestand gebruiken om alle routes te laden
in de map

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;

andere bestanden in dezelfde map zoals:

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

en dan in je root/index

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

Antwoord 5

Interessant om zoveel verschillende oplossingen te zien, hier is er nog een.

Te hulp schieten

Voor mijn laatste project besloot ik te zoeken naar bestanden met een bepaald naampatroon en ze vervolgens een voor een naar de server te sturen.

Importeer routes na het aanmaken van het serverobject

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

Het glob-patroon **/*route*.jsvindt alle bestanden binnen en onder de opgegeven huidige werkmap met een naam die het woord routebevat en eindigt met het achtervoegsel .js.

Bestandsstructuur

Met behulp van globbing hebben we een losse koppeling tussen het serverobject en zijn routes. Voeg gewoon nieuwe routebestanden toe en ze zullen worden opgenomen de volgende keer dat u uw server opnieuw opstart.

Ik structureer de routebestanden graag volgens hun pad en geef ze een naam met hun HTTP-methode, zoals:

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

Voorbeeld routebestand routes/users/get-route.js

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

Laatste gedachten

Globbing en itereren over bestanden is niet een bijzonder snel proces, daarom kan een caching-laag de moeite waard zijn om te onderzoeken in productie-builds, afhankelijk van uw omstandigheden.


Antwoord 6

Probeer de plug-in hapi-auto-route! Het is heel eenvoudig te gebruiken en laat een voorvoegsel toe in je routepad.

Volledige openbaarmaking: ik ben de auteur van deze plug-in


Antwoord 7

Ik weet dat dit al is goedgekeurd. Ik heb mijn oplossing neergezet voor het geval iemand een snelle oplossing wil en nieuw is bij Hapi.

Ik heb ook wat NPM toegevoegd zodat nieuwkomers kunnen zien hoe ze de server.registermoeten gebruiken met meerdere plug-ins in het geval ( good+ hapi-auto-route)

Enkele npm-pakketten geïnstalleerd:

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

In uw 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!');
        } 
    },
];

Voer nu uit: node server.js

Proost

Other episodes