精华 EggJS 10000 Star + 2 years - 阿里 Node 企业级框架 ✨✨✨
发布于 1 年前 作者 atian25 13623 次浏览 来自 分享

『大吉大利,明早吃蛋。』

底部有文化衫活动邀您参加。

知乎原文地址:https://zhuanlan.zhihu.com/p/45143762

image.png

2016 年 9 月,我们在 JSConf China 2016 上宣布了 Egg 开源,至今整整 2 年了。 在 Egg 2.0 发布通告 提到,核心代码已经很稳定,后续重心主要在开发者体验方面的优化。

Egg 是阿里 Node.js 的核心基础框架,面向『企业级的 Web 基础框架』这个领域,提供了「微内核 + 插件机制 + 框架定制能力」,完美达成生态共建和差异化定制的平衡点。

既适合个人小项目快速开发,也适合团队架构师基于自身的技术架构在 Egg 基础上扩展出适合特定团队业务场景的框架。

它沉淀自阿里在各行各业不同领域的大规模工程实践经验,稳定支撑了多年天猫双11大促,顶级流量压力。

接下来跟大家分享下,过去 9 个月里面,我们的一些产出和数据,本文较长,请慢慢品用:

  • 开发者数据分享
  • 文化衫活动邀请
  • 开发者体验优化
    • TypeScript 的支持
    • 新增「生命周期」
    • Alinode 接入指南
    • 和 Java 的互联互通方案
    • 实践案例 - 用 Egg 重构的 cnode 社区
    • 来自语雀团队的 sequelize ORM 实践分享
    • 与 Webpack 等前端工程的实践分享
    • 错误处理和 opentracing 的 RFC
    • egg-init 骨架重构方案
  • 未来规划

开发者数据

image.png | left | 600x303

  • 官网 PV 在 1.2w 左右。
  • npm egg 模块数 1006 个,GitHub 依赖库 3738 个。
  • 一千多个 Pull Request,2200 个 Issue,130 多位 Contributors 。
  • 共发布了 81 个版本,Release Note
  • 社区实践项目:cnodejs/egg-cnodeeggjs/awesome-egg
  • 知乎专栏 Node.js 一共发布了 48 篇文章,7600 订阅,阅读数据未知(知乎创作者中心看不上咱,不给内测资格 😭)。

正在使用 Egg 的公司,不完全统计:

  • 深度使用的: 阿里巴巴,全民直播,网易考拉
  • 使用并有分享过使用经验的:去哪儿,摩拜,点评
  • 有个别团队咨询过试水但最终有没有落地的不知道:美团,新浪,百度,腾讯,YY 等

顺便分享一个 cnpm 的统计数据

image.png | left | 720x423

image.png | left | 720x413


文化衫活动

欢迎大家访问以下链接,分享你们的实践经验,有机会获得 Egg 文化衫和相关周边喔~ 另外,第 10000 Star 的同学 godmeir 请联系我们。

『2018 年 EggJS 怎么样了?对它的看法有什么变化?』

image.png | left | 600x800


开发者体验优化

接下来跟大家分享下这段时间来,我们在『开发者体验』方面做的一些优化。

TypeScript

这几年来 TypeScript 很受欢迎,它的静态类型检查,智能提示,IDE 友好性等特性,对于大规模企业级应用,是非常的有价值的,被视为是企业级 JS 开发的未来之一。

阿里内部实践 TS 也蛮久了,在 5 个月前,也把我们的其中一部分成熟的实践,分享出来: 『天猪:当 Egg 遇到 TypeScript,收获茶叶蛋一枚』

非常感谢 @吖猩 在这领域的持续贡献:

这块目前还在持续优化中,有兴趣的同学可以参与以下几项优化:

  • egg-ts-helper 增加对 js 的支持,这样非 ts 的同学,也能享受到智能提示和静态检查的 Buffer 加成。
  • 完善插件自带的 d.ts 方便其他开发者。
  • 分享你的上层封装,如通过装饰器来注册路由或 AOP。(内部有不少实践,但还未达成共识)

PS: Egg.js 本身不会使用 TypeScript 重写,对于框架本身而言,JS 的灵活性可以让它更容易实现一些特性,同时它也并没有那么复杂的业务逻辑,TypeScript 并无法给框架研发带来更多的帮助。

生命周期

之前 Egg 提供给开发者在启动期的钩子不多,只有 beforeStart 几个。 感谢 killagu 同学给我们补充了更细致的生命周期,相关的 RFC 和文档如下:

// app.js
class AppBootHook {
  configDidLoad() {
    // Config, Plugin files have did load.
  }

  async didLoad() {
    // All files have did load, start plugin here.
  }

  async willReady() {
    // All plugins have started, can do some thing before app ready.
  }

  async didReady() {
    // Worker is ready, can do some things don't need to block the app boot.
  }

  async serverDidReady() {
    // Server is listening.
  }

