Summary
createAngularEsbuildContext receives and normalizes the Angular tsConfigPath, and passes it to the Angular compiler plugin, but it does not pass that path to the esbuild.BuildOptions object used by esbuild.context.
As a result, esbuild's own resolver does not honor baseUrl/paths from the configured Angular tsconfig for imports that esbuild resolves outside the Angular compiler program. Builds then depend on esbuild's automatic discovery of a file named exactly tsconfig.json, which does not cover common Angular/Nx layouts using tsconfig.app.json and tsconfig.lib.json.
This is the v4 equivalent of angular-architects/module-federation-plugin#848.
Affected version
native-federation/angular-adapter v22.0.6
- Current
main: 2221011563edb2ea5b0afa1003e6895b54e9e356
The failure was reproduced against the historical Angular adapter in @angular-architects/native-federation 21.2.5. Source inspection shows the same omission in v22.0.6.
Reproduction shape
Use an Angular/Nx workspace with:
-
An application configured with tsConfig: apps/example/tsconfig.app.json.
-
Path mappings in a base config, for example:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"example/contracts": ["libs/example/contracts/src/index.ts"]
}
}
}
-
A workspace library with tsconfig.lib.json but no ancestor file named exactly tsconfig.json containing the same mappings.
-
A transitive value import from that library to example/contracts.
-
A Native Federation production build.
The federation artefact build can fail with:
Could not resolve "example/contracts"
Adding a conveniently placed tsconfig.json, or patching the adapter to pass the configured tsconfig to esbuild, makes the same build succeed.
Root cause
src/tools/esbuild/angular-bundler.ts already normalizes the configured path:
tsConfigPath = path.join(workspaceRoot, tsConfigPath);
It also passes it to CompilerPluginOptions:
const pluginOptions: CompilerPluginOptions = {
tsconfig: tsConfigPath,
// ...
};
However, the separate config: esbuild.BuildOptions passed to esbuild.context(config) has no tsconfig property. Angular's compiler plugin uses onLoad, while static import resolution still goes through esbuild, so configuring only the compiler plugin is insufficient.
Proposed fix
Pass the already-normalized absolute path to esbuild as well:
const config: esbuild.BuildOptions = {
// ...
resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'],
+ tsconfig: tsConfigPath,
};
Suggested regression test
- Capture/mock the argument passed to
esbuild.context.
- Assert that
BuildOptions.tsconfig equals the normalized absolute tsConfigPath.
- Ideally include a fixture where an application uses
tsconfig.app.json, a library uses tsconfig.lib.json, and a transitive value import relies on a root path mapping.
I can prepare a focused PR if this approach is accepted.
Summary
createAngularEsbuildContextreceives and normalizes the AngulartsConfigPath, and passes it to the Angular compiler plugin, but it does not pass that path to theesbuild.BuildOptionsobject used byesbuild.context.As a result, esbuild's own resolver does not honor
baseUrl/pathsfrom the configured Angular tsconfig for imports that esbuild resolves outside the Angular compiler program. Builds then depend on esbuild's automatic discovery of a file named exactlytsconfig.json, which does not cover common Angular/Nx layouts usingtsconfig.app.jsonandtsconfig.lib.json.This is the v4 equivalent of angular-architects/module-federation-plugin#848.
Affected version
native-federation/angular-adapterv22.0.6main:2221011563edb2ea5b0afa1003e6895b54e9e356The failure was reproduced against the historical Angular adapter in
@angular-architects/native-federation21.2.5. Source inspection shows the same omission in v22.0.6.Reproduction shape
Use an Angular/Nx workspace with:
An application configured with
tsConfig: apps/example/tsconfig.app.json.Path mappings in a base config, for example:
{ "compilerOptions": { "baseUrl": ".", "paths": { "example/contracts": ["libs/example/contracts/src/index.ts"] } } }A workspace library with
tsconfig.lib.jsonbut no ancestor file named exactlytsconfig.jsoncontaining the same mappings.A transitive value import from that library to
example/contracts.A Native Federation production build.
The federation artefact build can fail with:
Adding a conveniently placed
tsconfig.json, or patching the adapter to pass the configured tsconfig to esbuild, makes the same build succeed.Root cause
src/tools/esbuild/angular-bundler.tsalready normalizes the configured path:It also passes it to
CompilerPluginOptions:However, the separate
config: esbuild.BuildOptionspassed toesbuild.context(config)has notsconfigproperty. Angular's compiler plugin usesonLoad, while static import resolution still goes through esbuild, so configuring only the compiler plugin is insufficient.Proposed fix
Pass the already-normalized absolute path to esbuild as well:
const config: esbuild.BuildOptions = { // ... resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'], + tsconfig: tsConfigPath, };Suggested regression test
esbuild.context.BuildOptions.tsconfigequals the normalized absolutetsConfigPath.tsconfig.app.json, a library usestsconfig.lib.json, and a transitive value import relies on a root path mapping.I can prepare a focused PR if this approach is accepted.