使用Typescript封装一款装饰器风格的Web框架
发布于 2 个月前 作者 215566435 1644 次浏览 来自 分享

前言

自上一篇文章Nodejs:摆脱黑工坊发展出一款基础企业级框架写到,如何封装Nodejs的Koa框架之后,反响还算不错,多谢大家的支持。

不过,上次的文章由于发表在知乎,由于知乎排版非常难看,所以大家都没看爽。

经过几个星期的努力,每晚抽出一些时间,终于把教程重新写好了,这次的教程稍微有些改动,那就是使用Typescript封装一款装饰器风格的Web框架

具体是怎么样的呢?看图。

起因

最近一直在尝试、研究eggjs。大量使用typescript去编写逻辑(准备写一篇文章讲述一下一些坑)

在写egg的路由的时候,体验大概是这样的:

还不错,但是有两个不爽的地方:

  • 找地址:在编写controller的时候,有时候会忘记这个controller到底是什么地址,是什么method…
  • 每次写完逻辑,会忘记把controller的方法map到router.ts中去,也就是我图中说的,要来回切换文件修改。

官方的说法是,把路由集中化管理,使得我们更好的管理这些路由地址。

但是在实际中,我个人最理想的方式就是看见controller,就能知道这个函数是对应的什么地址和method。我不知道这是不是我python写多了的原因,实际上egg强大的插件机制能够实现这一点,我打算最近搞一款egg插件,支持装饰器

然后呢,我对其进行了小小的改造,使得eggjs能够支持装饰器路由,先来看看效果:

嘿嘿,好不错对不对?

至于怎么实现的,其实也很简单,直接在router导出的函数运行期间,用装饰器自动收集所有的路由,就可以了。

刚了一波源码

直接修改router行为,这个貌似不是太优雅,所以我在思考是不是能够自定义一个egg loader或者写一个egg-xxx插件什么的。

框架的定制那自然必须要对框架底层有所了解

因此一言不合,我直接去刚了一波源码,所以就有了这个教程,这个教程也算是我看了egg部分源码以后的一些心得,为了能够融汇贯通,我自己也仿照着写了一个,造了一波轮子。

但是和之前我造的轮子不同,这一次我记录下了整个造轮子的过程。写成了教程,分享给大家啦。

教程特色

相比上次的教程,有几大改进。

  1. Typescript:使用TS写成,使用装饰器(@)进行路由。
  2. 面向对象:controller和service全部以类方式书写
  3. 如何拓展koa的实例和koa的context对象
  4. 讲解controller和service的生命周期(与egg相同)
  5. 使用高级Api去处理controller和service的实例,实现高性能
  6. 更好的观看体验,在gitbook上。
  7. 每一个步骤的代码,我都保存下来了
  8. 免费的,但是是骗星的,觉得有收获,就点个星,给点动力
  9. 持续更新中…写了80%,还差实战部分以及多进程架构与进程间通信

目录

项目地址,书就在里面了:

项目地址:使用Typescript封装一款装饰器风格的Web框

  1. 大项目的标配Typescript
  2. 自动编译TS与服务器自动重启
  3. 路由拆分
  4. 引入Controller与Service的概念
  5. Controller的实现
  6. Service的实现
  7. 优雅的处理硬编码(配置)
  8. 小总结
  9. 路由去中心化
  10. 项目目录结构的变化
  11. (非必要)插件的实现
  12. 企业框架还欠缺的东西
  13. 抽离自己的框架burn.js

每一章节的后面都有对应的代码:

为了阅读更加舒适,我已经将教程写在Gitbook之中

最后

诶,又来写了一个轮子,这款轮子是是系列教程《使用Typescript封装一款装饰器风格的Web框架》配套框架,全部使用Typescript编写完成。

在教程中,你将比较深入的了解到如何使用typescript&js的面向对象封装,将koa一步步的封装成为一款类egg.js的框架。

这样,你能就更深入的了解eggjs,根基更加牢固,本教程也算是eggjs typescript的一个前置教程吧。

喜欢的,给点星星,是你给我最大的支持,感谢。

16 回复

我使用Typescript装饰器封装了一个node工具 iwinter 项目地址,使用装饰器对路由进行封装,简洁优雅; 目前支持: 1、支持路径装饰器 Path 及 权限拦截 2、支持 GET POST PUT DELETE 方法,可使用装饰器 @GET @POST @PUT @DELETE 3、支持获取路径参数、查询参数、post请求体及原始请求对象 PathParam, QueryParam, BodyParam, ReqParam, ResParam, CtxParam, NextParam, OriginParam 4、支持在 Express 或 Koa 中使用 使用示例:

import {Controller, Path, GET, POST, PathParam, BodyParam, CtxParam, NextParam, OriginParam} from 'iwinter';
import {PostModel} from '../models/PostModel';
import {auth} from '../auth';

@Path('/api/posts', auth)
class PostController extends Controller {

    @GET
    @Path('/:name/:id', (ctx, next)=> ~~ctx.params.id > 20)	//Path(path:string, permission: Function)
    getAllPosts(@PathParam('id') id: number, @PathParam('name') name: string, @CtxParam('ctx') ctx: any){
        //ctx.response.redirect('/users');
        return [{
            id: id, name, content: 'test', author: 'test', comments: []
        }];
    }

    @POST
    @Path('/add')
    async addPost(@BodyParam('post') post: object){
    	let newPost = new Post(post);
        let result = await newPost.save();
        return result;
    }
}

export default PostController;

感觉跟你这个框架很配啊,是否考虑合作一波 : )

@yvanwangl 装饰器参数被标记为以后会有breaking change,不是很看好。而且,我的目的是为了在egg上做。

我以为你自己封装了一个框架,是时候研究一下egg了

@yvanwangl 加油。egg可以拓展的。

@yvanwangl 何必这么麻烦,已经有现成的框架了: https://docs.nestjs.com 而且原生支持 GraphQL

https://github.com/notadd/notadd/tree/next 我们写了个小项目,可以参考,也欢迎star

@这个是restful风格的

@yvanwangl restful 被 GraphQL 替代是趋势啊~ github 新版接口就是。GraphQL 就是下一代的 restful~

@新生事物要替代也是有一个阶段和周期的,话不能说太满

@yvanwangl 还是看看大厂的态度吧。GraphQL 不仅解决了restful 多次请求的问题,也解决了restful 不适合复杂业务的问题,趋势是阻挡不了的,用了就明白了。

@zuohuadong 我去年已经在用了

非常简洁的语言解释了框架由来,赞

@215566435 默默的问一句,封装框架思路怎么来的?

可以给 Egg 提一个 RFC

@hi363138911 首先,你要有自己的实践。

  1. 你在写第一个项目的时候,代码会非常的垃圾,遇到很多的问题。然后你摸不着头脑,一直写,直到代码不能维护。
  2. 直到有一天,勤奋的你看了某个教程,感受到了,很多东西都可以进行封装,然后你就尝试着去封装你原来很垃圾的代码
  3. 封装完成以后,你又发现,你看到了某个框架,比如egg的封装办法,你又用egg的模式,封装了你的代码
  4. 轻车熟路以后,你就构建出了一个类eggjs的框架,然后你去读eggjs代码的时候,特别轻松。
  5. 你已经学会了如何封装,就像天猪说的,用不用egg其实没事,重点是他的思想
  6. 用egg好了,它帮你封装好了,得心应手。

@215566435 谢谢,现在是进行 3 阶段路上

回到顶部