  async beforeClose() {
    // Do some thing before app close.
  }
}

Alinode

Node 发展到今天,已经被越来越广泛地应用到前后端分离、全栈开发、客户端工具等领域。 然而,相对于应用层的蓬勃发展,其 Runtime 对于绝大部分前端出身的开发者来说,处于黑盒的状态,这一点并没有得到很好的改善,从而也阻碍了 Node.js 在业务中的应用和推广。

作为一个 Node 开发者,最头痛的事莫过于莫名其妙的 CPU 100% 和内存泄露导致的 OOM。

所幸的是,阿里云 @朴灵 团队的 Node.js 性能平台 为 Node 开发者提供了:性能监控、安全提醒、故障排查、性能优化 等服务的整体性解决方案,提供完善的工具链和服务,协助开发者快速发现和定位线上问题。这些年来,为我们解决了非常多的线上问题,为业务保驾护航。

相关分享:

当然,在日常的答疑中,很多同学也表达了对数据安全方面的担忧。从我个人的角度来看,Alinode 的采集脚本,都是开源了,不会采集隐私数据。实在不行,在压测期接入用用也行,绝对可以让我们少掉一点头发,良心推荐。

和 Java 互联互通的方案

Node.js 在蚂蚁和阿里已经发展了四、五年时间,从最开始「前端工程师的玩具」,到 Web、BFF 场景的破局,逐步走到线上甚至是一些核心业务,非常不容易。

回头想想 Nodejs 为什么能活下来?依靠的绝不仅仅是:非阻塞I/O、事件驱动、轻量这些官方宣传的特性,我们认为更重要一点是我们打通了和 Java 的桥梁,实现了互联互通,这才让它真正融入阿里的技术体系。

伴随 蚂蚁 SOFA Java 技术栈 的开源,我们也开源了 Nodejs RPC 相关模块,希望能填补 Nodejs 社区这块的空白,也将我们几年来在 Nodejs 基础技术的一些经验做个总结和分享。

推荐阅读小丸子姐姐的相关科普文章:

egg-cnode

朴老师发起的 cnodejs/egg-cnode 项目,用 Egg 重写了 cnode 社区应用。 目前完成了功能层面的重构以及测试用例的补全:

  • 文件数减少 41,减少 22%
  • 代码行数减少 2460 行,减少 4.7%
  • 测试代码减少 980 行,减少 39%,覆盖率高于原项目。

目前还有较大的优化空间,因为第一阶段专注于功能迁移,不做大的优化,有些使用方式不符合 Egg 的最佳实践,欢迎有兴趣的同学加入一起完善。

值得关注的 RFC 和分享

在 eggjs 团队的日常协作中,遵循「基于 GitLab 的硬盘式异步协作模式」。 通过 issue 发起 RFC 提案 -> 讨论定稿-> 提交 Pull Request -> Code Review -> 发布。 这样便于沉淀,即使是当时没有参与讨论的开发者,事后也能通过 issue 了解某个功能设计的前因后果。

Θ 来自 语雀团队 的 ORM 实践分享

  • 语雀是基于 Egg 技术栈研发的,算是为数不多的涉及到各个技术点的 Node 大应用。
  • Egg 文档 - Sequelize

Θ 与 Webpack 等前端工程的实践分享

Θ 错误处理 && 问题跟踪

Θ 工具优化 目前的 egg-init 存在以下问题:

  • 脚手架逻辑集中化,全部在 egg-init 本身,作为全局命令,更新不方便。
  • 模板无法定制自己的逻辑,无法代码共享。
  • 没有 sub generator,如 egg-init add controller Test 这样的功能。
  • 脚手架只在项目初始化时用到,无法支撑升级功能,容易腐化和分裂。
  • 上层封装不方便,不支持 preset 。

因此提出了 『[RFC] egg-init refactor 』,应该下个月可以完工并分享给大家。

Θ 科普文 提到 Egg 值得自豪的应该是我们的文档吧,我们深知前端开发者在后端知识面还有很多需要科普的,也很乐意分享我们的实践:

『专访死马:为什么说Egg.js是企业级Node框架』

未来规划

老实说没有太多新特性,还是那个原因:Egg 采用的是『微内核 + 插件 + 上层框架』模式。

Egg 自身的迭代采取插件化的开发机制,功能分散在不同的模块中,可能开发者在使用时感知不到它的版本变更,但其实它一直都在进化。每周都可能有新特性和 BugFix 发布,更像是一个『改良派』而不是『改革派』,它会在兼容的前提下不断进化。

接下来的规划,还将继续放在 『开发者体验优化 + 实践经验分享』 方面。

  • egg cli 工具链和骨架的重构优化。
  • TypeScript 的继续优化,以及增加对 js 项目智能提示方面的支持。
  • 更多的实践项目和科普分享。
  • 国际化。

仅凭我们自己的精力是远远不够的,欢迎社区的大家一起加入,共同推动 Node 的发展。

写在最后

  • 如果你喜欢 Egg,请支持我们:
  • 分享本文,为我们点赞。
  • 来分享下你们的实践,无论大小,这很重要,谢谢,将有机会获得我们的文化衫。

『2018 年 EggJS 怎么样了?对它的看法有什么变化?』

  • 如果喜欢我的文章,请关注 我的知乎Follow GitHub
  • 广州阿里游戏,招前端,熟悉动效,Node 的速来~
51 回复

有空看看如何解决这个吧 https://github.com/eggjs/egg-cluster/pull/75 ps 妹儿不错

急需5个伙伴 unstar 一下, 这样我就是第 10000 个了,另外问一下 @atian25 是送妹子吗?

镇楼图好评

来自酷炫的 CNodeMD

image.png 放张 star 的趋势图,一步一个脚印

👍 点个赞。

@waitingsong 说句实话,直接在框架层使用这个worker方案,我并不认为是好事。 比如这会让beforeStart行为很奇怪,会让调试的现象更诡异以及架构灵活性会被相对较大的制约。 并不是说框架的worker的技术不好,讲真,主进程fork出agent管理cluster的方案是可以的。但感觉不适合直接打在框架里,我可能更愿意把worker做成更可插拔的功能。

当然egg会有上面的worker方案也必然经过了深思熟虑的,而我可能也只看到了一面

给力 egg其实很好用的。

Taro客户端发来热烈的祝贺

来自拉风的 Taro-cnode

来自酷炫的 CNodeMD

@zy445566 如果框架不实现worker 那么 worker 的通信恐怕不好管理。 目前的方案应该是兼顾各方面平衡的结果。

祝eggjs越来越好👍

一直在用EGG,茶叶蛋很好吃

@waitingsong 不对,我的意思是根本不要worker。 我为什么要在框架里面充分利用CPU,我更愿意开4个容器每个设置1核来用,用容器来伸缩。 而且直接在框架中增加,我觉得增加复杂度远大于我性能提升的好处。 你这个回答显然没有说服我,我都不要worker了,为什么还要worker通讯

@zy445566 这你得问问lz了 我认为多容器,也存在对容器(服务)的管理,包括状态监控、任务分发等。这依然需要一个上层的抽象层来实现。而egg不过是集成了而已,并且实现也许比容器方案还简单些。

@waitingsong 好吧,感谢你的回答,谢谢

@zy445566 egg是小而全的框架,追求简洁,所以多任务是自己实现而没采用现成的 pm2。大而全的就是 k8s 那陀拉~ 你也可以设定egg只启动一个 worker (加上master和agent总共3个进程) 然后容器化嘛。

没有银弹,实在不需要,如上说的,一个 worker,一个 agent,一个 master 就好了,没啥资源损耗。

实在要定制,可以自己写个 my-egg-cluster,然后基于 egg-core 继承为自己的一个框架。但缺点就是,生态里面用到 agent 和消息机制的一些插件会挂掉。或者是类似 egg-mock 那样,把 app 和 agent 放到一个进程里面去加载,这样是可以兼容插件。

但问题是,我们的资源利用率需要扣这么一点么? 一定要把所有目前暂时不需要的,即使不碍事的,也全部要清理掉么?

我们自己业务一般是配置 docker 为 4 个 cpu,启动 4 个 worker。

还有一种场景,不一定准确:

同样是 16 个实例的情况下,如果 agent 里面跟后端建立长连接,如果是 4 worker + 4 docker 就只有 4 条长连接,而 1 worker + 16 docker 是 16 条。

在 Egg 出现的时候,甚至到现在,Docker 也并没有成为每个团队的可选项。

没有银弹,只关乎历史惯性 + 取舍的平衡点。

@atian25 这确实是一个好的解释 我想是因为我这边只站在了纯后端的角度(可能是我这边服务没有Java只有node的缘故),所以考虑并不周到 但如果要做中间层或服务前端的后端,这确实是必然的需求

@zy445566 对于阿里来说egg应该是BFF首要需求,兼顾后端服务需求,所以是这样的设计。你需求是纯后端服务(那agent估计都不需要了,直接单进程然后容器化)

赞,顺便来看看中间关于worker讨论的几个楼

@waitingsong 其实留着也没问题,反正不耗什么

猪哥,我们比较期待一个ts+egg的开源实践。huaji.gif

看到支持TS真的非常非常激动

@yanlele 半年前就支持了

@zzx0106 欢迎贡献。。。 完整的开源项目这种很难的,大部分都是业务,没法开源的。

eggjs中http和socket.io怎么共享session啊头大

哈哈哈,妹子好评。

来自MaterialCNode

可以好好学一下

@zy445566 所以说egg是企业级框架,对于小司用node后端来讲,egg算是重量级框架了

用eggjs1年多了,非常好用,祝eggjs越来越好

顶一下,感觉学的东西又多了!

回到顶部