内容简介:去年年初对 Node.js 比较感兴趣,也用了很多 Node.js 的框架,但是开发体验不是特别好,我之前也是后端转前端,然后再接触 Node.js ,所以用过挺多的服务端框架,相对js而言,设计一款服务端框架并不容易,本人也不太愿意使用 typescript (为什么不用java,请勿吐槽)编写并且基于ES6 对入门的小伙伴会更友好一些,然后自己动手开发了一个Node.js 的Web 框架,快过年了才有时间写文章(手动狗头),在这里给大家分享一下开发经历。对于框架底层,想过自己开发一套(成本太高,并且考虑
去年年初对 Node.js 比较感兴趣,也用了很多 Node.js 的框架,但是开发体验不是特别好,我之前也是后端转前端,然后再接触 Node.js ,所以用过挺多的服务端框架,相对js而言,设计一款服务端框架并不容易,本人也不太愿意使用 typescript (为什么不用java,请勿吐槽)编写并且基于ES6 对入门的小伙伴会更友好一些,然后自己动手开发了一个Node.js 的Web 框架,快过年了才有时间写文章(手动狗头),在这里给大家分享一下开发经历。
注:目录只是为了好看,想到什么写什么,没有文笔可言,小白文。
选型
对于框架底层,想过自己开发一套(成本太高,并且考虑到生态问题)被我否决了,然后比较了 Koa2 与 Express 最终选择Koa2作为默认底层(最后由于框架的架构设计,koa2服务或者express都可以作为底层库 ),不过最后还是选择了 koa2 默认集成。
既然选择了 koa2 那自然也是兼容 koa2 的生态圈
架构设计
刚开始开发的时候其实是顺着koa的路子走的, 以koa作为底层,对koa的ctx进行扩展,后来觉得这样子封装一个koa的全家桶貌似没什么意义(晚上一大堆,造轮子没什么意义,和别的框架有啥区别,请原谅我这老土的想法 ),然后开始思考 :做这个框架的初衷和意义。
作为一个后端过来的,自然就想到了用IOC容器作为底层更优雅,但是js并没有类型约束,接口等特性,也看过很多 typescript的实现(和其他后端框架并无明显区别,不是我吐槽,其他语言的更完善更安全性能更好),我下定决心要写一个js(ES6)版的出来(学习成本低,更好入门 就是这么自以为是),然后就这样开启了我的 Node.js 之旅。
写偏了。。下面介绍一下这个框架的架构:
以容器作为底层,应用类集成容器基类并绑定在容器中,是应用程序对象也是容器的保姆。
其他所有的服务(包括 koa 、router、logger、validate、request、response等等)都是以提供者的形式在应用程序中注册(实际绑定到了容器)。
容器开发
前期没想那么多,开发容器也很顺利,在设计依赖注入模式的时候(由于没有接口),想躲过很多方案,最后决定使用装饰器(真香),不是ts,使用ECMA草案中装饰器(使用 babel
转码),最后 1.0
定稿以后,会成为可选方案,装饰器可以增加开发体验,但不是必须的,并且强烈推荐的模式进行设计。
例如我们开放一个端点(路由),装饰器例子,不是注入:
@Router('users') class UserController { @Get() index() { // ... } }复制代码
这种模式进行开发,上述例子开放了一个 GET /users
的访问端点
那如果进行注入呢:
class UserController { @Config() config; @Request() index(request) { this.request.param() this.config.get('app.port') } }复制代码
我们可以对属性,方法,构造函数进行注入
原理是使用装饰器标记控制器属性方法等需要注入的参数,然后调用函数的时候从容器中取出(这里碰到个坑),由于 http
服务请求的上下文在回调函数中,所以我绑定了一个回调函数到容器中,需要获取实例的时候将上下文传入函数中,生成例如 request
对象的实例。
提供者
这时候开发的框架,各种服务默认绑定在容器中,与应用类耦合,虽然是框架自带的服务,但是还是不够完美,所以借鉴了提供者的设计模式,将所有服务抽离并设计注册服务的api,在框架启动时,自动注册默认服务。
这样子,我们的所有服务与框架底层核心完全解耦,保证了底层核心的精简,并具有强大的可伸缩性。
模块化
既然是一个web框架,使用的时候肯定会承载不同的业务,所以我们需要使用模块化功能拆分业务,提升可维护性,比如可以设定这个模块包含了哪几个控制器(支持通配符),这个模块需要加载哪些中间件,甚至子模块功能
所以我就设计了这么一套方案,使用模块描述类来定义模块
module.exports = class ExampleModule { // 标示子模块 modules = []; // 标示需要装载的控制器 controllers = []; // 标示需要加载的中间件 middlewares = []; }复制代码
good
请求
作为web框架,肯定需要解析请求啊什么的,既然不是扩展 ctx
属性,那么我的方案就是使用 Request
类来解析 ctx
, 这样的好处就是,我可以解析 koa
的 ctx
, express
的 req
、 res
或者其他框架的上下文对象,并且这个类是注册在容器中的,如果你有其他的解析方案,当然也可以自己注册一个,然后为所欲为(没错, IOC
容器就是可以为所欲为:sunglasses:)。
响应
生产响应的时候肯定也要越方便越好,方便到你只需要在控制器中 return
就好,可以 return
各种类型,除了 koa2
中的支持的数据类型,还支持直接返回 框架的 View
(视图,即模板)实例或者 Response
(响应类)实例等等,框架都会自动判断。
class UserController { index() { return [{ id: 1 }] } }复制代码
就是这么方便,当然不仅仅这样,还有更多强大的功能。
验证器
我在使用很多框架的时候,验证请求数据不是很方便,所以也重新设计了一套方案(狗头),
当然还是使用装饰器模式
// 定义一个验证类,放在指定目录 class UserPostValidate extends Validate { @MaxLength(10) username; @Length(1, 20) password: }复制代码
然后在控制器中
class UserController extends Controller { store() { this.request.validate('UserPostValidate') } } 复制代码
狗头
写了好久,先去吃饭了,其实还有很多功能模块,例如日志服务、多进程服务、进程间通信服务、安全相关服务、 cookie
和 session
服务等等,有兴趣的可以留言继续解答,或者出第二篇,下次出点技术类的~~~:dog:
仓库地址: [ Github ]
当然,框架核心代码在 framework
这个包,目前还在开发和测试中,优化一些功能和文档,工具比较low逼,也需要完善,希望有大牛可以一起开发。
目前已经到 0.8.x
版本,已经历时半年(第一个npm包提交开始),离第一个稳定版不远了!!!!正在快车道中,希望明年尽快开放 1.0
版本服务大众。
也希望大家可以尝试下提供各种意见反馈,由于目前就一个人开发, bug
肯定不少, cli
工具方面已经很久没更新了,准备下一步完善工具,如果需要体验的(工具万一有 bug
),直接
clone
daze
仓库就可以。
然后,希望大家不要吝啬自己的 star
:dog::dog::dog::dog::dog::dog::dog::dog:给个鼓励~~~~
最后,祝大家新年快乐,新年新气象 :tada::tada::tada::tada::tada::tada::tada:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于Google MVVM框架的baseMVVM框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Genesis框架从入门到精通(7): 框架的过滤器
- 如何打造自己的POC框架-Pocsuite3-框架篇
- 如何打造自己的PoC框架-Pocsuite3-框架篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。