Node.js 将版本控制的API路由动态加载到express.Router中

Node.js 将版本控制的API路由动态加载到express.Router中,node.js,express,Node.js,Express,我的路线位于/src/routes/api/v0/,下面是一个示例路线: //src/routes/api/v0/dogs.js import { Router } from 'express' const router = Router() router.get('/dogs', (req, res) => { res.json({ message: 'List of all dogs' }) }) router.post('/dogs', (req, res) => {

我的路线位于
/src/routes/api/v0/
,下面是一个示例路线:

//src/routes/api/v0/dogs.js
import { Router } from 'express'

const router = Router()

router.get('/dogs', (req, res) => {
  res.json({ message: 'List of all dogs' })
})

router.post('/dogs', (req, res) => {
  res.json({ message: `Created a dog: ${req.body}` })
})

router.put('/dogs/:id', (req, res) => {
  const { id } = req.params
  res.json({ message: `Dog ${id} mutated into ${req.body}` })
})

router.delete('/dogs/:id', (req, res) => {
  const { id } = req.params
  res.json({ message: `Dog ${id} is gone` })
})

export { router as dogs }
假设还有另一个类似的路由文件,
cats.js
,为了简洁起见,这里省略了它。我正在从
index.js
导出这两个模块:

//src/routes/api/v0/index.js
export * from './cats'
export * from './dogs'
//src/server.js
import v0 from './routes/api'
...
app.use('/api', v0)
...
然后,我通过中介加载它们,如下所示:

//src/routes/api/index.js
import { Router } from 'express'
import { cats, dogs } from './v0'
const v0 = Router()

v0.use('/v0', cats)
v0.use('/v0', dogs)

export { v0 }
最后将它们加载到
server.js

//src/routes/api/v0/index.js
export * from './cats'
export * from './dogs'
//src/server.js
import v0 from './routes/api'
...
app.use('/api', v0)
...
有没有一种方法可以将单个路由模块加载到
express.Router
(my
src/routes/api/index.js中的
v0
)中,而不必将每个模块都交给我?比如:

//src/routes/api/index.js
import { Router } from 'express'
import * as apiV0 from './v0'

const v0 = Router()

v0.use('/v0', magically feed it apiV0)

您可以使用
fs
模块读取文件并导出其函数。你可以看看我的代码

我使用的
\uuu dirname
就是模型dirname。然后,你可以使用这个神奇的一行要求开始你的应用程序

import initFunction from 'src/routes'
import { Router } from 'express'

initFunction(Router()) // dont forget your express instance

initFunction

一种选择是导出一组路由器,而不是为每个路由器命名。然后,您可以迭代该数组,以一种通用的方式添加它们。因此,不要像这里那样按名称导入每个文件:

//src/routes/api/index.js
import { Router } from 'express'
import { cats, dogs } from './v0'
const v0 = Router()

v0.use('/v0', cats)
v0.use('/v0', dogs)

export { v0 }
您可以导出然后导入路由器阵列,然后迭代该阵列:

//src/routes/api/index.js
import { Router } from 'express'
import { allRouters } from './v0'
const v0 = Router()

for (const router of allRouters) {
    v0.use('/v0', router)
}

export { v0 }
事实上,您可以像现在一样导出单独的命名路由器,如果需要,还可以导出路由器阵列,然后导入代码可以自由使用单独的命名路由器或整个阵列


在OP编辑问题后添加此答案

您对显示以下内容的问题的编辑:

//src/routes/api/v0/index.js
export * from './cats'
export * from './dogs'
为所有这些路由的任何类型的自动收集创建一些复杂情况。ES6
导入
导出
无法动态确定。实际上,ES6要求可以对进出口进行静态分析。因此,不能在代码循环中导入或导出。以下是对该主题的讨论:

如果您使用的是
require()
,则可以构建一个模块,该模块可以通过查看文件系统或通过读取指定所有路由文件的配置文件来读取配置文件并加载所有路由文件。但是,您可以使用ES6
import
export
来实现这一点。因此,据我所知,如果要使用
导入
导出
,则必须手动指定导入。通过在导出路由集合之前将它们放入数组中,您至少只需要手动声明一次而不是两次(这是对当前代码的改进)

这里是手动导入它们,然后在更容易处理的数组中导出它们:

//src/routes/api/v0/index.js
import {dogs} from './dogs'
import {cats} from './cats'

export const allRouters = [dogs, cats];
然后,您可以安装它们:

//src/routes/api/index.js
import { Router } from 'express'
import { allRouters } from './v0'
const v0 = Router()

for (const router of allRouters) {
    v0.use('/v0', router)
}

export { v0 }

我喜欢这个!请详细说明如何将这些路由导出为数组?假设我有dogs.js和cats.js,它们都定义了各自的路径。如何将它们作为路由的组合数组放入api/index.js中?@boojum-您显示了从“/v0”
导入{cats,dogs},因此您似乎已经将
cats
dogs
路由器放在同一个文件中并分别导出。您只需将其更改为将它们导出到名为
allRouters
的数组中即可。如果这不是你所拥有的,那么我对你现在拥有的以及你目前正在做的事情感到困惑,你想改进它。嘿,很抱歉给你带来困惑!我更新了我的问题,希望它现在更清晰。@boojum-看看我在回答的末尾添加了什么。感谢您花时间解释导入/导出的案例,它解释了为什么我通过各种尝试得到了
未定义的
。由于我想坚持ES6语法,我很乐意接受您的回答。但您提供的示例并不适用于我:您的解决方案,使用
require()
readdir()
,将起作用,并且是在SO和其他地方出现的第一件事。虽然-由于个人喜好-我对ES6
导入
/
导出
感兴趣。基于这个原因,我接受你的工作方案是不公平的。不管怎样,谢谢你的时间!