Egg: [Feature Request] egg支持monorepo项目结构开发

Created on 6 May 2019  ·  17Comments  ·  Source: eggjs/egg

Background

很多前端项目是通过yarn workspace以monorepo方式搭建的,方便node module的管理。
对中台egg app和plugin的开发集中到一个monorepo里维护会方便些。

Proposal

egg-bin和egg-script提供--module-dir参数,用于声明monorepo的node_modules目录位置,默认为{process.cwd}/node_modules,framework将基于该参数路径查找egg和egg-plugin

Most helpful comment

目前在 yarn workspace 下确实会提示各种找不到库。

我看到目前的代码很多是通过在各种 node_modules 目录下查找来确定是否有依赖,包括 midway 团队那边也是这么写的。

而在 monorepo 的情况下,lerna 或者 yarn workspace 大都会把依赖统一放在 root dir 的 node_modules 里,虽然在单个 workspace 内部的 node_modules 中找不到,但是在 root dir 中是有的。可以考虑增加一个类似 require.resolve() 的方式去进一步查找。

我简单试了一下,对于 egg-utils/lib/framework.js 的相关代码:https://github.com/eggjs/egg-utils/blob/d8072dbd145832bf712762324591bd0ebe34ff85/lib/framework.js#L52-L67

加了个尝试通过 require.resolve() 查找后,问题解决了,可以作为参考:

const moduleDirs = new Set([
  moduleDir,
  // find framework from process.cwd, especially for test,
  // the application is in test/fixtures/app,
  // and framework is install in ${cwd}/node_modules
  path.join(process.cwd(), 'node_modules'),
  // prevent from mocking process.cwd
  path.join(initCwd, 'node_modules'),
]);

try {
  const test = path.join(require.resolve(`${frameworkName}/package.json`), '../..')
  moduleDirs.add(test);
} catch (e) {}

@popomore 另外,我倒是觉得 issue 的问题确实存在的话,就这么直接关了的确不好。贴上 discussion 或者 need help 之类的可能是更好的解决方式。

All 17 comments

若项目结构为

└ packages
    ├ mono-a (egg-bin)
    └ mono-b

设置egg-bin dev --module-dir=../../node_modules,应在base/packages/mono-a/node_modules和base/node_modules下查找framework和plugin

用 lerna 试试,有问题再问。如果只是 app 和 plugin,那可以用 path 来指定插件路径和 app 平级。

@popomore 尝试了yarn和lerna都不行,封装framework也不行,egg-bin启动就会报路径找不到后退出。看了下代码egg-utils\lib\framework.js:line 26 位置指明baseDir和node_modules拼接,没有办法通过assertAndReturn检查,是否可以把node_modules改成cli参数,可由用户指定node_modules路径?

