84

I want to separate Routes from my server.js file.

I am following this tutorial on Scotch.io http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4

It is working if all lines are on server.js file. But I am failing to separate. How can I make this work?

server.js

// set up ======================================================================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// configuration ===============================================================
app.use(bodyParser());

var port = process.env.PORT || 8000;

var mongoose = require('mongoose');
var database = require('./config/database');
mongoose.connect(database.url);
var Video = require('./app/models/video');

// routes =======================================================================
app.use('/api', require('./app/routes/routes').router);

// listen (start app with node server.js) ======================================
app.listen(port);
console.log("ready captain, on deck" + port);

module.exports = app;

And the app/routes/routes.js

var express = require('express');
var router = express.Router();

router.use(function(req, res, next) {
  console.log('Something is happening.');
  next();
});

router.get('/', function(req, res) {
  res.json({ message: 'hooray! welcome to our rest video api!' });  
});


router.route('/videos')

  .post(function(req, res) {

    var video = new Video();
    video.title = req.body.title;

    video.save(function(err) {
  if (err)
    res.send(err);

  res.json({ message: 'Video criado!' });
});


  })

  .get(function(req, res) {
    Video.find(function(err, videos) {
      if (err)
        res.send(err);

      res.json(videos);
    });
  });

module.exports.router = router;
yellowbuck
  • 1,071
  • 1
  • 15
  • 20
  • whats the node error? i think `module.exports = { router: router }` in routes.js should do it – bbuecherl May 28 '14 at 23:19
  • Hi @bbuecherl, I am getting a ReferenceError: Video is not defined – yellowbuck May 28 '14 at 23:25
  • It looks like you have lowercase 'v' for videos and trying to reference uppercase 'V' for videos. – Ben May 28 '14 at 23:30
  • Looks like he is not able to find `Video`, you need to move your line `var Video = require("./app/models/video");` from `server.js` to `routes.js`. – bbuecherl May 28 '14 at 23:30
  • @bbuecherl I tried but it can't find the module... Ben, the code is working when all on server.js... – yellowbuck May 28 '14 at 23:41
  • 1
    When including video.js in route.js, use proper path something like "..\models\video" – Kiran Pagar May 28 '14 at 23:54
  • @KiranPagar, thank you it worked... "../models/video" – yellowbuck May 29 '14 at 00:02
  • check this sample http://wiki.workassis.com/nodejs-express-separate-routes for making a separate route file – Bikesh M Aug 02 '16 at 10:56
  • Does this answer your question? [How to include route handlers in multiple files in Express?](https://stackoverflow.com/questions/6059246/how-to-include-route-handlers-in-multiple-files-in-express) – ggorlen Mar 14 '21 at 00:08

9 Answers9

105

Server.js

var express = require('express');
var app = express();

app.use(express.static('public'));

//Routes
app.use(require('./routes'));  //http://127.0.0.1:8000/    http://127.0.0.1:8000/about

//app.use("/user",require('./routes'));  //http://127.0.0.1:8000/user  http://127.0.0.1:8000/user/about


var server = app.listen(8000, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Example app listening at http://%s:%s", host, port)

})

routes.js

var express = require('express');
var router = express.Router();

//Middle ware that is specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});


// Define the home page route
router.get('/', function(req, res) {
  res.send('home page');
});

// Define the about route
router.get('/about', function(req, res) {
  res.send('About us');
});


module.exports = router;

*In routs.js you should define Middle ware

ref http://wiki.workassis.com/nodejs-express-separate-routes/

Bikesh M
  • 8,163
  • 6
  • 40
  • 52
69

As far as separating routes from main file is concerned..

Server.js

//include the routes file
var routes = require('./routes/route');
var users = require('./routes/users');
var someapi = require('./routes/1/someapi');

////////
app.use('/', routes);
app.use('/users', users);
app.use('/1/someapi', someapi);

routes/route.js

//last line - try this
module.exports = router;

Also for new project you can try on command line

express project_name

You will need express-generator for that

Kiran Pagar
  • 1,005
  • 15
  • 21
  • 2
    This doesn't really separate the routes, it separates the controller. @Bikesh has the more correct solution. – superluminary Dec 05 '16 at 14:14
  • I am trying to separate API from main app file then its showing error `apiRoutes.post('/register', function(req, res, next) { ^ TypeError: Cannot read property 'post' of undefined at Object. (F:\saurabh_sharma\nodejs\salecrm\app\routes.js:4:10) at Module._compile (module.js:413:34) at Object.Module._extensions..js (module.js:422:10) ...` – Saurabh Sharma Jan 18 '17 at 10:32
  • ahh i see, i think i can use fs for best solution – Taufik Nurhidayat Apr 06 '23 at 03:48
