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

JavaScript 2018-01-21 21 阅读
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);    })
                

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。