淺談阿里 Node 框架 Midway 在企業產品中的應用實踐

什麼是 Midway

Midway(中途島)品牌是淘寶技術部(前淘寶 UED)前端部門研發的一款基於 Node.js 的全棧開發解決方案。它將搭配團隊的其餘產品,Pandora 和 Sandbox,將 Node.js 的開發體驗朝着全新的場景發展,讓用戶在開發過程當中享受到史無前例的愉悅感。html

Midway 基於 阿里 Egg.js 框架二開,將 IoC 引入到框架中,借鑑 Nest.js,引入豐富的裝飾器方法,提高開發中的用戶體驗。前端

midway 的一些特性以下。git

依賴注入( IoC )

首先想說說 控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,能夠用來減低計算機代碼之間的耦合度。其中最多見的方式叫作依賴注入(Dependency Injection,簡稱 DI),還有一種方式叫「依賴查找」(Dependency Lookup)。github

經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體將其所依賴的對象的引用傳遞給它。也能夠說,依賴被注入到對象中。通俗地來講,有點像上京東或者淘寶購買商品,你只須要在搜索框中輸入你要購買的商品,能夠選擇它的分類、品牌、價格等參數,而後軟件就會給你提供你心儀的商品,你只須要下單、購買、等着收貨便可。簡單明瞭,若是軟件給你推薦的結果,你並不滿意,咱們就會拋出異常,整個過程無需你本身控制,而是電商平臺相似容器的結構來控制。web

全部的商品都會在電商平臺中註冊,你只須要告訴 Ioc 你是什麼東西,你要買什麼東西,而後 Ioc 就會在系統運行到你須要的時候,將你要的東西傳遞給你。同時也將你售賣的東西,交付給其餘須要的地方,全部商品的建立、配送、銷燬,所有由 IoC 控制。這就是控制反轉。typescript

在這裏插入圖片描述

Midway 框架採用 injection 這個 Npm 包作 IoC 控制,這個包自己也是淘寶中途島團隊自主開發的,實現了依賴注入。編程

基於 Egg.js

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 的緣由有如下幾點:

  1. 底層基於 koa,提過封裝上層框架能力;
  2. 雙十一的併發量均可以支撐住(不要給我說,大家平臺的流量可以比淘寶天貓雙十一還要高);
  3. 兼容 koa 插件,Egg.js 插件也有幾百個,一些使用率很高的框架由官方維護,例如,egg-mongoose、egg-sequelize 等等;
  4. 阿里維護的項目,而且阿里自身也在深度使用;
  5. 問題回答的效率,首先是國內的框架,你能夠用中文提交 issue,另外就是回覆效率很高(本人提過幾個 issue,基本上一小時內就回復了,不知道是否是我問題簡單的緣由)。

採用 Typescript

TypeScript是一種由微軟開發的自由和開源的編程語言。它是 JavaScript 的一個超集,並且本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程。安德斯·海爾斯伯格,C# 的首席架構師,已工做於 TypeScript 的開發。

  • TypeScript 擴展了 JavaScript 的語法,因此任何現有的JavaScript 程序能夠不加改變的在 TypeScript 下工做。
  • TypeScript 是爲大型應用之開發而設計,而編譯時它產生 JavaScript 以確保兼容性。
  • TypeScript 支持爲已存在的 JavaScript 庫添加類型信息的頭文件,擴展了它對於流行的庫如 jQuery、MongoDB、Node.js 和 D3.js 的好處。而且咱們常用的宇宙第一編輯器 Visual studio code 也是 Typescript 開發的。
  • Typescript 可使用 Javascript 中的全部代碼和概念,Typescript 是爲了 JavaScript 開發更加容易而誕生的,Typescript 只從語義核心方面對 JavaScript 原有模型進行擴展,因此 JavaScript 能夠無需修改,或少許修改便可和 Typescript 同時工做,也可使用編譯器將 Typescript 轉換爲 JavaScript 代碼。
  • Typescript 經過類型註解,提供編譯時的靜態檢查,而且爲函數提供了缺省參數,而且引入了模塊的概念,能夠把聲明、數據、函數和類封裝在模塊中。使用 Typescript 相較於 JavaScript 有如下顯著優點:
  1. 靜態檢查
  2. 大型項目的規範,使用 Typescript 更容易重構
  3. 協做能力
  4. 生產力,乾淨的 ES6 代碼,自動完成和動態輸入提升了開發者的工做效率

提供多種裝飾器

由於 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 的特性,我簡單總結了一下,使用 Midway 帶來的好處,有如下幾點。

  1. 使用 Midway 學習成本低,若是你以前使用過阿里的 Egg.js 框架,基本上不須要怎麼學習,便可用於實際工做中
  2. 各類裝飾器方法提高開發效率
  3. 使用 Typescript 使用
  4. 使用 Ioc,優化項目依賴管理
  5. 底層基於 Egg.js 兼容 Egg.js 的全部生態
  6. 採用 Typescript,強類型,面向接口編程
  7. 提供裝飾器方法,簡化開發

如何從 Egg 平穩遷移到 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 機制,優化了開發體驗。

相關文章
相關標籤/搜索