24

Another way to separate routes into their own files with Express 4.0:

server.js

var routes = require('./routes/routes');
app.use('/', routes);

routes.js

module.exports = (function() {
    'use strict';
    var router = require('express').Router();

    router.get('/', function(req, res) {
        res.json({'foo':'bar'});
    });

    return router;
})();
jrbedard
  • 3,662
  • 5
  • 30
  • 34
14

One way to separate routes into their own file.

SERVER.JS

var routes = require('./app/routes/routes');  //module you want to include
var app=express();
routes(app);   //routes shall use Express

ROUTES.JS

module.exports=function(app) {
 //place your routes in here..
 app.post('/api/..., function(req, res) {.....}   //example
}
Mick Cullen
  • 9,214
  • 3
  • 21
  • 17
6

If you're using express-4.x with TypeScript and ES6, this would be a best template to use;

src/api/login.ts

import express, { Router, Request, Response } from "express";

const router: Router = express.Router();
// POST /user/signin
router.post('/signin', async (req: Request, res: Response) => {
    try {
        res.send('OK');
    } catch (e) {
        res.status(500).send(e.toString());
    }
});

export default router;

src/app.ts

import express, { Request, Response } from "express";
import compression from "compression";  // compresses requests
import expressValidator from "express-validator";
import bodyParser from "body-parser";
import login from './api/login';

const app = express();

app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());

app.get('/public/hc', (req: Request, res: Response) => {
  res.send('OK');
});

app.use('/user', login);

app.listen(8080, () => {
    console.log("Press CTRL-C to stop\n");
});

Much clear and reliable rather using var and module.exports.

gihanchanuka
  • 4,783
  • 2
  • 32
  • 32
3

We Ought To Only Need 2 Lines of Code

TL;DR

$ npm install express-routemagic --save
const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')

That's it!

More info:

How you would do this? Let's start with file structuring:

project_folder
|--- routes
|     |--- api
|           |--- videos
|           |     |--- index.js
|           |
|           |--- index.js
|     
|--- server.js

Note that under routes there is a structure. Route Magic is folder aware, and will imply this to be the api uri structure for you automatically.

In server.js

Just 2 lines of code:

const magic = require('express-routemagic')
magic.use(app, __dirname, 'routes')

In routes/api/index.js

const router = require('express').Router()

router.get('/', (req, res) => { 
    res.json({ message: 'hooray! welcome to our rest video api!' })
})

In routes/api/videos/index.js

Route Magic is aware of your folder structure and sets up the same structuring for your api, so this url will be api/videos

const router = require('express').Router()

router.post('/', (req, res) => { /* post the video */ })
router.get('/', (req, res) => { /* get the video */ })

Disclaimer: I wrote the package. But really it's long-overdue, it reached my limit to wait for someone to write it.

Calvintwr
  • 8,308
  • 5
  • 28
  • 42
2

An issue I was running into was attempting to log the path with the methods when using router.use ended up using this method to resolve it. Allows you to keep path to a lower router level at the higher level.

routes.js

var express = require('express');
var router = express.Router();

var posts = require('./posts');

router.use(posts('/posts'));  

module.exports = router;

posts.js

var express = require('express');
var router = express.Router();

let routeBuilder = path => {

  router.get(`${path}`, (req, res) => {
    res.send(`${path} is the path to posts`);
  });

  return router

}

module.exports = routeBuilder;

If you log the router stack you can actually see the paths and methods

Zack Lucky
  • 671
  • 3
  • 10
  • 25
1

I simply delcared the files and used require in the server.js file

 app.use(express.json());
 require('./app/routes/devotion.route')(app);
 require('./app/routes/user.route')(app);
Kisakyamukama
  • 99
  • 1
  • 10
0

In my case, I like to have as much Typescript as possible. Here is how I organized my routes with classes:

export default class AuthService {
    constructor() {
    }

    public login(): RequestHandler {
       return this.loginUserFunc;
    }

    private loginUserFunc(req: Request, res: Response): void {
        User.findOne({ email: req.body.email }, (err: any, user: IUser) => {
            if (err)
                throw err;
            if(!user)
                return res.status(403).send(AuthService.noSuccessObject());
            else
                return AuthService.comparePassword(user, req, res);
        })
    }
}

From your server.js or where you have your server code, you can call the AuthService in the following way:

import * as express from "express";
import AuthService from "./backend/services/AuthService";

export default class ServerApp {
    private authService: AuthService;

    this.authService = new AuthService();

    this.myExpressServer.post("/api/login", this.authService.login(), (req: express.Request, res: express.Response) => {
    });
}
Leonardo Venoso
  • 1,203
  • 12
  • 15