koa2学习笔记:如何优雅组织koa-router多路由文件代码
一个项目肯定会有很多个路由,放到一个文件肯定是不靠谱的,放到多个文件又如何优雅组织代码是个问题。
参照一些PHP框架,我期望将所有的路由放到同一个文件夹,类比一些PHP框架的控制器controllers文件夹,期望路由目录结构如下
--controllers //改目录下存放我们所有的路由文件 -----site.js //controllers目录下的文件 -----user.js //controllers目录下的文件 -----v1 //controllers目录下的文件夹 ------news.js //controllers目录下的文件夹v1中的文件
期望最终的路由完整路径 = 路由文件所在目录+路由文件名称+路由文件中定义的路由路径
如:site.js中定义了 router.get('/index',...),则真实路由为 /site/index
v1文件夹下的news.js中定义了 router.get('/list',...),则真实路由为 /v1/news/list
示例文件内容如下
site.js
var router = require('koa-router')() router.get('/index',ctx=>{ ctx.body = 'site index' }) router.get('/about',ctx=>{ ctx.body = 'site about' }) module.exports = router
user.js
var router = require('koa-router')() router.get('/list',ctx=>{ ctx.body = 'user list' }) router.get('/:id',ctx=>{ ctx.body = 'user detail' }) module.exports = router
/v1/news.js
var router = require('koa-router')() router.get('/list',ctx=>{ ctx.body = 'news list' }) router.get('/:id',ctx=>{ ctx.body = 'news detail' }) module.exports = router
接下来就是如何组织路由了,我们可以利用koa-router的嵌套路由来组织我们所有的路由
const router = require('koa-router')() router.use(路由前缀, 其他路由.routes(), 其他路由.allowedMethods());
参见 我们上一篇文章:http://shanhuxueyuan.com/news/detail/128.html
我们可以遍历controllers下的所有文件,然后将 文件所在目录及文件名 作为路由前缀,在使用require引入单个文件的路由设置,通过嵌套路由组成我们最终的路由。
在app.js中完成这个功能
app.js
const Koa = require('koa') const fs = require('fs') const path = require('path') let router = require('koa-router')() const app = new Koa() let base_path = __dirname + '/controllers' //要遍历文件所在目录,我们固定为 congtrollers文件夹 let file_path = '/' //默认文件路由为/ requireRouters(base_path,file_path) function requireRouters(base_path,file_path){ let files = fs.readdirSync(base_path + file_path); //读取目录下的文件 //遍历所有文件 files.forEach(file=>{ let file_name = base_path + file_path + file //完整文件名 if(fs.statSync(file_name).isFile() && path.extname(file_name)==='.js'){ //如果是文件且是js后缀文件 let inner_router = require(file_name) //require这个文件 let base_router = file_path + file.substring(0,file.length-3) //文件所在目录+文件名,作为路由前缀 router.use(base_router,inner_router.routes()) //通过嵌套路由方式设置真实的路由 }else{ requireRouters(base_path,`${file_path}${file}/`) //如果是文件夹,则遍历这个文件夹 } }) } app.use(router.routes()); // 添加路由中间件 app.listen(3031)
通过以上方式即组成我们最终的路由,后续我们想要添加路由,只需要在controllers中添加文件即可,不需要在别的地方进行任何修改,非常方便。
以上代码都放在app.js中感觉不太理想,因为app.js中可能要有很多逻辑,所以可以把这部分抽出来,以中间件的形式在app.js中引入,实现的结果,我们期望如下
const Koa = require('koa') const app = new Koa() let composeRouter = require('./middleware/composeRouter') app.use(composeRouter(__dirname + '/controllers').routes()); //传入路由所在文件夹即可 app.listen(3031)
composeRouter实现
const fs = require('fs') const path = require('path') const router = require('koa-router')() function requireRouters(base_path,file_path){ let files = fs.readdirSync(base_path + file_path); files.forEach(file=>{ let file_name = base_path + file_path + file if(fs.statSync(file_name).isFile() && path.extname(file_name)==='.js'){ let inner_router = require(file_name) let base_router = file_path + file.substring(0,file.length-3) router.use(base_router,inner_router.routes()) }else{ requireRouters(base_path,`${file_path}${file}/`) } }) } module.exports = (routerPath)=>{ let base_path = routerPath let file_path = '/' requireRouters(base_path,file_path) return router }
通过中间件的形式,让我们的app.js文件更简洁可读
点赞(2)