function getFrameworkPath({ framework, baseDir }) {
  const pkgPath = path.join(baseDir, 'package.json');
  assert(fs.existsSync(pkgPath), `${pkgPath} should exist`);

  const moduleDir = path.join(baseDir, 'node_modules');
  const pkg = utility.readJSONSync(pkgPath);

  // 1. pass framework or customEgg
  if (framework) {
    // 1.1 framework is an absolute path
    // framework: path.join(baseDir, 'node_modules/${frameworkName}')
    if (path.isAbsolute(framework)) {
      assert(fs.existsSync(framework), `${framework} should exist`);
      return framework;
    }
    // 1.2 framework is a npm package that required by application
    // framework: 'frameworkName'
    return assertAndReturn(framework, moduleDir);
  }
 ...

cd 到应用目录应该可以

遇到同样的问题,采用yarn workspace方式,egg项目无法运行
报错 Error: egg is not found

same issue here.

issues明明都没解决,怎么就关了? 这就是阿里清issue的方式咩

不要道德绑架,我们本身不用单库,无法处理这个问题,我只是给出建议。好的开源方式是提出解决方案,或直接提 PR,而不是把开源团队当外包。

目前在 yarn workspace 下确实会提示各种找不到库。

我看到目前的代码很多是通过在各种 node_modules 目录下查找来确定是否有依赖,包括 midway 团队那边也是这么写的。

而在 monorepo 的情况下,lerna 或者 yarn workspace 大都会把依赖统一放在 root dir 的 node_modules 里,虽然在单个 workspace 内部的 node_modules 中找不到,但是在 root dir 中是有的。可以考虑增加一个类似 require.resolve() 的方式去进一步查找。

我简单试了一下,对于 egg-utils/lib/framework.js 的相关代码:https://github.com/eggjs/egg-utils/blob/d8072dbd145832bf712762324591bd0ebe34ff85/lib/framework.js#L52-L67

加了个尝试通过 require.resolve() 查找后,问题解决了,可以作为参考:

const moduleDirs = new Set([
  moduleDir,
  // find framework from process.cwd, especially for test,
  // the application is in test/fixtures/app,
  // and framework is install in ${cwd}/node_modules
  path.join(process.cwd(), 'node_modules'),
  // prevent from mocking process.cwd
  path.join(initCwd, 'node_modules'),
]);

try {
  const test = path.join(require.resolve(`${frameworkName}/package.json`), '../..')
  moduleDirs.add(test);
} catch (e) {}

@popomore 另外,我倒是觉得 issue 的问题确实存在的话,就这么直接关了的确不好。贴上 discussion 或者 need help 之类的可能是更好的解决方式。

@meteorlxy 给 egg-utils 提个 PR 吧

同样遇到一样的问题,Any updates?

yarn workspace可以暂时用yarn的nohoist

除了nohoist的方式,可以用hack的方式进行解决。如果不想因为egg的问题修改yarn workspace的工作方式,可采用如下方案:

  • egg启动提供了--framework的参数,可以通过传递这个参数,手动指定egg package所在的位置,例如:--framework ../../../node_modules/egg
  • 使用framework启动后,plugin的package resolve会有问题。可通过查看源码发现,如果plugin的使用声明中,包含path字段,例如:
const validate = {
    enable: true,
    package: 'egg-validate',
    path: path.resolve('...', 'egg-validate')
  }

会直接使用path字段中指定的包路径,而不是使用egg自己的plugin resolve机制。

注意: 这里需要同时对自己添加的插件和egg默认的插件均进行此操作,egg默认的插件列表在egg/config/plugin.js文件中

另外,问题出现的原因是egg并未考虑到mono-repopackage安装方式,并且package的resolve的参数都是写死的。建议对此修改,如果暂时没有人力支持,也可提供临时的解决办法。而不是直接关issue。感谢~

@atom-yang 感谢分享。

但从我们的角度来看,没有 get 到 mono-repo 方式的场景,也因此无法 support。

平时维护的 egg 插件也都上百个了,还真没遇到什么场景需要把很多个插件在一个 Git 仓库里面维护的情况。在我们的视角看来,插件都应该是独立可测试的,放在一个仓库容易导致耦合。

这个不是用不用 mono-repo 的问题,而是 framework 和 plugin 寻址的问题,既然 egg 允许 framework 和 plugin 发布 npm 包,就应该遵循 node_modules 的寻址方式,而不是自己内部单独搞一套。

@atian25

any updates? And I think you should reopen this issue @popomore.

目前在 yarn workspace 下确实会提示各种找不到库。

我看到目前的代码很多是通过在各种 node_modules 目录下查找来确定是否有依赖,包括 midway 团队那边也是这么写的。

而在 monorepo 的情况下,lerna 或者 yarn workspace 大都会把依赖统一放在 root dir 的 node_modules 里,虽然在单个 workspace 内部的 node_modules 中找不到,但是在 root dir 中是有的。可以考虑增加一个类似 require.resolve() 的方式去进一步查找。

我简单试了一下,对于 egg-utils/lib/framework.js 的相关代码:https://github.com/eggjs/egg-utils/blob/d8072dbd145832bf712762324591bd0ebe34ff85/lib/framework.js#L52-L67

加了个尝试通过 require.resolve() 查找后,问题解决了,可以作为参考:

const moduleDirs = new Set([
  moduleDir,
  // find framework from process.cwd, especially for test,
  // the application is in test/fixtures/app,
  // and framework is install in ${cwd}/node_modules
  path.join(process.cwd(), 'node_modules'),
  // prevent from mocking process.cwd
  path.join(initCwd, 'node_modules'),
]);

try {
  const test = path.join(require.resolve(`${frameworkName}/package.json`), '../..')
  moduleDirs.add(test);
} catch (e) {}

@popomore 另外,我倒是觉得 issue 的问题确实存在的话,就这么直接关了的确不好。贴上 discussion 或者 need help 之类的可能是更好的解决方式。

随着问的人越来越多,lerna 的使用也越发广泛,这个问题在 midway v1/v2 都已经处理,可以放心使用。https://github.com/midwayjs/midway/pull/751

Was this page helpful?
0 / 5 - 0 ratings