如何在Express中的多个文件中包含路由处理程序?

时间:2011-05-19 13:16:12

标签: node.js express

在我的NodeJS express应用程序中,我app.js有一些常用路由。然后在wf.js文件中,我想定义更多的路由。

如何让app.js识别wf.js文件中定义的其他路由处理程序?

一个简单的 require 似乎不起作用。

14 个答案:

答案 0 :(得分:347)

如果您想将路由放在单独的文件中,例如 routes.js ,您可以通过这种方式创建routes.js文件:

module.exports = function(app){

    app.get('/login', function(req, res){
        res.render('login', {
            title: 'Express Login'
        });
    });

    //other routes..
}

然后您可以通过 app.js 以这种方式传递app 对象来要求它:

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

还要看一下这些例子

  

https://github.com/visionmedia/express/tree/master/examples/route-separation

答案 1 :(得分:93)

在@ShadowCloud示例的基础上,我能够动态地包含子目录中的所有路由。

路由/ index.js

var fs = require('fs');

module.exports = function(app){
    fs.readdirSync(__dirname).forEach(function(file) {
        if (file == "index.js") return;
        var name = file.substr(0, file.indexOf('.'));
        require('./' + name)(app);
    });
}

然后将路径文件放在routes目录中,如下所示:

路由/ test1.js

module.exports = function(app){

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

    //other routes..
}

根据我的需要重复多次,最后在 app.js 放置

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

答案 2 :(得分:83)

即使这是一个较老的问题,我偶然发现了寻找类似问题的解决方案。在尝试了一些解决方案后,我最终走向了一个不同的方向,并认为我会为最终到此处的其他人添加我的解决方案。

在express 4.x中,您可以获取路由器对象的实例并导入包含更多路由的另一个文件。您甚至可以递归执行此操作,以便您的路由导入其他路由,从而允许您创建易于维护的URL路径。例如,如果我的'/ tests'端点已经有一个单独的路由文件,并且想为'/ tests / automated'添加一组新的路由,我可能想要将这些'/ automated'路由分解为另一个文件到保持我的'/ test'文件小而易于管理。它还允许您通过URL路径对路由进行逻辑分组,这非常方便。

./app.js的内容:

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

var testRoutes = require('./routes/tests');

// Import my test routes into the path '/test'
app.use('/tests', testRoutes);

./routes/tests.js的内容

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

var automatedRoutes = require('./testRoutes/automated');

router
  // Add a binding to handle '/test'
  .get('/', function(){
    // render the /tests view
  })

  // Import my automated routes into the path '/tests/automated'
  // This works because we're already within the '/tests' route so we're simply appending more routes to the '/tests' endpoint
  .use('/automated', automatedRoutes);

module.exports = router;

./routes/testRoutes/automated.js的内容:

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

router
   // Add a binding for '/tests/automated/'
  .get('/', function(){
    // render the /tests/automated view
  })

module.exports = router;

答案 3 :(得分:18)

在前一个答案上构建更多内容,此版本的routes / index.js将忽略任何不以.js(及其本身)结尾的文件

var fs = require('fs');

module.exports = function(app) {
    fs.readdirSync(__dirname).forEach(function(file) {
        if (file === "index.js" || file.substr(file.lastIndexOf('.') + 1) !== 'js')
            return;
        var name = file.substr(0, file.indexOf('.'));
        require('./' + name)(app);
    });
}

答案 4 :(得分:17)

.js文件夹中所有/routes个文件的完整递归路由,将其放入app.js

// Initialize ALL routes including subfolders
var fs = require('fs');
var path = require('path');

function recursiveRoutes(folderName) {
    fs.readdirSync(folderName).forEach(function(file) {

        var fullName = path.join(folderName, file);
        var stat = fs.lstatSync(fullName);

        if (stat.isDirectory()) {
            recursiveRoutes(fullName);
        } else if (file.toLowerCase().indexOf('.js')) {
            require('./' + fullName)(app);
            console.log("require('" + fullName + "')");
        }
    });
}
recursiveRoutes('routes'); // Initialize it

/routes中您放置whatevername.js并初始化您的路线:

module.exports = function(app) {
    app.get('/', function(req, res) {
        res.render('index', { title: 'index' });
    });

    app.get('/contactus', function(req, res) {
        res.render('contactus', { title: 'contactus' });
    });
}

答案 5 :(得分:6)

我正在尝试使用“ express”:“ ^ 4.16.3”更新此答案。这个答案类似于ShortRound1911。

server.js

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const db = require('./src/config/db');
const routes = require('./src/routes');
const port = 3001;

const app = new express();

//...use body-parser
app.use(bodyParser.urlencoded({ extended: true }));

//...fire connection
mongoose.connect(db.url, (err, database) => {
  if (err) return console.log(err);

  //...fire the routes
  app.use('/', routes);

  app.listen(port, () => {
    console.log('we are live on ' + port);
  });
});

/src/routes/index.js

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

const siswaRoute = require('./siswa_route');

app.get('/', (req, res) => {
  res.json({item: 'Welcome ini separated page...'});
})
.use('/siswa', siswaRoute);

module.exports = app;

/src/routes/siswa_route.js

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

app.get('/', (req, res) => {
  res.json({item: 'Siswa page...'});
});

