[聚合文章] Nodejs:摆脱黑工坊发展出一款基础企业级框架

Nodejs:摆脱黑工坊发展出一款基础企业级框架
说着也是奇怪,nodejs发展那么多年了,基础框架依旧横行霸道,当你提到nodejs的时候肯定会有人说koa/express 云云,然后随便搜索一下教程,就是教你如何制作一款博客。
诚然,nodejs强大的能力可不是给大家单单用来制作一款博客的...
无论是express还是koa,都是属于基础框架。我认为基础框架和企业级框架有两点是不同的:
- 基础框架没有任何的限制和约束,开发者可以以任意风格书写自己的代码,业务逻辑
- 企业级框架特别繁琐
没有任何约束的框架在一开始的时候会非常的爽快,开发几个demo,手到擒来,但是一旦代码真正上去的时候(而且一定会),你就会发现,大量重复的操作,重复的逻辑,以及无法做单元测试。导致项目的复杂度越来越高,代码越来越丑,非常的难以维护。
为框架添加一些约束,就会增加其难用程度,学习成本变高,很多新手就会觉得:哎哟,我这样写逻辑也是可以的嘛,为什么要搞那么复杂?
编程就是这样,如果你真正接触过一个从零到有的项目,你就会知道,很多东西你刚开始逃避的,到最后你就得全部加回来,一个不少!话虽如此,跑题有甚,今天我们就来看看,如何将基础框架koa变成一款低端的企业级框架。
koa基础
koa真的很容易,代码超级简单,稍微有些基础的同学,半天就能读懂其源码和用法:Koa 框架教程 - 阮一峰的网络日志,在这里我就不多说基础了。
如下几个步骤,就能让你在你的目录下搭建一个koa2的项目,极其简单
npm init //一路回车npm install --save koanpm install --save koa-router//在目录下新建一个app.js文件touch app.js
//app.jsconst koa = require('koa');const router = require('koa-router');const app = new koa();const Router = new router();Router.get('/', (ctx, next) => { ctx.body = 'hello';})app.use(Router.routes());app.listen(3000, '127.0.0.1', () => { console.log('服务器启动');})
访问http://127.0.0.1:3000/
就能看到我们的hello.
是的,简简单单的几步,我们就能够搭建起一个非常简单的koa服务器了。
koa进阶
诚然,不幸的事情很快就发生了。我们的网站,不可能只有一个路由,而是一大堆路由,那么代码就会变成
//app.jsRouter.get('/', (ctx, next) => { ctx.body = 'hello';})Router.post('/create', (ctx, next) => { ctx.body = 'hello';})Router.post('/post', (ctx, next) => { ctx.body = 'hello';})Router.patch('/patch', (ctx, next) => { ctx.body = 'hello';})...
一大堆的router 列表,一个成熟的大网站,势必有几千几万个路由组成,都写在一个文件中是不可能的,这样会导致程序无法维护。我们第一个要做就是路由拆分
路由拆分1
最简单的路由拆分,也是github里面大量demo代码的做法,就是定义一个Router文件夹,把所有router代码拆分到各个router文件中去,导出,然后再app.js
进行引入。
第一步
在router文件中只做路由path和HTTP方法的导出:
//user.jsconst mapRouter = require('../routerLoader').mapRouter;const getUser = async (ctx, next) => { ctx.body = 'getUser';}const getUserInfo = async (ctx, next) => { ctx.body = 'getUserInfo';}/** * 注意,我们规定HTTP方法放在前面,path放在后面,中间用空格隔开 */module.exports = { 'get /': getUser, 'get /getUserInfo': getUserInfo}
第二步
我们先在app.js同级目录下添加一个routerLoader.js,然后添加以下的方法
//routerLoader.jsconst router = require('koa-router');const Router = new router();const User = require('./router/user');//倒入模块/** * 添加router */const addRouters = (router) => { Object.keys(router).forEach((key) => { const route = key.split(' '); console.log(`正在映射地址:${route[1]}--->HTTP Method:${route[0].toLocaleUpperCase()}--->路由方法:${router[key].name}`) Router[route[0]](route[1], router[key]) })}/** * 返回router中间件 */const setRouters = () => { addRouters(User); return Router.routes()}module.exports = setRouters;
第三步
修改app.js
//app.jsconst koa = require('koa');const setRouters = require('./routerLoader');//引入router中间件const app = new koa();app.use(setRouters());//引入router中间件app.listen(3000, '127.0.0.1', () => { console.log('服务器启动');})
到这里,我们完成了简单的路由拆分,由此我们引入了第一个规范:
- 所有路由不得随便乱写,必须写在router文件夹中
- 导出router方法的时候,必须用http+空格+路径的方式进行导出
路由拆分2
上述的方法很好,将一大堆的路由,都拆成了小路由,并且每一个文件控制一个路由模块,每一个模块又有了自己的功能,非常的爽!我们维护项目的力度再次变得可控起来。
好景不长,当我们增加到100个路由模块的时候,我们就想哭了,routerLoader.js文件就会变成..
const User = require('./router/user');//倒入模块const model2 = require('./router/model2');//倒入模块.....//省略一大堆模块const model100 = require('./router/model100');//倒入模块/** * 返回router中间件 */const setRouters = () => { addRouters(User); addRouters(model2); ...//省略一大堆模块 addRouters(model100); return Router.routes()}module.exports = setRouters;
这个routerLoader.js又会变成非常长的一个文件,这显然不符合我们的要求,而且,我们每添加一个路由模块,就要跑到routerLoader.js中去添加两行代码,不仅容易犯错,还很烦人。
我们是否可以自动扫描router目录下的文件,让其自动帮我们加载呢?答案是:肯定的。
........./** * 扫描目录 */const Scan = () => { const url = './router'; const dir = fs.readdirSync(url)//同步方法无所谓的,因为是在服务器跑起来之前就完成映射,不会有任何性能影响 dir.forEach((filename) => { const routerModel = require(url + '/' + filename); addRouters(routerModel); })
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。