排查问题
Import scripts of redi more than once
[redi]: You are loading scripts of redi more than once! This may cause undesired behavior in your application. Maybe your dependencies added redi as its dependency and bundled redi to its dist files. Or you import different versions of redi.
这个错误的含义是你加载了多次 redi 的代码。这个错误的原因可能是以下其中一种:
- 你引入的包也依赖了
@wendellhu/redi
,但是它们没有将 redi 设置为外部依赖,而是将 redi 打包到了它们的 dist 文件中 - 你引入的包依赖的
@wendellhu/redi
和你自己安装的redi
版本不一致 - 你在一个 monorepo 中工作,repo 使用了不同版本的 redi
redi 在内部使用了 Symbol
和 instanceof
。所以当你加载了多次 redi 的代码时,redi 会无法正常运行。
为了解决这个问题,你可以采取以下办法:
- 联系这些包的维护者,让他们将
@wendellhu/redi
设置为外部依赖 - 这些包的维护者可能重新导出了 redi 的 API,这种情况下请使用这些 API 而不要直接使用 redi
- 在你的 monorepo 中使用相同的 redi 版本
Could not find dependency registered on
[redi]: It seems that you register “undefined” as dependency on the X parameter of “XXX”. Please make sure that there is not cyclic dependency among your TypeScript files, or consider using “forwardRef”.
当 redi 试图弄清楚某个类 XXX
依赖于哪些依赖项时,发现某个依赖项被解析为 undefined
,就会抛出这个错误。发生这个错误的原因大致如下:
我们假设这个依赖项是 YYY
,
YYY
一定是一个类- tsc 编译 TypeScript 到 JavaScript 时,
YYY
标识符先被声明,稍后才会被赋值上YYY
的构造函数 - 在 TypeScript 文件之间存在循环依赖,导致当
Inject
装饰器视图在XXX
上记录依赖关系时,YYY
还没有被赋值
为了解决这个问题,你可以使用 forwardRef
,这会导致对 YYY
的取值过程延后到构建 XXX
的实例时,从而避免这个问题:
import { Inject, forwardRef } from "@wendellhu/redi";
class XXX {
constructor(@Inject(forwardRef(() => YYY)) private readonly _yyy: YYY) {}
}
更加推荐的做法是解除文件之间的循环依赖。推荐使用 dpdm 来查找文件直接的依赖关系。你可以从 XXX
所在文件开始遍历依赖关系,然后把包含这个文件的循环依赖打破。