GithubHelp home page GithubHelp logo

eggjs / egg Goto Github PK

View Code? Open in 1sVSCode Editor NEW
17.9K 475.0 1.7K 59.25 MB

🥚 Born to build better enterprise frameworks and apps with Node.js & Koa

Home Page:

License: MIT License

JavaScript 98.68% Shell 0.11% TypeScript 1.02% Less 0.19%
egg framework koa koa2 koa-middleware nodejs node-framework enterprise eggjs

egg's Introduction

NPM version NPM quality NPM download FOSSA Status

Continuous Integration Test coverage Known Vulnerabilities Open Collective backers and sponsors


  • Built-in Process Management
  • Plugin System
  • Framework Customization
  • Lots of plugins


Follow the commands listed below.

$ mkdir showcase && cd showcase
$ npm init egg --type=simple
$ npm install
$ npm run dev
$ open http://localhost:7001

Node.js >= 8.5.0 required.




How to Contribute

Please let us know how can we help. Do check out issues for bug reports or suggestions first.

To become a contributor, please follow our contributing guide.

Sponsors and Backers

sponsors backers



FOSSA Status

egg's People


dead-horse avatar atian25 avatar popomore avatar fengmk2 avatar thonatos avatar whxaxes avatar SunShinewyf avatar shaoshuai0102 avatar killagu avatar gxcsoccer avatar lslxdx avatar waitingsong avatar Azard avatar cemremengu avatar DarrenWong avatar kylezhang avatar leoner avatar jtyjty99999 avatar MaledongGit avatar XadillaX avatar SF-Zhou avatar mansonchor avatar okoala avatar monkindey avatar BaffinLee avatar shepherdwind avatar ngot avatar denghongcai avatar Jeff-Tian avatar mattma avatar


simexce avatar  avatar KoSanFai avatar 今天你写bug了吗 avatar  avatar 不二先生 avatar  avatar Dear John avatar 王乐轩 avatar John avatar Jack avatar  avatar Gad Iradufasha avatar Johnson avatar  avatar  avatar Jay Parmani avatar 余晖 avatar Islem Maboud avatar Mithat Ercan avatar  avatar Vickko avatar Hank Chiu avatar Omar Dulaimi avatar  avatar  avatar GunnmF avatar Yサイズ avatar kimifdw avatar Zorro avatar APIS-X avatar  avatar  avatar zhuoyan avatar T4J avatar MoonLake avatar  avatar  avatar OldDriver avatar pteea avatar ZRY551. avatar  avatar xunfeng avatar Yuanjun Zhong avatar whyccc avatar iCloud.Yin avatar 季悠然 avatar Mukiyat Berdikhan avatar jiang-24-gdufs avatar  avatar  avatar  avatar 懒熊吖 avatar fyb avatar  avatar hao avatar JohnTitor avatar Alexander Balyshyn avatar Tao Pan avatar  avatar  avatar 简单框架(马克) avatar Hao.Dongfang avatar  avatar xueyunfeng avatar Saria Mirza avatar 张剑™ avatar Alvis avatar TF avatar  avatar  avatar markthree avatar Jesse Pledger avatar  avatar lvvvl avatar 洋葱呀 avatar Chuck avatar waiting avatar zhang avatar  avatar  avatar  avatar yushuisheng avatar Suxiaohui avatar  avatar 越南小商贩 avatar  avatar zixi0825 avatar starOfTomorrow avatar yinan avatar NULL avatar Root avatar  avatar  avatar  avatar wslyiyi avatar 大学生日常 avatar 王浩 avatar mezz2020 avatar  avatar


