Egg: Symbol.for('egg#eggPath') is required on Application

Created on 4 Apr 2019  ·  22Comments  ·  Source: eggjs/egg

What happens?

业务代码使用TS,引入框架,npm run dev 告警。

复现步骤,错误日志以及相关配置

AssertionError [ERR_ASSERTION]: Symbol.for('egg#eggPath') is required on Application
    at EggLoader.getEggPaths (/Users/ronesam/Sites/Tugou/Egg/oa.citytogo.cn/node_modules/egg-core/lib/loader/egg_loader.js:267:7)
    at new EggLoader (/Users/ronesam/Sites/Tugou/Egg/oa.citytogo.cn/node_modules/egg-core/lib/loader/egg_loader.js:72:26)
    at getLoader (/Users/ronesam/Sites/Tugou/Egg/oa.citytogo.cn/node_modules/egg-bin/node_modules/egg-ts-helper/src/scripts/eggInfo.ts:71:10)
    at Object.<anonymous> (/Users/ronesam/Sites/Tugou/Egg/oa.citytogo.cn/node_modules/egg-bin/node_modules/egg-ts-helper/src/scripts/eggInfo.ts:19:16)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)

相关环境信息

  • 操作系统:Mac OS 10.14.4
  • Node 版本:v10.15.3
  • Egg 版本:2.6.1
need-more-information

Most helpful comment

我也遇上这个问题,经过一番 debug,定位到问题所在,希望对遇到相同场景的人有所帮助。

必现路径

  1. 封装了一个 Egg Framework - myFramework,执行 yarn link
  2. 在项目中 yarn link myFramework 测试
  3. 本地启动项目 yarn dev
  4. Get the error!

定位问题 🕵️‍♂️

  1. 搜索源代码,找到报错的位置egg-core
getEggPaths() {
    while (proto) {
      proto = Object.getPrototypeOf(proto);
      if (proto === Object.prototype || proto === EggCore.prototype) {
        break;
      }

      assert(proto.hasOwnProperty(Symbol.for('egg#eggPath')), 'Symbol.for(\'egg#eggPath\') is required on Application');
      ...
    }
  }
  1. 在 assert 前添加 console 打印 proto,依次得到 Application.prototype, EggApplication.prototype, EggCore.prototype。所以报错前一刻,proto 是 EggCore.prototype 🤔🤔🤔

  2. 往前回溯,找到 egg-ts-helper 中加载 framework 的代码。egg-ts-helper

function getLoader(baseDir: string, framework: string) {
  const frameworkPath = path.join(baseDir, 'node_modules', framework);
   //...
  const egg = utils.requireFile(frameworkPath) || utils.requireFile(framework);

  return new EggLoader({
    //...
    app: Object.create(egg.Application.prototype),
  });
}

在我的 💻 上utils.requireFile 那段代码最终执行的 frameworkPath/Users/User/p/myFramework(不是项目路径下)。到这里,问题就很清晰了。

问题所在

link framework 启动之后,项目使用的 egg-coremyFramework 使用的 egg-core 不是同一个包。

   /node_modules
       /egg-core
framework
   /node_modules
       /egg-core

导致最终得到的 EggCore.prototype 不相等(打印出来 proto 确实是 EggCore.prototype,来自两个都叫EggCore的对象的 prototype)

All 22 comments

提供最小可复现仓库

Hello @ronesam. Please provide a reproducible example following the instruction.

Issues labeled by Need Reproduce will be closed if no activities in 7 days.


@ronesam,请根据这个说明提供最小可复现代码。

如果在 7 天内没有进展会被自动关闭。

hey, we need more information to follow up this issue, recommend to use egg-init --type=simple to provide a mini project and upload to your github.

for now it will close due to lack of activity, feel free to reopen this issue if provided more information.

我也遇上这个问题,经过一番 debug,定位到问题所在,希望对遇到相同场景的人有所帮助。