module.exports = app;

我希望这可以帮助某人。编码愉快!

答案 6 :(得分:5)

对所有这些答案进行一次调整:

var routes = fs.readdirSync('routes')
      .filter(function(v){
         return (/.js$/).test(v);
      });

只需使用正则表达式通过测试数组中的每个文件进行过滤。它不是递归的,但会过滤掉不以.js结尾的文件夹

答案 7 :(得分:5)

我知道这是一个老问题,但我试图找出类似于我自己的东西,这是我最终的地方,所以我想把我的解决方案解决类似的问题以防其他人有同样的问题我遇到的问题。那里有一个很好的节点模块叫做consign,可以为你做很多文件系统的东西(即没有readdirSync的东西)。例如:

我有一个安静的API应用程序我正在尝试构建,我想把所有请求放到' / api / *'要进行身份验证,我想将我在api中的所有路由存储到他们自己的目录中(让我们称之为#ap;')。在应用程序的主要部分:

app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));

在routes目录中,我有一个名为" api"的目录。和一个名为api.js的文件。在api.js中,我只是:

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

// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({cwd: 'routes'})
  .include('api')
  .into(router);

module.exports = router;

一切都按预期工作。希望这有助于某人。

答案 8 :(得分:4)

如果你想要一个单独的.js文件来更好地组织路由,只需在app.js文件中创建一个指向文件系统中位置的变量:

var wf = require(./routes/wf);

然后,

app.get('/wf', wf.foo );

其中.foowf.js文件中声明的某个函数。例如

// wf.js file 
exports.foo = function(req,res){

          console.log(` request object is ${req}, response object is ${res} `);

}

答案 9 :(得分:1)

这可能是有史以来最棒的堆栈溢出问题/答案。我 Sam's / Brad的解决方案。我以为我会使用我实现的异步版本:

function loadRoutes(folder){
    if (!folder){
        folder = __dirname + '/routes/';
    }

    fs.readdir(folder, function(err, files){
        var l = files.length;
        for (var i = 0; i < l; i++){
            var file = files[i];
            fs.stat(file, function(err, stat){
                if (stat && stat.isDirectory()){
                    loadRoutes(folder + '/' + file + '/');
                } else {
                    var dot = file.lastIndexOf('.');
                    if (file.substr(dot + 1) === 'js'){
                        var name = file.substr(0, dot);

                        // I'm also passing argv here (from optimist)
                        // so that I can easily enable debugging for all
                        // routes.
                        require(folder + name)(app, argv);
                    }
                }
            });
        }
    });
}

我的目录结构有点不同。我通常通过require - './routes'在app.js中定义路径(在项目的根目录中)。因此,我正在跳过对index.js的检查,因为我想要也包括那个。

编辑: 你也可以将它放在一个函数中并递归调用它(我编辑了这个例子以显示这个),如果你想将你的路由嵌套在任意深度的文件夹中。

答案 10 :(得分:1)

我写了一个小插件来做这个!厌倦了一遍又一遍地编写相同的代码。

https://www.npmjs.com/package/js-file-req

希望它有所帮助。

答案 11 :(得分:0)

如果您将 express-4.x TypeScript 和ES6一起使用,这将是一个最佳模板;

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

非常清楚,而不是使用varmodule.exports

答案 12 :(得分:0)

您可以将所有路由功能放在其他文件(模块)中,并将其链接到主服务器文件。 在主express文件中,添加一个将模块链接到服务器的函数:

   function link_routes(app, route_collection){
       route_collection['get'].forEach(route => app.get(route.path, route.func));
       route_collection['post'].forEach(route => app.post(route.path, route.func));
       route_collection['delete'].forEach(route => app.delete(route.path, route.func));
       route_collection['put'].forEach(route => app.put(route.path, route.func));
   }

并为每个路由模型调用该函数:

link_routes(app, require('./login.js'))

在模块文件(例如,login.js文件)中,照常定义功能:

const login_screen = (req, res) => {
    res.sendFile(`${__dirname}/pages/login.html`);
};

const forgot_password = (req, res) => {
    console.log('we will reset the password here')
}

并使用request方法作为键将其导出,其值是一个对象数组,每个对象都有路径和功能键。

module.exports = {
   get: [{path:'/',func:login_screen}, {...} ],
   post: [{path:'/login:forgotPassword', func:forgot_password}]
};   

答案 13 :(得分:0)

index.js

const express = require("express");
const app = express();
const http = require('http');
const server = http.createServer(app).listen(3000);
const router = (global.router = (express.Router()));
app.use('/books', require('./routes/books'))
app.use('/users', require('./routes/users'))
app.use(router);

路由/users.js

const router = global.router
router.get('/', (req, res) => {
    res.jsonp({name: 'John Smith'})
}

module.exports = router

路线/books.js

const router = global.router
router.get('/', (req, res) => {
    res.jsonp({name: 'Dreams from My Father by Barack Obama'})
}

module.exports = router

如果你的服务器在本地运行 (http://localhost:3000) 那么

// Users
curl --request GET 'localhost:3000/users' => {name: 'John Smith'}

// Books
curl --request GET 'localhost:3000/users' => {name: 'Dreams from My Father by Barack Obama'}