对比 对比 Node 的 Web 框架

1,923 阅读4分钟

对比下 node 生态下的 web 框架。

主要从以下几个方面进行对比

  • github watch star fork
  • 主要实现
FrameWorkGithubDocsWatchStarFork
express地址地址1.8k54.5k9.2k
koa地址地址85331.7k3.1k
egg地址地址48417.3k1.7k
midway地址地址914.7k281
nest地址地址67940.5k4.1k

代码比较

image.png

git clone https://github.com/expressjs/express.git;
git clone https://github.com/koajs/koa.git;
git clone https://github.com/eggjs/egg.git;
git clone https://github.com/midwayjs/midway.git;
git clone https://github.com/nestjs/nest.git;

拉取 5 个项目的源代码,利用 Vscode Statistics 对代码行数进行统计。

Express

languagefilescodecommentblanktotal
JavaScript15214,0183,0333,71720,768
Markdown123,64808444,492
HTML28260053313
YAML31741931224
JSON19901100
Handlebars3710879
CSS4440347
Makefile1110314

Koa

languagefilescodecommentblanktotal
JSON211,0970211,099
JavaScript744,5331,1161,1976,846
Markdown132,19728193,018
YAML64701259

Egg

languagefilescodecommentblanktotal
Markdown10423,298307,70431,032
JavaScript47511,5141,4912,45915,464
TypeScript251,0656912812,037
JSON1406100132742
YAML102881425327
PlantUML228802290
HTML174401458
Shell Script22281040
Properties11012
XML11001

Midway

languagefilescodecommentblanktotal
Markdown525,1039696,36912,441
TypeScript2314,4534761,1236,052
JavaScript1172,6891665503,405
JSON1001,859948982,905
YAML81312430185
Shell Script785714106
TypeScript React3491656
XML2300232
HTML2180422
CSS8150924
Ignore11001

Nest

languagefilescodecommentblanktotal
JSON232353,573268136353,977
TypeScript1,28857,7154,9358,32670,976
JavaScript535,6422,3211,3669,329
Markdown452,103978783,078
YAML143624752461
graphql7330095425
HTML4600666
XML1430144
Handlebars2200626
Shell Script5169530
Ignore12002

代码统计小结

上面只是一个简单的统计,只能反应一些大致情况。

依赖情况 package.json

Express

{
	  "accepts": "~1.3.7",
    "array-flatten": "1.1.1",
    "body-parser": "1.19.0",
    "content-disposition": "0.5.3",
    "content-type": "~1.0.4",
    "cookie": "0.4.0",
    "cookie-signature": "1.0.6",
    "debug": "2.6.9",
    "depd": "~1.1.2",
    "encodeurl": "~1.0.2",
    "escape-html": "~1.0.3",
    "etag": "~1.8.1",
    "finalhandler": "~1.1.2",
    "fresh": "0.5.2",
    "merge-descriptors": "1.0.1",
    "methods": "~1.1.2",
    "on-finished": "~2.3.0",
    "parseurl": "~1.3.3",
    "path-to-regexp": "0.1.7",
    "proxy-addr": "~2.0.5",
    "qs": "6.7.0",
    "range-parser": "~1.2.1",
    "safe-buffer": "5.1.2",
    "send": "0.17.1",
    "serve-static": "1.14.1",
    "setprototypeof": "1.1.1",
    "statuses": "~1.5.0",
    "type-is": "~1.6.18",
    "utils-merge": "1.0.1",
    "vary": "~1.1.2"
}

Koa

{
    "accepts": "^1.3.5",
    "cache-content-type": "^1.0.0",
    "content-disposition": "~0.5.2",
    "content-type": "^1.0.4",
    "cookies": "~0.8.0",
    "debug": "^4.3.2",
    "delegates": "^1.0.0",
    "destroy": "^1.0.4",
    "encodeurl": "^1.0.2",
    "escape-html": "^1.0.3",
    "fresh": "~0.5.2",
    "http-assert": "^1.3.0",
    "http-errors": "^1.6.3",
    "koa-compose": "^4.1.0",
    "on-finished": "^2.3.0",
    "only": "~0.0.2",
    "parseurl": "^1.3.2",
    "statuses": "^1.5.0",
    "type-is": "^1.6.16",
    "vary": "^1.1.2"
}