必现路径

  1. 封装了一个 Egg Framework - myFramework,执行 yarn link
  2. 在项目中 yarn link myFramework 测试
  3. 本地启动项目 yarn dev
  4. Get the error!

定位问题 🕵️‍♂️

  1. 搜索源代码,找到报错的位置egg-core
getEggPaths() {
    while (proto) {
      proto = Object.getPrototypeOf(proto);
      if (proto === Object.prototype || proto === EggCore.prototype) {
        break;
      }

      assert(proto.hasOwnProperty(Symbol.for('egg#eggPath')), 'Symbol.for(\'egg#eggPath\') is required on Application');
      ...
    }
  }
  1. 在 assert 前添加 console 打印 proto,依次得到 Application.prototype, EggApplication.prototype, EggCore.prototype。所以报错前一刻,proto 是 EggCore.prototype 🤔🤔🤔

  2. 往前回溯,找到 egg-ts-helper 中加载 framework 的代码。egg-ts-helper

function getLoader(baseDir: string, framework: string) {
  const frameworkPath = path.join(baseDir, 'node_modules', framework);
   //...
  const egg = utils.requireFile(frameworkPath) || utils.requireFile(framework);

  return new EggLoader({
    //...
    app: Object.create(egg.Application.prototype),
  });
}

在我的 💻 上utils.requireFile 那段代码最终执行的 frameworkPath/Users/User/p/myFramework(不是项目路径下)。到这里,问题就很清晰了。

问题所在

link framework 启动之后,项目使用的 egg-coremyFramework 使用的 egg-core 不是同一个包。

   /node_modules
       /egg-core
framework
   /node_modules
       /egg-core

导致最终得到的 EggCore.prototype 不相等(打印出来 proto 确实是 EggCore.prototype,来自两个都叫EggCore的对象的 prototype)

@HelKyle 感谢反馈和分享。
@whxaxes 看看

目前是会有这个问题,因为 link 过来后导致存在了两个 egg-core ,这个暂时没想到啥解决方案,除非去干涉 require 的行为,就有点 hack 了

@whxaxes
如果循环条件放松一些,改成 proto === Object.prototype || proto === EggCore.prototype || proto.constructor.name === 'EggCore' 可行吗?

link 之后把你框架下面的 egg-core 删了

@popomore 不行吧,/Users/User/p/myFramework/ 下的 js require('egg') 会报错。因为找不到 egg-core

egg 里面 require 的 egg-core 应该在 egg 项目里面有

我删除了 framework 下面的 node_modules 启动项目会提示我 egg module 不存在。从表现上看,yarn link 创建了软链,实际 require 时是按照 /framework 路径去查找 module 而不是 /project/node_modules/framework/ ?不知道我理解的对不对。

   /node_modules
       /egg-core
framework
   /node_modules
       /egg-core

+1
这个问题难道之前没人遇到吗?

最后这个问题是如何解决的呢?

如果只是 link 的时候报错,可以临时修改本地代码先用着:
proto === Object.prototype || proto === EggCore.prototype || proto.constructor.name === 'EggCore'

可以全局安装egg-core,project和framework里的egg-core都link到全局的那个

proto === Object.prototype || proto === EggCore.prototype || proto.constructor.name === 'EggCore'

这个谁pr一下,唉

+1

+1

这个感觉需要reopen,毕竟对于团队来说,framework 开发是非常有必要的。yarn link的友好支持,肯定对这个更有帮助。

+1

我也遇到了

遇到了+1。用这个判断临时修改下
proto === Object.prototype || proto === EggCore.prototype || proto.constructor.name === 'EggCore'

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yuu2lee4 picture yuu2lee4  ·  3Comments

whlsxl picture whlsxl  ·  3Comments

kylezhang picture kylezhang  ·  3Comments

lvgg3271 picture lvgg3271  ·  3Comments

weijiatan456 picture weijiatan456  ·  3Comments