npm run dev
创建 egg 实例
- 继承链
Application extends EggApplication extends EggCore extends KoaApplication
// 1.super KoaApplication
拥有koa的属性方法:
1. middleWare
2. use
3. listen
/*
1. baseDir 项目路径
2. BaseContextClass(基类)
3. 实例化生命周期
4. 实例化loader
*/
constructor(options = {}) {
options.baseDir = options.baseDir || process.cwd();
this.BaseContextClass = BaseContextClass;
this.lifecycle = new Lifecycle({
baseDir: options.baseDir,
app: this
})
this.loader = new Loader({
baseDir: options.baseDir,
app: this,
env: options.env,
})
}
// 生命周期实例
this[BOOT_HOOKS] = []
this[BOOTS] = []
ready this.triggerWillReady()
ready this.triggerDidReady()
// loader实例记录了很多信息
// package.json对象 环境变量 项目信息(name baseDir env)
constructor(options) {
this.pkg = utility.readJSONSync(path.join(this.options.baseDir, 'package.json'));
this.serverEnv = this.getServerEnv();
this.eggPaths = this.getEggPaths() // 继承
this.appInfo = this.getAppInfo();
}
// super EggCore
constructor(options = {}) {
super(options);
this.ContextCookies = ContextCookies;
this.ContextLogger = ContextLogger;
this.ContextHttpClient = ContextHttpClient;
this.HttpClient = HttpClient;
this.loader.loadConfig();
}
// 加载插件 loadPlugin
// this.orderPlugins 依赖的所有的插件
{
p1: { enable: true, path, dependencies },
p2: { enable: true, path, dependencies },
}
this.getLoadUnits() // 根据orderPlugins返回的插件数组,最后一个是 app
{
path: plugin.path,
type: 'plugin',
}
{
path: baseDir,
type: 'app'
}
loadConfig() {
this.configMeta = {};
const target = {};
// 根据环境变量 加载项目的 config.default config.dev
const appConfig = this._preloadAppConfig();
// 按照所有插件 -> app
for (const filename of this.getTypeFiles('config')) {
for (const unit of this.getLoadUnits()) {
const isApp = unit.type === 'app';
// 插件的config文件的函数的参数 appInfo appconfig
const config = this._loadConfig(unit.path, filename, isApp ? undefined : appConfig, unit.type);
extend(true, target, config);
}
}
// 配置定义的中间件
target.coreMiddleware = target.coreMiddlewares = target.coreMiddleware || [];
target.appMiddleware = target.appMiddlewares = target.middleware || [];
// 得到最终的配置
this.config = target;
}
loadExtend(name, proto) {
// app/extend/application
const filepaths = this.getExtendFilePaths(name);
for (let filepath of filepaths) {
// 抛出对象
const ext = this.requireFile(filepath);
const properties = Object.getOwnPropertyNames(ext)
Object.defineProperty(proto/* app */, property, descriptor)
}
}
loadApplicationExtend this.app
loadRequestExtend this.app.request
loadResponseExtend
this.loadContextExtend() this.app.context
this.loadHelperExtend()
if (this.app && this.app.Helper) {
this.loadExtend('helper', this.app.Helper.prototype);
}
this.loadCustomLoader()
this.loadCustomApp()
1. 执行所有插件的 app 文件,项目app文件 将类存进 lifecycle 的 hooks中,这里注意如果导出的是一个函数:
class Hook {
constructor(app) {
this.app = app;
}
configDidLoad() {
hook(this.app) // 函数
}
}
2. 同步执行所有插件的 configWillLoad configDidLoad (config其实已经在上面设置了)
triggerConfigWillLoad() {
for (const boot of this[BOOTS]) {
boot.configWillLoad();
}
this.triggerConfigDidLoad();
}
triggerConfigDidLoad() {
for (const boot of this[BOOTS]) {
boot.configDidLoad()
}
this.triggerDidLoad();
}
3. process.nextTick 执行 didload(异步async)
then -> willReady(异步)-> 盲猜这里进行了listen(也就是项目启动了)-> then -> didReady
4. this.loadService() // 解析service下的文件丰富ctx,BaseContextClass在这体现
5. this.loadMiddleware(); // (this.config[name]/* config里面配置的中间件的信息 */) => (ctx, next) => {}
执行 use
先是插件中间件,然后是项目的中间件;
6. this.loadController()
7. this.loadRouter(); // router.js