nodejs ExpressJS routes only working for index

I have routes in separate folder for expressjs. The setup is working fine for the 'index' page, but not for any additional routes.

This is my index.js, inside my routes folder.

 module.exports = function(db) {

    return {
        index: function(req, res, next) {
            res.send('index');
        }
    }
}

This is my join.js, inside my routes folder.

 module.exports = function(db) {

    return {
        join: function(req, res, next) {
            res.send('join');
        }
    }
}

In my app.js, I define my routes like this:

          var routes = require('./routes')(db);
          app.get('/', routes.index);
          app.get('/join', routes.join);

When I go to http://localhost:3000 but when I go to http://localhost:3000/join i get Cannot GET /join

If I define my route for join like this:

 app.get('/join', function(req, res){
     res.send('join 2');
 });

This works.

Any idea what I'm doing wrong here?

Thank you!

I was having a similar problem, but then remembered this is all "just javascript" and was able to muddle out an answer.

If you want to have your routes defined in multiple files (instead of cramming them all into one routes/index.js file) you can just build the routes object in a hackish way (as follows):

var express = require('express')
  , routes = {
       index: require('./routes').index
     , events: require('./routes/events.js').events
  }
  , hbs = require('hbs');

NOTE: You don't need the express and hbs definitions (first and last lines) in there, I just put it in there to give you a little context. This code snippet came directly from the top of my app.js file.

Notice the .index and .events chained onto the require() function calls. That's the key. My events.js file only has one export (events):

exports.events = function(req, res){
  console.log('in events');
  res.render('events', { events: events, title: "EVENTS" });
  console.log('events done');
};

Since the require() function essentially grabs a file and requires (imports) any non-private vars (that is, those attached to the special exports object) and exposes them to the file containing the require() call, I'm able to just grab the specific function I'm requiring from the file I'm including with the require() call. If I had multiple exports defined in the required file, I imagine I could grab them like so (have not tested):

routes = {
    index: require('./routes').index
  , events: require('./routes/events.js').events
  , favorites: require('./routes/events.js').favorites
  , upcoming: require('./routes/events.js').upcoming
}

I suspect that this would give someone with a bunch of nodeJS or MVC experience an aneurysm if they read your code (I'm betting that it would include the same file 3 times, but I'm not really sure). Maybe better off to do:

routes = {
    index: require('./routes').index
  , events: require('./routes/events.js').events
  , favorites: require('./routes/favorites.js').favorites
  , upcoming: require('./routes/upcoming.js').upcoming
}

Otherwise, why not just shove them all in index? Not really sure though, this is only my second day working with Node and any of its related technologies...

Also will probably help you if you throw a console.log statement right after your var declarations:

console.log(routes);

The reason why the routes/index.js file works and your routes/join.js does not is because of Node's module loading rules. Check out the docs for modules/folders as modules

It says that it will try to load these files in order. package.json, index.js, index.node.

You can change the file it loads by creating a package.json file in the directory. Set the main property to the name of the new file.

An example of how to make the routes work the way you want is on another question.

I tested a similar scenario and it worked for me.

I'm guessing the mistake is probably in your routes.js file. You are likely doing:

routes.index = require('./index')(db);
routes.join = require('./join')(db);

Maybe you forget to call the method for join, just doing require(./join). Just a guess.

if you just say

var routes = require('./routes')

By default, node will start looking for the index file (whether it's index.js or index.node). If you want to use your join file, you will need to explicitly say it:

var join = require('./routes/join')

Now i think join.join should work.