Egg

{
    "@types/accepts": "^1.3.5",
    "@types/koa": "^2.0.48",
    "@types/koa-router": "^7.0.40",
    "accepts": "^1.3.5",
    "agentkeepalive": "^4.0.2",
    "cache-content-type": "^1.0.1",
    "circular-json-for-egg": "^1.0.0",
    "cluster-client": "^3.0.1",
    "debug": "^4.1.1",
    "delegates": "^1.0.0",
    "egg-cluster": "^1.23.0",
    "egg-cookies": "^2.3.0",
    "egg-core": "^4.18.0",
    "egg-development": "^2.4.2",
    "egg-i18n": "^2.0.0",
    "egg-jsonp": "^2.0.0",
    "egg-logger": "^2.3.2",
    "egg-logrotator": "^3.0.5",
    "egg-multipart": "^2.4.0",
    "egg-onerror": "^2.1.0",
    "egg-schedule": "^3.6.0",
    "egg-security": "^2.4.3",
    "egg-session": "^3.1.0",
    "egg-static": "^2.2.0",
    "egg-view": "^2.1.2",
    "egg-watcher": "^3.1.0",
    "extend2": "^1.0.0",
    "graceful": "^1.0.2",
    "humanize-ms": "^1.2.1",
    "is-type-of": "^1.2.1",
    "koa-bodyparser": "^4.2.1",
    "koa-is-json": "^1.0.0",
    "koa-override": "^3.0.0",
    "ms": "^2.1.1",
    "mz": "^2.7.0",
    "on-finished": "^2.3.0",
    "semver": "^7.3.2",
    "sendmessage": "^1.1.0",
    "urllib": "^2.33.0",
    "utility": "^1.15.0",
    "ylru": "^1.2.1"
  }

Midway

{
    "@eggjs/router": "^2.0.0",
    "@midwayjs/decorator": "^1.20.3",
    "debug": "^4.1.1",
    "egg": "^2.20.0",
    "egg-core": "^4.15.0",
    "egg-logger": "^2.3.2",
    "extend2": "^1.0.0",
    "injection": "^1.8.0",
    "midway-core": "^1.20.3",
    "midway-schedule": "^1.20.3",
    "mkdirp": "^0.5.1"
  }

Nest

{
    "@nuxtjs/opencollective": "0.3.2",
    "axios": "0.21.1",
    "class-transformer": "0.4.0",
    "class-validator": "0.13.1",
    "cli-color": "2.0.0",
    "cors": "2.8.5",
    "express": "4.17.1",
    "fast-json-stringify": "2.7.9",
    "fast-safe-stringify": "2.0.8",
    "iterare": "1.2.1",
    "object-hash": "2.2.0",
    "path-to-regexp": "3.2.0",
    "reflect-metadata": "0.1.13",
    "rxjs": "7.3.0",
    "socket.io": "4.1.3",
    "tslib": "2.3.1",
    "uuid": "8.3.2"
}

依赖情况总结

image.png
从上图看

  • Nest 是依赖于 Express
  • Midway 依赖于 Egg,Egg 又依赖于 Koa

## Hello World 对比 ![image.png](https://cdn.nlark.com/yuque/0/2021/png/750901/1631446783578-51fe6474-6bae-4579-9e9f-167a3c77e791.png#clientId=u851b1f9b-9a9b-4&from=paste&height=188&id=u1bc00bd8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=376&originWidth=800&originalType=binary&ratio=1&size=248257&status=done&style=none&taskId=ud69a0a72-1019-46b8-8100-974ef0cb9e5&width=400)
下面分别展示不同框架下实现 `helloword`

