使用express.js动态加载路由

7
我正在使用express.js作为web服务器,希望有一个简单的方法将所有的"app.get"和"app.post"函数分离到不同的文件中。例如,如果我想为登录页面指定get和post函数,我希望在routes文件夹中有一个login.js文件,当我运行node app.js时,它可以动态加载(自动添加所有文件而无需指定每个文件)。
我尝试了这个this solution!,但它对我不起作用。

1
链接的解决方案看起来应该可以工作;你能把你的实现粘贴一下吗? - furydevoid
4个回答

18

app.js

var express=require("express");
var app=express();
var fs=require("fs");
var routePath="./routers/"; //add one folder then put your route files there my router folder name is routers
fs.readdirSync(routePath).forEach(function(file) {
    var route=routePath+file;
    require(route)(app);
});
app.listen(9123);
我已将以下两个路由器放入该文件夹中:

route1.js

module.exports=function(app){
  app.get('/',function(req,res){
     res.send('/ called successfully...');
  });
}

route2.js

module.exports=function(app){
app.get('/upload',function(req,res){
  res.send('/upload called successfully...');
});
}

如果@anonymousfox仍然遇到任何困难,请告诉我。 - sachin
感谢@sachin的帮助。我设法让某些东西工作了,但它与您提供的解决方案有点不同。当我尝试将相对路径“./routers/”传递给fs.readdirSync时,我收到一个错误,说该目录不存在。如果我做同样的事情,但使用__dirname +“/routes”,它就能够工作。我遇到的第二个问题是mac osx在我的路由文件夹中创建了.DS_Store文件。当添加路由时,此文件被解析并最终抛出错误。为了解决这个问题,我添加了一个检查来查看是否有.js扩展名。 - anonymousfox

1

Typescript

routes/testroute.ts

import { Router } from 'express';

const router = Router();
router.get('/test',() => {
    // Do your stuffs Here
});



export = router;

index.ts

let app = express() 

const routePath = path.join(__dirname, 'routes');

fs.readdirSync(routePath).forEach(async (filename) => {
    let route = path.join(routePath, filename);
    try {
        const item = await import(route);
        app.use('/api', item.default);
    } catch (error) {
        console.log(error.message);
    }
});

app.listen()


0
我最终采用了递归方法来保持代码的可读性和异步性:
// routes     
processRoutePath(__dirname + "/routes");

function processRoutePath(route_path) {
    fs.readdirSync(route_path).forEach(function(file) {
        var filepath = route_path + '/' + file;
        fs.stat(filepath, function(err,stat) {
            if (stat.isDirectory()) {
                processRoutePath(filepath);
            } else {
                console.info('Loading route: ' + filepath);
                require(filepath)(app, passport);
            }
        });
    });
}

这可以通过检查正确的文件扩展名等来使其更加健壮,但我保持我的路由文件夹干净,不想增加复杂性


-2

采用这种方法,就无需手动编写路由。只需设置一个类似于URL路径的目录结构即可。示例路由位于/routes/user/table/table.get.js,API路由将是/user/table

import app from './app'
import fs from 'fs-readdir-recursive'
import each from 'lodash/each'
import nth from 'lodash/nth'
import join from 'lodash/join'
import initial from 'lodash/initial'

const routes = fs(`${__dirname}/routes`)
each(routes, route => {
  let paths = route.split('/')

  // An entity has several HTTP verbs
  let entity = `/api/${join(initial(paths), '/')}`
  // The action contains a HTTP verb
  let action = nth(paths, -1)

  // Remove the last element to correctly apply action
  paths.pop()
  action = `./routes/${join(paths, '/')}/${action.slice(0, -3)}`

  app.use(entity, require(action))
})

示例路由:

import { Router } from 'express'
import Table from '@models/table.model'

const routes = Router()

routes.get('/', (req, res, next) => {   
  Table
    .find({user: userIdentifier})
    .select('-user')
    .lean()
    .then(table => res.json(table))
    .catch(error => next(error))
})

module.exports = routes

2
哈哈,Lodash 只是用来加载路由的。他在应用程序中不会在任何其他地方使用它,所以我认为这是整个库的浪费。 - user6516765
正如@user6516765所说,仅仅为了做一些在普通JavaScript中可以轻松复制的事情而浪费内存是不值得的。 - Epic Speedy
lodash是一种浪费大量内存和时间的工具。在这里,使用原生JavaScript函数,如.forEach,会更加合适。 - Austin McCalley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接