azu avatar Fangdun Tsai avatar Paulo R. A. Sales avatar yuanhong avatar Jawf avatar lifesinger avatar sharper avatar fengmk2 avatar davidwei_001 avatar 刘永健 avatar TZ | 天猪 avatar Jandy avatar Donosn avatar dafei1288 avatar 穿山甲 avatar satans17 avatar Haoliang Gao avatar Yang Leijun avatar dingyun avatar  avatar saiyagg avatar Shawn avatar bingdian avatar  avatar Tony Liu avatar hui avatar 伍伟 avatar  avatar QIqiZhou avatar RockyChao avatar poprlz avatar guixue avatar hz2004 avatar jack avatar kimhou avatar xiaoxian avatar Jinhui Fan avatar Archer (炽宇) avatar miser avatar FX avatar James Cloos avatar Corning avatar cheng xu avatar Suyi avatar vincent guo avatar garryshield avatar .ッ掌心、 avatar aurimas avatar  avatar Kitsune avatar Ray avatar diycp avatar Alexander avatar 李文富 avatar ShFu avatar  avatar zōng yǔ avatar MogicYang avatar zhangaz1 avatar Albert 理斯特 avatar 知行ethan avatar tangyao avatar durban zhang avatar Deng Ruoqi avatar echo avatar Sirajuddin Khan avatar 任国强 avatar  avatar Richie avatar Edward Xie avatar  avatar NoScripter avatar 蔡正海 avatar robert avatar  avatar Jamy avatar  avatar  avatar Wei DeMing avatar Wang, Enjun avatar forl avatar CaiCai avatar GreyWolf avatar gdiplus avatar hodgevk avatar zhangchen avatar Ming Gong avatar  avatar 1166544 avatar  avatar jorry有桥 avatar 史蒂芬孙 avatar 仙森 avatar Carlis Liu avatar avatar Cobain avatar  avatar  avatar  avatar  avatar

egg's Issues

proxymock 改造

  • egg-proxymock -> egg-mockdata ?
  • 配合 loader #11 的改造, 支持 mock 不同的对象
  • 除了原支持的 exports.fn 方式, 增加 class 的支持, 如继承 ServiceClass 然后替换


增加不同类别的 label

  1. semver: major, semver: minor, semver: patch
  2. core
  3. plugin: security,
  4. tools: egg-mock, egg-bin
  5. feature, fix, refactor, improve, test, doc, release, discussion

Master 去除 loader 依赖

master 现在的 loader 会加载 config

  1. 读取 env,可以单独实现
  2. 获取 logger 的配置,master 的 logger 可以直接使用 consoleLogger,error 打到 stderr

Frontend send ajax request to Egg has an error of CORS or OPTIONS 405 Method Not Allowed

Goal: Egg works as simple RESTful api server, Frontend communicates with Egg via Ajax requests. Browser (Chrome latest) has Cross Origin enabled by default. Egg enabled CORS, frontend sends a request and need to get the payload back from Egg.

I have created an Angular frrontend and trying to talk to Egg ONLY via RESTful api. But I run into an issue of CORS. This is the error message from browser console:

XMLHttpRequest cannot load http://localhost:7001/api/user. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

I am not sure that it is an error from front end, or egg, or its plugins: egg-rest, egg-cors, or just an User error.

Here is how you can duplicate the issue.

1st Use [examples/restful_api] , then enabled cors plugins at [here](

// restful_api/config/plugin.js
exports.cors = true; = true;

Note: it works on curl with/without cors=true. and all CRUD operation works as expected.

2nd Frontend ajax request: Here I included a simple HTML with jquery ajax caller.

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <script src=""></script>
      url: "http://localhost:7001/api/user",
      type: "GET",
      contentType: "application/json",
      async: true,
      crossDomain: true,
      beforeSend: function(xhr) {
        xhr.setRequestHeader('X-Test-Header', 'test-value');
      success: function( users ) {
        console.log('users: ', users)

3rd - Load up in the browser, I see the error below:

screen shot 2016-08-14 at 9 57 59 am

Error on terminal console

screen shot 2016-08-14 at 10 02 38 am


关于 loader 有几个问题,需要先确定下

  • 运行环境及其名称,是否还是这几个 prod, test, default, local, unittest
  • 运行环境如何确定,除了 process.env.NODE_ENV
  • 是否还需要支持 framework 封装这个功能?


确定 Release 规则


Egg 参与人员过多,仓库过多,经常会遇到某个人没有某仓库的发布权限。

Release 时会修改版本和更新 changelog,这个也需要 review。


  1. Changelog 可 review
  2. npm 自动发布
  3. 锁定 master 目录不允许提交


锁定 master 目录不允许任何人提交,并添加合并检测(review+2,travis 和 codecov 通过)。

Release 时本地修改版本和 changelog 后提交 PR,review 后合并。

Travis 根据 commit 信息判断是否 release(非 PR,master 分支,切 commit 匹配),通过 eggjs 账号 发布到 npm。


  • 支持 travis 发布 npm 包,还需要自动 push tag
  • “本地生成 changelog 和版本”有工具支持,保证生成格式一致
  • 文档更新
  • 确定 commit 信息 chore(release): release 1.0.0
  • 自动更新 github release

Updated at 2017-02-09

screenshot 2016-08-16 8 25 51

以后所有的仓库都需要这样配置,不允许直接 push 到 master。但是 release 的时候还有一步需要 push,这个规则需要明确下。



Framework Slogan

Here are a few ideas for the Egg.js framework slogan

  1. A supreme node.js framework builder to maximize productivity
  2. A modular framework builder for node.js developer
  3. The last node.js framework you ever need
  4. The node.js framework changes everything
  5. A promise to your success
  6. A node.js framework Builder
  7. next generation web framework builder for node.js (Note: compared with slogan)
  8. Modular, opinionated, feature rich web framework for Node.js (Note: compared with slogan)

Example cookie does not work

Running cookie example, I clicked on "remember" checkbox, then submit. It routes to /remember route, none of the logic in remember route is being run due to error secret is missing. See the full error log

2016-08-11 23:52:47,376 INFO 10862 [-/::1/-/8ms GET /] status 200 (rt: 8ms)
2016-08-11 23:52:49,389 WARN 10862 [-/::1/-/15ms POST /remember] nodejs.ForbiddenError: secret is missing
    at Object.module.exports.throw (/Users/mattma/Desktop/egg/egg/node_modules/koa/lib/context.js:91:23)
    at Object.context.assertCSRF.context.assertCsrf (/Users/mattma/Desktop/egg/egg/node_modules/koa-csrf/index.js:69:30)
    at Object.csrf (/Users/mattma/Desktop/egg/egg/node_modules/egg-security/lib/middlewares/csrf.js:39:12)
    at next (native)
    at Object.<anonymous> (/Users/mattma/Desktop/egg/egg/node_modules/koa-compose/index.js:29:12)
    at next (native)
    at onFulfilled (/Users/mattma/Desktop/egg/egg/node_modules/co/index.js:65:19)
    at /Users/mattma/Desktop/egg/egg/node_modules/co/index.js:54:5
    at (/Users/mattma/Desktop/egg/egg/node_modules/co/index.js:50:10)
    at Object.toPromise (/Users/mattma/Desktop/egg/egg/node_modules/co/index.js:118:63)

Deadline -- 8月底前必须完成的事.

做下备忘, 然后定下时间点和分猪肉吧.

我们还剩下不到 15 天了, 包括周六日.

  • 类库
    • 完成 egg 的所有核心库
    • egg 插件检查 (文档, 注释英文, 更新依赖版本, 发布 1.x 版本, public ) #5
    • 框架
      • aliyun-egg 还搞么?
    • example
  • 数据收集 @fengmk2 @gxcsoccer
    • benchmark
    • 业务使用情况统计, 应用数/进程数 (先放到内网 issue, 并走数据披露流程)
  • 文档编写
    • 编写使用文档, 参考 chair 文档
      • 列出大纲 (#55) @atian25
      • 术语整理
      • 文档列表(待分猪肉)
    • 文档翻译为 English @mattma
    • Web 规范文档的翻译 @mattma
      • 是否需要补充 logger 的规范进去?
      • #12
    • Api 文档构建 #34
    • jsconf ppt 编写 ( @atian25 本周出大纲 review )
  • 官网建设 (已出原型图, 使用 hexo 发布, @popomore)
  • 清理 milestone, #5

cc @eggjs/core @eggjs/contributor

1.0 Milestone





  • aliyun-egg


  • egg README
  • 其他 README 规范
  • Tutorial
  • benchmark @fengmk2

release ready


  1. 先提交源码保证可以用,依赖层级比较深。
  2. 补测试,测试的目录接口和源码保持一致。
  3. 新仓库先提交空的 README,提交 PR 完成功能,补测试需要测试通过

重构 messenger


  1. broadcast(action, data):发送给所有的 agent / app 进程(包括自己)
  2. sendToApp(action, data): 发送给所有的 app 进程
    • 在 app 调用该方法上会发送给自己和其他的 app 进程
    • 在 agent 上调用该方法会发送给所有的 app 进程
  3. sendToAgent(action, data): 发送给 agent 进程
    • 在 app 调用该方法上会发送 agent 进程
    • 在 agent 上调用该方法会发送给 agent 自己
  4. sendRandom(action, data):
    • app 上没有该方法(现在 egg 的实现是等同于 sentToAgent)
    • agent 上回随机发送消息给一个 app 进程(由 master 来控制发送给谁)
  5. sendTo(pid, action, data): 发送给指定进程

[RFC] 抽取 passport 模型

  • egg-passport-github
  • egg-passport-weibo @shaoshuai0102
  • egg-passport-gitlab
  • egg-passport-google
  • egg-passport-taobao

RFC: passport

由于业界的 passport 已经足够简单,egg 做起来就是配置。对应应用开发者,更加是配置,基本无需编写代码就能实现。

一个应用的 authenticate 通用过程

  1. 用户会选择应用提供的其中一种 strategy 进行 authenticate 登录,如应用同时提供了 twitter 和 facebook 两种方式。
  2. 用户去 twitter 登录成功后,会返回应用网站,然后 egg-passport-twitter 插件,会使用 verify callback 来完成对统一约定 user 的封装,继续返回给 egg-passport 做后续处理。
  3. egg-passport 会触发 app.passport.verify hook,这样应用层就能做最终的核实,例如做新用户注册,老用户绑定校验等等,这里也是用户数据持久化的地方。
  4. 用户登录之后,每次访问应用都会根据 app.passport.deserializeUserapp.passport.serializeUser 来还原 session。


  • 框架内置了高度抽象的 passport 插件。
  • passport-xxx 插件都需要声明依赖内置的 passport 插件。
  • passport-xxx 插件开发者只需要简单结合一下 现有的模块,就可以快速完成一个网站的 authenticate 接入。
    如要对接 Twitter 的 oauth,那么只需要引入 passport-twitter,并实现一个 passport-twitter 插件即可。

统一 user 字段约定

ctx.user 是一个 getter,真实数据来自于 ctx.state.user

每个 passport-xxx 插件都需要按照约定封装一个 user。

  • 必须 user.provider: 用户信息来自那种登录策略,如 twitter, weibo, facebook,这样就能通过此字段读取 user.profile 信息了。一般都是自动填充
  • 必须 用户 id,字符串
  • 必须 用户名
  • 可选 user.displayName: 昵称
  • 可选 user.token: oauth1 的话必须提供
  • 可选 user.tokenSecret: oauth1 的话必须提供
  • 可选 user.accessToken: oauth2 的话必须提供
  • 可选 user.refreshToken: oauth2 的话必须提供
  • 可选 user.profile: profile 的其他字段,每个平台提供的都不太一样,需要各种区别

passport 配置

// config/config.${env}.js
exports.passport = {
  twitter: {
    consumerKey: 'your-consumer-key',
    consumerSecret: 'your-consumer-secret',
    // 更多配置请查看 passport-twitter 插件

应用需要关注的3个用户数据处理 hooks

// app.js
module.exports = app => {
  // 1. 核实登录用户信息,自行判断是否需要做数据调整,
  // 也可以在这里由应用自身统一 user 的数据结构,并且保存到数据库。
  // - 必须返回核实后的 user,即 verifiedUser,数据结构可以由应用自行统一约定
  // - 核实失败,throw 一个带有 status = 401 的 error 异常
  // - 其他异常,将会当作服务端内部异常处理
  // passport-xxx 插件已经按约定生成了 user 数据,应用可以在此做最终的用户校验,并且做数据持久化
  // 在 strategy.authenticate 成功之后调用
  app.passport.verify(function* (ctx, user) {
  // 自行处理经过 verify 后的 verifiedUser 数据如何序列化到 session
  // 在 http 请求结束阶段,保存数据到 session 之前调用
  app.passport.serializeUser(function* (ctx, verifiedUser) {
    // you can store profile and handle token here
  // 根据 sesssion 中的 sessionUser 信息,还原出 verifiedUser
  // 在 http 请求开始阶段,还原 session 之后调用
  app.passport.deserializeUser(function* (ctx, sessionUser) {


初始化项目出错 read ECONNRESET

[test] egg-init --type simple showcase
[egg-init] /Users/xx/test/showcase is not exists, now create it.
[egg-init] dest dir is /Users/xx/test/showcase
Error: read ECONNRESET
    at exports._errnoException (util.js:896:11)
    at TLSWrap.onread (net.js:556:26)


刚看了 Singleton 的文档, 有几点疑问, 讨论下:

  • 我们之前的实现里面, 有很多用 Symbol + this[HELPER] 之类的方式去实现只实例化一次的对象, 这个是不是可以类似提供下简化方法?
  • 是否要考虑 loader singleton 的约定?
  • Singleton 其实是支持多实例的,那这个命名是不是不太准确?
  • 示例里面的 DataService 这个命名感觉有点问题, 会认为是放在 app/service 下, 但这个就是每个请求一个实例了.


通用安全插件、阿里云各服务插件(oss、cdn、等等常用的) @fishbar

  • egg-oss
  • egg-rds -> egg-mysql
  • egg-security
  • mts
  • ots
  • mc
  • ons


[RFC] egg-opentracing

分布式链路追踪是当今微服务架构中必不可少的组成部分,一个请求穿插于各个应用系统、中间件、数据库之间,通过 tracing 就能知道整个请求的链路以及各部分的耗时。Egg 会基于开放的 opentracing 来实现这个功能。


Trace:一个 Trace 代表在微服务架构中的一次链路请求,可能经过一个或多个微服务应用。

Span:一个 span 代表系统中具有开始时间和执行时长的逻辑运行单元,一个 Trace 会包含多个 Span。

SpanContext:代表一个 Span 的信息,比如 TraceId,spanId,以及该 Span 的相关信息。注意:这个和 egg 的 ctx 没有关系。

Baggage:还有一些信息也在 SpanContext 中,我们称之为 Baggage,这些信息会在整个 Trace 中传递。

Tag:Span 中用来识别 span 的一些信息,比如

  • error
  • component: httplib, jdbc, mongoose
  • span.kind: client, server
  • http.url
  • http.method
  • http.status_code
  • framework
  • peer.hostname

Carrier:在微服务架构中,两个应用之前会通过不同的协议进行通讯,但是 opentracing 是无法感知的,所以定义了 Carrier 这个概念,他通过 Inject 和 Extract 和 SpanContext 之前进行互相转换,然后 Carrier 可以在协议中传递。比如 HTTP 请求,SpanContext 通过 Inject 设置 HTTPCarrier(转换成请求头),在请求接收方通过 Extract 将 HTTPCarrier 提取成 SpanContext。

Collector:我们通过 Collector 收集每个 span 的具体信息,然后记录,可以通过日志的方式或请求上报的方式。


Egg 提供 ctx.tracer 实例作为一次 Trace,下面按照一个微服务应用整个请求周期描述各个 API


比如收到了一个 HTTP 请求,在 server 入口应该

// app/middleware/meta.js
module.exports = () => {
  return async function meta(ctx, next) {
    // 从 http header 获取 span 上下文
    const spanContext = ctx.tracer.extract('HTTP', ctx.header);
    // 创建 span 时指定父级 span
    const span = ctx.tracer.startSpan('http_server', { childOf: spanContext });
    await next();


比如发起一个 RPC 请求,需要在 RPC 客户端

const span = ctx.tracer.startSpan('rpcclient');
const rpcCarrier = {};
ctx.tracer.inject(span.context, 'RPC', rpcCarrier);
ctx.rpcclient.invoke(data, rpcCarrier);

定义 Carrier

上面使用到了 inject 和 extract 其实是需要这里提前定义的

// lib/http_carrier.js
module.exports = class HttpCarrier {
  inject(spanContext) {
    // 转换
    return header;
  extract(header) {
    // 转换
    return spanContext;

// config/config.default.js
exports.opentracing = {
  carrier: {
    'HTTP': require('../lib/http_carrier'),

定义 Collector


// lib/log_collector.js
module.exports = class LogColletor {
  collect(spanContext) {


// config/config.default.js
exports.opentracing = {
  collector: {
    log: require('../lib/log_collector'),


Egg 的 Tracer 和 Span 对象都是 opentracing 的一个实现,但你也可以通过覆盖的方式来实现。

// config/config.default.js
exports.opentracing = {
  globalTracer: YourTracer,


Zipkin, Dapper, HTrace, X-Trace


egg-mock is a mock server and a list of mocked API with egg-mock plugin.

  • mm.cluster
  • API
  • test with egg





loader 只提供原子粒度的 API,由框架来自行组织


  • getServerEnv
  • getEggPaths
  • getLoadUnits
  • getAppname

Low Level API

  • loadFile
  • loadToApp
  • loadToContext
  • loadExtend

High Level API

  • loadPlugin
  • loadConfig
  • loadController
  • loadMiddleware
  • loadApplicationExtend
  • loadContextExtend
  • loadRequestExtend
  • loadResponseExtend
  • loadHelperExtend
  • loadCustomApp
  • loadCustomAgent
  • loadService


插件需要用到 loader 功能需要增加一个 loader 插件,比如 db 的功能

|- app
  `- db
    `- a.js

新增 egg-loader-db 插件

// app.js
module.exports = function(loader) {
  app.loader.loadToApp('app/db', 'db');

db 插件直接依赖 egg-loader-db 插件

load unit

每个加载单元的目录结构都是类似的,框架、插件、应用的路径都是称为 loadDir。

|- app
  |- extend
  |- service
  |- controller
  |- middleware
  `- router.js
|- config
  |- config.js
  `- plugin.js
|- agent.js
`- app.js


  • directory: null,
  • target: null,
  • ignore: undefined,
  • lowercaseFirst: false,
  • initializer: null,
  • call: true,
  • override: false,
  • inject: undefined,


  • 去除 loading
  • app.js/agent.js 支持返回一个 promise #51
  • 调整 console
  • 去除 lib/core 潜规则?
  • 去除 eggPath 和 customEgg 参数
  • 增加 strict 模式 #52


egg-core 是包含了 loader 和应用初始化的功能,简单理解就是一个有目录约定的 koa,初始化包括了 loader。

  • loader
  • ready
  • logger
  • router

egg 就像其他框架一样只需要继承 egg-core 就可以直接使用


嗯, 只需提供一个机制给框架开发者扩展, 如集团那边是有 proxy, 其他开发者可以定义: -> app/db/xxx.js -> app/filters/xxx.js



类似 oss / mysql 等都可能存在需要创建多个实例的需求,在插件里面现在有两种实现方式:

  1. 新增一个 createInstance 方法来自定义创建。
  2. 配置支持数组形式,然后通过 this.mysql.db1 来获取

对外的插件最好有一个统一的形式。特别是 aliyun-egg 估计会遇到挺多类似的问题

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.