### Express `pre install` ```json mkdir express; cd express; npm init -y; yarn add express ; touch app.js; ``` `app.js` ```json const express = require('express') const app = express() const port = 3000

app.get('/', (req, res) => { res.send('Hello World!') })

app.listen(port, () => { console.log(Example app listening at http://localhost:${port}) })

`run`

- node app.js
- curl http://localhost:3000



目录情况
```json
|____package.json
|____app.js

Koa

  • pre install -> mkdir koa; cd koa; npm init -y; yarn add koa; vim app.js
  • 输入 app.js
const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);
  • node app.js && curl localhost:3000

目录

|____package.json
|____app.js


### Egg
  • pre install -> mkdir egg; cd egg; npm init egg --type=simple; npm i;
  • npm run dev && curl localhost:7001

目录

.
|____jsconfig.json
|____app
| |____controller
| | |____home.js
| |____router.js
| |____public
|____test
|____config
| |____config.default.js
| |____plugin.js
|____.eslintrc
|____.autod.conf.js
|____README.md
|____appveyor.yml
|____logs
|____.gitignore
|____package.json
|____.github
| |____workflows
| | |____nodejs.yml
|____.eslintignore
|____run
|____.travis.yml

如果说 express 和 koa 给我们的是一张白纸,egg 就为我们约定好了一套企业通用的规则。

Midway

  • pre install -> npm init midway --type=web midway;
  • npm run dev; curl localhost;7001

目录

.
|____test
|____jest.setup.js
|____jest.config.js
|____bootstrap.js
|____typings
|____.editorconfig
|____logs
|____.gitignore
|____package.json
|____tsconfig.json
|____run
|____.eslintrc.json
|____src
| |____config
| | |____config.local.ts
| | |____plugin.ts
| | |____config.default.ts
| | |____config.unittest.ts
| |____controller
| | |____api.ts
| | |____home.ts
| |____interface.ts
| |____service
| | |____user.ts
| |____configuration.ts

其他的语言生成的都是 JavaScript,Midway 生成的默认语法 TypeScript。而且从上面的结构上看 MidWay 生成的结构和 egg 的结构非常像,所以说底层应该是引用了 Egg 的。


### Nest
  • pre install -> npm i -g @nestjs/cli; nest new nest;
  • yarn run start; curl localhost:3000


目录

.
|____test
| |____app.e2e-spec.ts
| |____jest-e2e.json
|____nest-cli.json
|____README.md
|____yarn.lock
|____.gitignore
|____package.json
|____tsconfig.build.json
|____.prettierrc
|____.eslintrc.js
|____tsconfig.json
|____src
| |____main.ts
| |____app.service.ts
| |____app.module.ts
| |____app.controller.spec.ts
| |____app.controller.ts

nest 默认也是 TypeScript

TypeScript 的支持

FrameWorkTypeScript 支持度
Express⭐️ ⭐️ ⭐️
Koa⭐️ ⭐️ ⭐️
Egg⭐️ ⭐️
Midway⭐️ ⭐️ ⭐️ ⭐️ ⭐️
Nest⭐️ ⭐️ ⭐️ ⭐️ ⭐️

因为 Egg 的核心是 loader 加载机制。更多的是约定大于配置,这样对 TypeScript 的支持我个人感觉更加不友好 😈

相关项目

语言的未来的发展。这里挑选的是在 Github 中 topic:${name} 的前 Top 10 的项目。

Express

Koa


### Egg

Midway


### Nest
## 微服务 支持 | FrameWork | 微服务 支持度 | | --- | --- | | Express | ⭐️ ⭐️ | | Koa | ⭐️ ⭐️ | | Egg | ⭐️ ⭐️ | | Midway | ⭐️ ⭐️ ⭐️ ⭐️ ⭐️ | | Nest | ⭐️ ⭐️ ⭐️ ⭐️ ⭐️ |