繁体   English   中英

将版本化 API 路由动态加载到 express.Router

[英]Dynamically load versioned API routes into express.Router

我的路线位于./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/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/server.js
import v0 from './routes/api'
...
app.use('/api', v0)
...

有没有办法将单个路由模块加载到express.Router (我的src/routes/api/index.jsv0 )而无需将每个模块都传递给我? 就像是:

//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模块读取文件并导出其功能。 你可以在这里查看我的代码。

我使用的__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 的import export无法动态确定。 ES6 有意要求对导入和导出进行静态分析。 因此,您不能在代码循环中导入或导出。 这是对该主题的讨论:

我可以使用循环来最小化 ES6 导入语句吗?

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

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

//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 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM