Midway(中途岛)品牌是淘宝技术部(前淘宝 UED)前端部门研发的一款基于 Node.js 的全栈开发解决方案。它将搭配团队的其余产品,Pandora 和 Sandbox,将 Node.js 的开发体验朝着全新的场景发展,让用户在开发过程当中享受到史无前例的愉悦感。html
Midway 基于 阿里 Egg.js 框架二开,将 IoC 引入到框架中,借鉴 Nest.js,引入丰富的装饰器方法,提高开发中的用户体验。前端
midway 的一些特性以下。git
首先想说说 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,能够用来减低计算机代码之间的耦合度。其中最多见的方式叫作依赖注入(Dependency Injection,简称 DI),还有一种方式叫“依赖查找”(Dependency Lookup)。github
经过控制反转,对象在被建立的时候,由一个调控系统内全部对象的外界实体将其所依赖的对象的引用传递给它。也能够说,依赖被注入到对象中。通俗地来讲,有点像上京东或者淘宝购买商品,你只须要在搜索框中输入你要购买的商品,能够选择它的分类、品牌、价格等参数,而后软件就会给你提供你心仪的商品,你只须要下单、购买、等着收货便可。简单明了,若是软件给你推荐的结果,你并不满意,咱们就会抛出异常,整个过程无需你本身控制,而是电商平台相似容器的结构来控制。web
全部的商品都会在电商平台中注册,你只须要告诉 Ioc 你是什么东西,你要买什么东西,而后 Ioc 就会在系统运行到你须要的时候,将你要的东西传递给你。同时也将你售卖的东西,交付给其余须要的地方,全部商品的建立、配送、销毁,所有由 IoC 控制。这就是控制反转。typescript
Midway 框架采用 injection 这个 Npm 包作 IoC 控制,这个包自己也是淘宝中途岛团队自主开发的,实现了依赖注入。编程
Midway 是基于阿里开源的另外一款 Node 框架 Egg.js 为基础开发的。json
Egg.js 号称为企业级框架和应用而生,Egg 采用“约定优于配置”,规划了一套统一的约定,进行开发,我司现有产品采用 Egg.js 进行开发迭代,Egg.js 约束了一套目录规范和开发规范和插件规范,减小由于人的差别致使项目规范混乱,Egg.js 有很高的可扩展性,使用 Egg.js 提供的 loader 机制可让框架根据开发者本身的规划,定义默认配置,亦可覆盖 Egg.js 的默认配置。bash
由于 Egg.js 的这种高度可扩展性,给开发者提供了基于 Egg.js 封装上层框架的能力,而且 Egg.js 插件高度可扩展,而且现有生态较为完备,而且兼容 koa 的插件,生态环境很是优异。Egg.js 经过 Node 官方的 Cluster 模块,实现多进程模型,充分利用多核心 CPU 性能。另外 Egg.js 在淘宝双十一,和阿里绝大部分的 Web 系统中的表现,充分的说明了,Egg.js 优异的稳定性。数据结构
我的以为 Midway 选择 Egg.js 的缘由有如下几点:
TypeScript是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,并且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。安德斯·海尔斯伯格,C# 的首席架构师,已工做于 TypeScript 的开发。
由于 Midway 使用 Typescript 开发,因此支持装饰器方法。在 Java 开发中,装饰器模式很是常见,经过装饰器方法能够向一个现有的对象添加新的功能,而且不会改变对象的结构,装饰器和被装饰的对象能够独立,不会相互耦合。
举例说明,例如 Midway 提供了路由装饰器,能够直接经过装饰器方法声明路由。代码示例以下(代码来源于官方示例):
import { provide, controller, inject, get } from 'midway';
@provide()
@controller('/user')
export class UserController {
@inject('userService')
service: IUserService;
@get('/:id')
async getUser(ctx): Promise<void> {
const id: number = ctx.params.id;
const user: IUserResult = await this.service.getUser({id});
ctx.body = {success: true, message: 'OK', data: user};
}
}
复制代码
如上代码使用 @controller 声明这个类为控制器类,同时经过标注请求,声明了请求的方法,除了 @get 之外,Midway 还基于 koa-router 封装了 @post、@del、 @put、@patch、@options、@head、 @all,其余装饰器方法的示例能够经过 Midway 官方文档查看,本文只作简要介绍,后续本人可能会写一系列的 Midway 实战教程,敬请期待。
我司基于 Egg.js 开发了一套通用 OA 产品(持续迭代中),在实际开发过程当中,体验仍是不错,可是也有一些开发体验很差的地方,由于使用 JavaScript 因此自动补齐,智能提示基本上是没法使用,虽然官方或我的提供了插件可是使用起来,老是有些不尽如人意,另外咱们的路由声明、多文件 多文件夹,维护起来很麻烦:好比说我要写一个新的接口,我须要先去 router 文件夹里面建立一份路由文件,而后在 /app/router.js 文件里引用这个文件。
而后再去控制器里面建立文件,编写方法,好几个文件,来回切换。因此我以为使用装饰器方法声明路由仍是很方便的。最开始尝试过使用第三方插件实现装饰器注册路由,可是体验不是很好,后续就没有继续使用了。
另外就是 JavaScript 语言自己的痛点,代码规范、接口声明、类型效验问题、多人同时开发,每一个人的开发习惯都不相同,因此长期迭代维护的项目可能会由于每一个人的习惯不一样,可维护性逐渐下降,咱们如今的私有化部署项目,不少低级 Bug 都是由于类型不对,数据结构不对等之类的引发。
若是真的要维护这个项目几年,JavaScript 灵活度很高,因此项目前期可使用 JavaScript 构建,以换取开发效率高,可是我以为若是不进行规范约束,后期几乎不可维护。从企业产品角度出发,由于 Typescript 面向对象编程语言的结构,保持了代码的整洁度,代码规范的一致性,所以我我的以为,在企业项目中使用 Typescript 更加适合。若是只是小型项目或我的项目,JavaScript 更适合灵活开发,开发效率更高。不过一切技术的选择都要从实际场景出发。任何不从实际场景出发的技术选型都是耍流氓。
根据以前讲的 Midway 的特性,我简单总结了一下,使用 Midway 带来的好处,有如下几点。
将项目从一个框架,迁移到另外一个框架,并非一件简单的事,不过把 Egg 项目重构为 Midway 还算是没有什么特别的困难,首先由于 Midway 基于 Egg.js 因此以前项目中使用的 egg 插件或 koa 插件,能够无需修改,或者少许修改,便可在 Midway 中使用,另外由于 Midway 的不少方法与 Egg.js 保持一致,因此大部分你在 Egg.js 中使用的方法,亦可在 Midway 中继续使用,目录结构这部分,与 Egg.js 大体相同,不过 Midway 在其基础上,从新对项目结构分层,将项目分为 Web 层和业务逻辑层:
├── README.md
├── README.zh-CN.md
├── dist ---- 编译后目录
├── logs ---- 本地日志目录
│ └── midway6-test ---- 日志应用名开头
│ ├── common-error.log ---- 错误日志
│ ├── midway-agent.log ---- agent 输出的日志
│ ├── midway-core.log ---- 框架输出的日志
│ ├── midway-web.log ---- koa 输出的日志
│ └── midway6-test-web.log
├── package.json
├── src ---- 源码目录
│ ├── app ---- web 层目录
│ │ ├── controller ---- web 层 controller 目录
│ │ │ ├── home.ts
│ │ │ └── user.ts
│ │ ├── middleware (可选) ---- web 层中间件目录
│ │ │ └── trace.ts
│ │ ├── public (可选) ---- web 层静态文件目录,能够配置
│ │ ├── view (可选)
│ │ | └── home.tpl ---- web 层模板
│ ├── config
│ │ ├── config.default.ts
│ │ ├── config.local.ts
│ │ ├── config.prod.ts
│ │ ├── config.unittest.ts
│ │ └── plugin.ts
│ └── lib ---- 业务逻辑层目录,自由定义
│ │ └── service ---- 业务逻辑层,自由定义
│ │ └── user.ts
│ ├── interface.ts ---- 接口定义文件,自由定义
│ ├── app.ts ---- 应用扩展文件,可选
│ └── agent.ts ---- agent 扩展文件,可选
├── test
│ └── app
│ └── controller
│ └── home.test.ts
├── tsconfig.json
└── tslint.json
复制代码
另外就是在使用 Typescript 后,开发者须要编写接口定义,和声明文件,不过我相信,你们学习一些 Typescript 知识之后,这些都不是问题。另外,是否须要重构项目也要从实际状况出发,应先实际调研,当前项目是否规范混乱,难以维护,另外就是重构的意义是否大于重构的成本。若是你的项目尚未开始实施,或刚刚开始实施,若是你想使用 Typescript 做为产品语言,我以为 Midway 能够做为你的框架选型之一,另外可能有些人会说,若是我都要写 Typescript 了,为何我不用 Nest.js 呢?我以为框架选型仍是要从实际出发,你就直接使用,而是要看,这个框架的性能,稳定性,维护团队,将来规划等等方面出发,我选择 Egg.js,选择 Midway 首先是由于它的维护团队是阿里巴巴,性能稳定,另外就是有 IoC 机制,优化了开发体验。