Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

egg-core的loadToApp不支持property存在就合并 #3528

Closed
zjlhope opened this issue Mar 11, 2019 · 27 comments
Closed

egg-core的loadToApp不支持property存在就合并 #3528

zjlhope opened this issue Mar 11, 2019 · 27 comments

Comments

@zjlhope
Copy link

zjlhope commented Mar 11, 2019

目前的实现是:
const target = this.app[property] = {};
希望的写法是:
const target = this.app[property] = this.app[property] || {};

为什么呢?
假如我要加载自定义文件夹里的controller,在app.js写上:
app.loader.loadController({
directory: path.join(app.config.baseDir 'app/gis')
})
那么后面应用加载controller就会冲掉这个app.controller,因为const target = this.app[property] = {};

为什么希望这样做?
我的框架是希望模块化更加彻底,每个模块负责定义自己的路由,自己的控制器,项目只要挂载他们就好了

@xingtian
Copy link

支持+1

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

你可以把原来的目录一起加载,directory 支持数组

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

你可以把原来的目录一起加载,directory 支持数组

你说的没错,但是loadController会调用loadToApp,loadToApp这句话
const target = this.app[property] = {};
会把我加的冲掉,最后只剩下应用自己的controller

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

你应该是提供一个配置,如 config.myLoader.controller.directory = [],然后在插件里面,一次性加载所有的,而不是多次调用 load。可以用 app.loader.loadUnits.map() 来获取所有的加载路径。

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

你应该是提供一个配置,如 config.myLoader.controller.directory = [],然后在插件里面,一次性加载所有的,而不是多次调用 load。可以用 app.loader.loadUnits.map() 来获取所有的加载路径。

我明白你的意思,上面我只是举个例子,主要是egg框架有个内部的loadController调用,它加载的app/controller下的,它是最后加载的,会将我不管哪种方式调用loadController的控制器清除掉,就是const target = this.app[property] = {};引起的

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

你调用的时机不对,看下生命周期的文档。

另外,最近有个 custom loader 的 RFC 也可以关注下,#3480

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

你调用的时机不对,看下生命周期的文档。

另外,最近有个 custom loader 的 RFC 也可以关注下,#3480

我是想在route.js被调用之前就注入controller,现在我是在app.js调用loadController的,请问哪个生命周期合适呢?
custom loader也不能满足哦,它本质上只是代码调用换成配置而已,假如我要写,那就如下:
module.exports = {
customLoader: {
// 定义在 app 上的属性名 app.adapter
controller: {
// 相对于 app.config.baseDir
directory: 'app/adapter',
// 如果是 ctx 则使用 loadToContext
inject: 'app',
// 是否加载框架和插件的目录
loadunit: false,
// 还可以定义其他 LoaderOptions
}
},
};
最后还是被框架的哪个loadController调用冲掉了,本质还是那一句

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

app.js 你放到 beforeStart 里面 (不过这个 API 有新的了,看看生命周期文档,应该在 configDidLoad 里面)

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

app.js 你放到 beforeStart 里面 (不过这个 API 有新的了,看看生命周期文档,应该在 configDidLoad 里面)

image
应该也是不行的

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

app.js 你放到 beforeStart 里面 (不过这个 API 有新的了,看看生命周期文档,应该在 configDidLoad 里面)

我现在是手动把node_modules里的那一句改了,才跑通的

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

提供最小可复现方式

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

非常简单的复现:
1.新建一个controller,不要放在app/controller目录下,比如放于:app/gis,命名为gis.js
2.应用的app.js写:
app.loader.loadController({
directory: path.join(app.config.baseDir 'app/gis')
}),
然后你的app/router.js里的controller得不到controller.gis这个控制器

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

都说了,app.js 里面放在 beforeStart 里面。

@egg-bot
Copy link

egg-bot commented Mar 11, 2019

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

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


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

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

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

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

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

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

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

代码复现

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

都说了,app.js 里面放在 beforeStart 里面。

我试了,不行哦,router.js还是没法获取到,被冲掉了

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

看,有复现代码库的话,就很快了。

// app/router.js
const path = require('path');

module.exports = app => {
  app.loader.loadController({
    directory: [
      path.join(app.config.baseDir, 'app/controller'),
      path.join(app.config.baseDir, 'app/gis'),
    ]
  });

  const { router, controller } = app;
  router.get('/', controller.home.isIOS);
  router.get('/config', controller.home.getConfig);
  router.get("/gis", controller.gis.transform);
};

@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

看,有复现代码库的话,就很快了。

// app/router.js
const path = require('path');

module.exports = app => {
  app.loader.loadController({
    directory: [
      path.join(app.config.baseDir, 'app/controller'),
      path.join(app.config.baseDir, 'app/gis'),
    ]
  });

  const { router, controller } = app;
  router.get('/', controller.home.isIOS);
  router.get('/config', controller.home.getConfig);
  router.get("/gis", controller.gis.transform);
};

可以了。居然这样玩就行了,想复杂了,非常感谢~~

@atian25
Copy link
Member

atian25 commented Mar 11, 2019

对着代码交流,沟通效率是最高的。

@atian25 atian25 closed this as completed Mar 11, 2019
@zjlhope
Copy link
Author

zjlhope commented Mar 11, 2019

对着代码交流,沟通效率是最高的。

受教了~~

@guohuihot
Copy link

guohuihot commented Sep 30, 2019

这个loadController控制器(加载框架里的,继承)能在当前项目loadController之前操作吗?因为想让当前项目的控制器可以覆盖框架的

@atian25
Copy link
Member

atian25 commented Sep 30, 2019

框架目前是没有 loadController 的。

如果你是在定制上层框架的话,就会涉及到 custom loader ,加载顺序你可以随便定义(建议不要放飞,避免跟社区不好兼容)

@guohuihot
Copy link

我看有提到“微服务”,了解了下,有点倾向于“微服务”的设计,egg有这方面的资料介绍吗?主要是微服务间的通信方式

@guohuihot
Copy link

框架目前是没有 loadController 的。

如果你是在定制上层框架的话,就会涉及到 custom loader ,加载顺序你可以随便定义(建议不要放飞,避免跟社区不好兼容)

另外关于你说的custom loader, 是在app上扩展还是framework上扩展,其实在此之前我是在framework上重写了下loader,但是在app里运行是,好像就不调用,所以现在不太清楚这个扩展要写在哪里?

@atian25
Copy link
Member

atian25 commented Sep 30, 2019

如果只是单纯的新增 loader,直接在 app 或 plugin 层面 可以用 config.customLoader 配置,参见 atian25/egg-showcase#13

如果你想深度定制 loader 的话,在 framework 层面可以继承 Loader 调整它内部的逻辑,在 egg loader 文档那里有提到。

@aCodeBaby
Copy link

@atian25 有个疑问,为什么loadController的实现中,directory没有对loadUnit做处理,而是直接写死了一个路径?这么做的考量和理由是?
比如service这里,就map了一下loadUnit的配置
directory: this.getLoadUnits().map(unit => path.join(unit.path, 'app/service')),
controller就直接是
directory: path.join(this.options.baseDir, 'app/controller'),

@atian25
Copy link
Member

atian25 commented Nov 19, 2019

因为 Controller 只支持应用级别

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants