Node.js, restify and proper routing
Asked Answered
L

3

8

I'm still wrapping my head around Node, but I have a very simple question. I see a lot of node examples where people are declaring their routes and all their logic in a single app.js file (or sometimes splitting them off into subfiles).

My question is basically: is it better to keep all your route declarations in the app or bootstrap a generic route that maps to your file structure. This may seem like a primitive question but my goal is to grasp what's most efficient within node.

I'm currently building an API handler with Restify but I have another app that uses Express (so this question will likely answer both questions).

In my route I can either declare a single route bootstrap like so:

app.all('/api/:package/:controller', function(request, response) {
    var controller = require(
        '../' + request.params.package + '/api/' + request.params.controller
    );
    controller.index(request, response);
    response.end();
});

This basically accepts all calls from the API and targets the proper api controller. Alternatively I can declare each route individually or perhaps even write an loop that goes through each of my controllers and declares them on init. So:

for (var i in packages.controllers) {
    app.all('api/' + package + '/' + controllers[i].name, function(request, response) {
       var controller = require(
           '../' + request.params.package + '/api/' + request.params.controller
       );
       controller.index(request, response);
    }
}

packages.controllers being an array of all possible controllers. Note the above code is not accurate, I have an HMVC folder structure so the code is a bit more complicated than the above. But you get the point.

I'm wondering what the consequences of either are and if it really matters at all?

Thanks!

Lexicographer answered 20/5, 2012 at 2:22 Comment(0)
C
3

The exploding app.js file prompted a couple of us to create a small reference app to codify a standard Express app structure. It's not rocket science, but rather a set of conventions that makes things more organized.

You can find it here: https://github.com/EAAppFoundry/tableau

We'd love suggestions/pull requests if there something we got wrong or is missing.

Conviction answered 20/5, 2012 at 18:22 Comment(2)
Thanks Don, that's an interesting boilerplate you guys have there. However I guess my main question isn't resolved still. In your app you're defining each of the routes explictly in routes.js. I want to generate this automagically so I don't have to manually define the routes.Lexicographer
magic stuff tends to scare me.. :) We went with the routes.js b/c it was explicit. it makes it easy to see what route matches have been declared without polluting it with the impl code.Conviction
A
6

I would not recommend a single app.js at all. You will end up with a 5,000+ line file which is a nightmare to maintain.

The largest issue I see with your snippet is that even though require() gets cached, it has to perform a synchronous IO request. It's just a bad habit to get into.

Similar to what Don recommends, I have had the best luck splitting out routes into modules which export a single function which accept an instance of the app. You can think of it as "decorating" the app instance:

// app.js
var app = express.createServer();
app.configure(function(){ //... });

require('./foo')(app);

// foo.js
exports = module.exports = function(app){

    app.get('/whatever', function(req, res){});

};
Apricot answered 20/5, 2012 at 19:20 Comment(1)
Hmmm, I see but it still requires me to explicitly register each of the routes in my app.js. I'm not keen on doing that, I want the app to autogenerate the routes depending on my file structure. I guess I'm looking for a solution that parses the file structure and generates the routes at node.js launch time. Then all the routes and modules will be stored in memory (so no synchronous issues will exist). Basically I'm learning forward my second code snippet. I think, that it will loop through all my controllers, require the controllers and store them in memory. I think that makes sense...lol.Lexicographer
C
3

The exploding app.js file prompted a couple of us to create a small reference app to codify a standard Express app structure. It's not rocket science, but rather a set of conventions that makes things more organized.

You can find it here: https://github.com/EAAppFoundry/tableau

We'd love suggestions/pull requests if there something we got wrong or is missing.

Conviction answered 20/5, 2012 at 18:22 Comment(2)
Thanks Don, that's an interesting boilerplate you guys have there. However I guess my main question isn't resolved still. In your app you're defining each of the routes explictly in routes.js. I want to generate this automagically so I don't have to manually define the routes.Lexicographer
magic stuff tends to scare me.. :) We went with the routes.js b/c it was explicit. it makes it easy to see what route matches have been declared without polluting it with the impl code.Conviction
B
0

I don't think there should be any real problem with looping through the directory tree and generating the routes. However, it'll be hard to define route based middleware and other routing features (such as variables in the routes) in a nice way.

I wrote a library that I use to define my routes declaratively and with minimal repetition which you might be interested in. It's inspired by Rails resourceful routing and is pretty flexible - the idea is to build a hash of routes and subroutes; there are also facilities to define groups of routes, middleware and variables.

https://github.com/cheesun/express-declarative-routing

Although it doesn't automatically generate the routes based on your directory structure, I think that'd be a cool feature and welcome you add it to the library.

Barret answered 8/3, 2014 at 4:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.