I am currently in the process of transitioning a rather substantial TypeScript project from internal modules to external modules. The main reason behind this move is to establish a single core bundle that has the capability to load additional bundles if and when necessary. Additionally, I have the objective of ensuring that these bundles can also be executed on the server using NodeJS.
Initially, I attempted to build the core bundle using AMD and require.js, but encountered an issue with circular dependencies. Upon learning that such conflicts are common with require.js and that CommonJS is often recommended for large projects, I switched to that approach. However, even with browserify in place, I faced the exact same problem at the same point when executing the compiled bundle.
The project consists of approximately 10 base classes that heavily depend on each other, resulting in multiple circular dependencies. Despite efforts, it appears challenging to eliminate all instances of interdependence.
To clarify why eliminating circular dependencies seems unfeasible, consider the following simplified structure:
Triples consist of 3 Resources (subject, predicate, object)
Resource includes TripleCollections to track its usage in triples
Multiple functions within Resource rely on properties of Triple
Functions in Triple manage interactions with TripleCollections
TripleCollection features functions that utilize methods from Triple
Calling TripleCollection.getSubjects() returns a ResourceCollection
Invoking ResourceCollection.getTriples() provides a TripleCollection
Resources store objects of their triples in ResourceCollections
ResourceCollection employs various functions of Resource
After reviewing relevant discussions on SO (this source being particularly beneficial), it seems my options are limited to a few possibilities:
1) Consolidate base classes with circular dependencies into a single file.
This approach would result in one extensive file, requiring aliases for imports:
import core = require('core');
import BaseA = core.BaseA;
2) Utilize internal modules
While the core bundle functioned adequately (despite circular dependencies) using internal TypeScript modules and reference files, creating separate bundles for runtime loading will necessitate shims for all modules using require.js.
Although I am not fond of excessive aliasing, I intend to pursue option 1 initially. If successful, I can proceed with CommonJS and browserify, facilitating potential execution on the server via Node at a later stage. Should option 1 prove ineffective, option 2 will be considered as an alternative.
Q1: Are there any potential solutions I may have overlooked?
Q2: What constitutes the optimal setup for a TypeScript project featuring a core bundle that dynamically loads additional bundles (which support the core) upon request? Given the existence of circular dependencies, along with the requirement for cross-platform compatibility, what configuration would best serve these requirements?
Alternatively, am I attempting the implausible? :)