Search code examples
javascriptnode.jsexpressurl-routing

Express dynamic routing using / and /:slug as different route files


so I'm in the process of refactoring my node/express application and I'm trying to separate my roots. Here's my issue:

I want an homepage and then a completely different page for extensions, that doesn't fall into other routes.

So for example, let's say I have 3 pages: Homepage, About, and then an user page where the URL is "mysite.com/username123".

Now I know (or at least believe) this can be accomplished by doing something like:

var express = require('express');
var router = express.Router();
router.get('/:slug', function(req, res, next) {
    if(req.params.slug) {
        var data = { 
            my: 'data'
        };
        res.render('index', data);
    } else {
        var userdata = { 
            my: 'data'
        };
        res.render('user', userdata);
    }
});
module.exports = router;

But this isn't what I want to do; I would like to keep these in two different route files. So my app.js file would have something like:

var routes = require('./routes/index');
var users = require('./routes/users');
var about = require('./routes/about');

app.use('/', index);
app.use('/', users);
app.use('/about', about);

Where /users renders if there is a slug. This actually sort of works. If there is no :slug, the index file is loaded, otherwise the users file is loaded (which has the :slug in the route file, not shown here). But then /about is overwritten.

Now I supposed I could shove /about to the top of the list and that would work, but this seems extremely sloppy and the whole point of doing this is to properly structure my code.

How are situations like this supposed to be properly handled? Could someone please give me some help here?


Solution

  • It happens because /about is overridden by /:slug. In other words, express cannot tell if about is not meant to be a slug.

    Solutions would be to either

    1. Add a url param to let express differentiate the routes.

      router.get('/users/:slug')

    2. Skip to next route

      router.get(':slug', function (req, res, next) {
         if (req.params.slug === 'about') {
            return next();
      }
      
        // get user data and render
        res.render('user', userdata);
      });
      

    Attach the /about route below this.