使用 express.js 动态加载路由

Posted

技术标签:

【中文标题】使用 express.js 动态加载路由【英文标题】:Dynamically load routes with express.js 【发布时间】:2013-05-22 22:57:46 【问题描述】:

我正在使用 express.js 作为网络服务器,并且想要一种简单的方法来将所有“app.get”和“app.post”函数分隔为单独的文件。例如,如果我想为登录页面指定 get 和 post 函数,我想在动态加载的 routes 文件夹中有一个 login.js 文件(将自动添加所有文件而无需指定每个文件) 当我运行 node app.js

我已经尝试过这个this solution!,但它不适合我。

【问题讨论】:

链接的解决方案看起来应该可以工作;你能粘贴你的实现吗? 【参考方案1】:

打字稿

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()

【讨论】:

【参考方案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

【讨论】:

大声笑,lodash 只是用于加载路线。他永远不会在他的应用程序的其他任何地方使用它,所以我认为这是对整个库的浪费。 正如@user6516765 所说。只做一些可以在 vanilla javascript 中轻松复制的事情是浪费内存。 lodash 是对内存和时间的巨大浪费。像 .forEach 这样的原生 JavaScript 函数在这里可以接受【参考方案3】:

我最终使用递归方法来保持代码的可读性和异步性:

// 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);
            
        );
    );

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

【讨论】:

【参考方案4】:

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 的帮助。我设法让一些工作,但它与您提供的解决方案有点不同。当我尝试将相对路由“./routers/”传递给 fs.readdirSync 时,我收到一条错误消息,指出该目录不存在。如果我做了同样的事情,但使用了 __dirname + "/routes",它就可以工作了。我遇到的第二个问题是 mac osx 在我的路由文件夹中创建 .DS_Store 文件。添加路由时,正在解析此文件并最终引发错误。为了解决这个问题,我添加了一个检查以查看是否有 .js 分机。

以上是关于使用 express.js 动态加载路由的主要内容,如果未能解决你的问题,请参考以下文章

如何在路由中动态加载组件

Angular2:无路由的延迟加载和动态加载

Nodejs动态加载路由,Nodejs遍历目录,Nodejs路由工具

如何动态加载路由计算?

vue-router+vuex实现加载动态路由和菜单

vue路由自动加载、按组件异步载入vuex以及dll优化