我正在将一个相当大的打字稿项目从内部模块移动到外部模块。我这样做是因为我想创建一个核心捆绑包,如果需要,可以加载其他捆绑包。我要记住的第二个要求是,我希望能够在nodeJS服务器上运行捆绑包(如果需要,可以进行一些修改)。
我首先尝试使用AMD& require.js构建核心包,但我遇到了循环依赖的问题。在阅读了这与require.js相同之后,commonJS更经常被建议用于大型项目我尝试过。但是现在它与browserify一起设置了,当我运行编译的bundle时,我的完全相同的问题出现在完全相同的地方。
我有类似10个基类的东西,它们相互依赖并形成多个循环依赖。我没有看到任何方法来删除所有这些。
一个简化的设置来解释为什么我认为我不能删除循环依赖项:
Triples are made of 3 Resources (subject,predicate,object)
Resource has TripleCollections to keep track of which triples its used in
Resource has multiple functions which rely on properties of Triple
Triple has some functions which handle TripleCollections
TripleCollection has multiple functions which uses functions of Triple
TripleCollection.getSubjects() returns a ResourceCollection
ResourceCollection.getTriples() returns a TripleCollection
Resource keeps track of the objects of its triples in ResourceCollections
ResourceCollection uses multiple functions of Resource
我已经在SO上阅读了多个相关问题(this one最有帮助),而且从我可以收集到的内容中我只有几个选项:
1)将所有具有循环依赖关系的基类放在1个文件中。
这意味着它将成为一个文件的地狱。而且导入总是需要别名:
import core = require('core');
import BaseA = core.BaseA;
2)使用内部模块
当我使用内部打字稿模块和参考文件时,核心包工作正常(具有循环依赖性)。但是,如果我想在运行时创建单独的bundle并加载它们,我将不得不使用带有require.js的所有模块的填充程序。
虽然我不太喜欢所有别名,但我想我现在会尝试选项1,因为如果它可以工作,我可以继续使用CommonJS和browserify,稍后我也可以更轻松地在节点上运行服务器上的所有内容。如果1没有成功,我将不得不求助于选项2。
Q1:我有没有提到一些可能的解决方案?
第二季度:具有1个核心捆绑包的打字稿项目的最佳设置是什么,它根据需要加载其他捆绑包(构建在核心上)。这似乎无法绕过循环依赖。最好能在客户端和服务器上运行。或者我只是要求不可能的事情? :)
答案 0 :(得分:7)
简单地说(也许是简单的,但我不这么认为),如果你有ModuleA
和ModuleB
并且两者都相互依赖,那么它们就不是模块。它们位于不同的文件中,但它们不像 modules 。
在你的情况下,这些类是高度相互依赖的,你不能使用它们中的任何一个而不需要它们,所以除非你能重构程序以尝试单向依赖,而不是两个-way(例如),我会将这组类视为一个单独的模块。
如果你把所有这些放在一个单独的模块中,你可能仍然能够通过移动一些依赖关系将它分解为模块(并且所有这些问题都很大程度上是修辞的,因为它们是那种问题您需要问问自己),Triple
和Resource
相互分享的内容是什么?这可以转移到他们可以依赖的类中吗?为什么Triple
需要知道TripleCollection
(可能因为这代表了一些分层数据)?可能只有一些东西可以移动,但从当前设计中删除的任何依赖性都会降低复杂性。例如,如果可以删除Triple
和Resource
之间的双向关系。
可能您现在无法彻底改变此设计,在这种情况下,您可以将其全部放在一个模块中,这将在很大程度上解决模块加载问题,并且它还可以将代码保持在一起因为同样的原因而改变。
所有这些的摘要是:
如果您有双向模块依赖关系,请将其设为单向模块依赖关系。通过移动代码以一种方式实现依赖,或者将它们全部移动到一个更大的模块中,更诚实地表示模块之间的耦合。
因此,我对您选项的看法与您的问题略有不同......
1)尝试重构代码以减少耦合以查看是否可以保留较小的模块
失败了......
2)将所有具有循环依赖关系的基类放在1个文件中。
我不会将内部模块选项放在列表中 - 我认为外部模块是管理大型程序的更好方法。