从egg-helper开发中学习egg源码

开发helper插件目的所有的工具函数维护在 app/util 文件内,在使用时需要手动require,如果多个文件使用,需要多个require,致使业务代码实现不优雅在工具函数内部无法直接读取配置文件,通常是使用传参的方式Egg也提供Helper框架扩展,但是需将工具函数维护在 app/extend/helper.js 文件内,我更倾向于单独维护开发经历初始版 loadToCon...
摘要由CSDN通过智能技术生成

开发egg-helper插件目的

  • 所有的工具函数维护在 app/util 文件内,在使用时需要手动require,如果多个文件使用,需要多个require,致使业务代码实现不优雅
  • 在工具函数内部无法直接读取配置文件,通常是使用传参的方式
  • Egg也提供Helper框架扩展,但是需将工具函数维护在 app/extend/helper.js 文件内,我更倾向于单独维护

开发经历

第一版

使用egg官方文档提供的loadToContext方法,将 app/helper 内所有文件挂载到ctx.helper对象
loadToContext官方文档,请戳这里

代码实现

// --------egg-helper/app.js -------
module.exports = app => {
  const dir = app.loader.getLoadUnits().map(unit => {
    return path.join(unit.path, 'app/helper');
  });
  app.loader.loadToContext(dir, 'helper', {
    inject: app,
    call: true,
  });
};
...

缺点:

  • 覆盖掉原有的ctx.helper对象(这里可以选择修改挂载属性名称来避免覆盖,但为了和egg保持一致,所以未选择此方案)

源码学习

打开egg-core工程,根据package.json找到入口文件

...
// -------- egg-core/index.js -------
module.exports = {
  EggCore, 
  EggLoader,
  BaseContextClass,
  utils,
};

在index.js文件内,export出四个对象
EggCore:
egg核心类

  • 继承于koa Application
  • 初始化egg Application的对象方法和属性
// -------- egg-core/lib/egg.js -------
...
class EggCore extends KoaApplication {
  constructor() {
    ...
    const Loader = this[EGG_LOADER];
    assert(Loader, "Symbol.for('egg#loader') is required");
    this.loader = new Loader({  // 实例化loder,即EggLoader
      baseDir: options.baseDir,
      app: this, 
      plugins: options.plugins,
      logger: this.console,
      serverScope: options.serverScope,
    });
    const Controller = this.BaseContextClass;
    this.Controller = Controller; // 定义Controller使用基类
    const Service = this.BaseContextClass;
    this.Service = Service; // 定义Service使用基类
    ...
  }
}
...

EggLoader:
egg-core核心类

  • 提供load方法,例如loadToContext、loadToApp
  • 提供获取egg基础信息方法和属性,例如 getAppInfo
  • 挂载 /lib/loader/mixin目录下定义的load函数,具体加载顺序在 egg/lib/loader/appworkerloader.js中定义
// -------- egg-core/lib/loader/egg_loader.js -------
class EggLoader {
  ...
  // 将property挂载到ctx
  loadToContext(directory, property, opt) {
     opt = Object.assign({}, {
       directory,
       property,
       inject: this.app,
     }, opt);
 
     const timingKey = `Load "${String(property)}" to Context`;
     this.timing.start(timingKey);
     new ContextLoader(opt).load(); // 实例化ContextLoader
     this.timing.end(timingKey);
  },
  // 获取当前 应用/框架/插件下所有文件路径,返回路径数组
  getLoadUnits() {
    if (this.dirs) {
      return this.dirs;
    }
    const dirs = this.dirs = [];
    // 插入插件路径
    if (this.orderPlugins) {
      for (const plugin of this.orderPlugins) {
        dirs.push({
          path: plugin.path,
          type: 'plugin',
        });
      }
    }
    // 插入框架路径
    for (const eggPath of this.eggPaths) {
      dirs.push({
        path: eggPath,
        type: 'framework',
      });
    }
    // 插入当前应用路径
    dirs.push({
      path: this.options.baseDir,
      type: 'app',
    });
    debug('Loaded dirs %j', dirs);
    return dirs;
  }
 }
...
const loaders = [
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值