From 9debc7f18cf73fbac46f94c47a85becfa076f36c Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:37:06 +0000 Subject: [PATCH] fix(@angular/build): respect tsconfig declarationMap and compilationMode in library builder Remove schema defaults for `declarationMap` and `compilationMode` in `@angular/build:library` and preserve `declarationMap` when reading TypeScript configuration for library builds so values configured in `tsconfig.lib.json` / `tsconfig.lib.prod.json` are respected unless explicitly overridden in `angular.json`. --- .../projects/lib/tsconfig.lib.json | 1 - .../build/src/builders/library/options.ts | 4 +- .../builders/library/pipeline/build-action.ts | 25 ++++++++-- .../src/builders/library/pipeline/bundler.ts | 4 +- .../builders/library/pipeline/compilation.ts | 10 +++- .../build/src/builders/library/schema.json | 6 +-- .../tests/options/compilation-mode_spec.ts | 48 +++++++++++++++++++ .../tests/options/declaration-map_spec.ts | 38 +++++++++++++++ .../build/src/builders/library/types.ts | 7 ++- .../compilation/angular-compilation.ts | 1 + .../angular/compilation/compiler-options.ts | 6 ++- .../angular/compilation/parallel-worker.ts | 1 + .../compilation/typescript-compilation.ts | 8 +++- 13 files changed, 141 insertions(+), 18 deletions(-) diff --git a/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json b/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json index fe12470400e2..23e851ac9c8b 100644 --- a/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json +++ b/modules/testing/builder/projects/hello-world-lib/projects/lib/tsconfig.lib.json @@ -2,7 +2,6 @@ "extends": "../../tsconfig.json", "compilerOptions": { "declaration": true, - "declarationMap": true, "inlineSources": true, "types": [] }, diff --git a/packages/angular/build/src/builders/library/options.ts b/packages/angular/build/src/builders/library/options.ts index 450dce36cab5..c90fd525e1f2 100644 --- a/packages/angular/build/src/builders/library/options.ts +++ b/packages/angular/build/src/builders/library/options.ts @@ -38,8 +38,8 @@ export async function normalizeLibraryOptions( assets: rawAssets, stylePreprocessorOptions, inlineStyleLanguage = 'css', - compilationMode = 'partial', - declarationMap = false, + compilationMode, + declarationMap, allowedNonPeerDependencies: rawAllowedNonPeerDependencies = [], keepLifecycleScripts = false, watch = false, diff --git a/packages/angular/build/src/builders/library/pipeline/build-action.ts b/packages/angular/build/src/builders/library/pipeline/build-action.ts index 19718a793deb..294eb954421b 100644 --- a/packages/angular/build/src/builders/library/pipeline/build-action.ts +++ b/packages/angular/build/src/builders/library/pipeline/build-action.ts @@ -124,6 +124,8 @@ export async function buildAction(actionContext: BuildActionContext): Promise; + + /** Effective declarationMap setting resolved from builder options and tsconfig. */ + readonly declarationMap: boolean; + + /** Effective compilationMode setting resolved from builder options and tsconfig. */ + readonly compilationMode: 'partial' | 'full'; } /** @@ -125,7 +131,7 @@ export async function compileLibrary( processWebWorker: () => '', }; - const { referencedFiles } = await compilationInstance.initialize( + const { referencedFiles, compilerOptions } = await compilationInstance.initialize( tsConfigPath, hostOptions, { @@ -220,6 +226,8 @@ export async function compileLibrary( failedFiles: failedFiles.size > 0 ? failedFiles : undefined, }, diagnosePromise, + declarationMap: !!compilerOptions.declarationMap, + compilationMode: compilerOptions.compilationMode === 'full' ? 'full' : 'partial', }; } catch (error) { if (!cached) { diff --git a/packages/angular/build/src/builders/library/schema.json b/packages/angular/build/src/builders/library/schema.json index bac9944091f6..ee34936bdd62 100644 --- a/packages/angular/build/src/builders/library/schema.json +++ b/packages/angular/build/src/builders/library/schema.json @@ -71,14 +71,12 @@ }, "declarationMap": { "type": "boolean", - "description": "Generates a sourcemap for each corresponding '.d.ts' file.", - "default": false + "description": "Generates a sourcemap for each corresponding '.d.ts' file." }, "compilationMode": { "type": "string", "description": "Angular compilation mode. Use 'partial' when publishing to npm (APF requirement). Use 'full' only during development or for private, internal monorepo packages that are never published.", - "enum": ["partial", "full"], - "default": "partial" + "enum": ["partial", "full"] }, "allowedNonPeerDependencies": { "description": "A list of package names allowed in the 'dependencies' and 'optionalDependencies' sections of package.json. Values can be regular expression patterns.", diff --git a/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts b/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts index cd794206960d..0efedef5708f 100644 --- a/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts +++ b/packages/angular/build/src/builders/library/tests/options/compilation-mode_spec.ts @@ -37,5 +37,53 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) => const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs'); expect(fesm).toContain('ɵɵdefineComponent'); }); + + it('should respect angularCompilerOptions.compilationMode from tsconfig when not set in builder options', async () => { + await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.angularCompilerOptions = { + ...tsconfig.angularCompilerOptions, + compilationMode: 'full', + }; + + return JSON.stringify(tsconfig, null, 2); + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs'); + expect(fesm).toContain('ɵɵdefineComponent'); + + const pkgJson = JSON.parse(harness.readFile('dist/lib/package.json')); + expect(pkgJson.scripts?.prepublishOnly).toContain('full compilation mode'); + }); + + it('should override angularCompilerOptions.compilationMode from tsconfig when set in builder options', async () => { + await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.angularCompilerOptions = { + ...tsconfig.angularCompilerOptions, + compilationMode: 'full', + }; + + return JSON.stringify(tsconfig, null, 2); + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + compilationMode: CompilationMode.Partial, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + const fesm = harness.readFile('dist/lib/fesm2022/lib.mjs'); + expect(fesm).toContain('ɵɵngDeclareComponent'); + }); }); }); diff --git a/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts b/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts index a37e2f0dd255..2e30109d6a03 100644 --- a/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts +++ b/packages/angular/build/src/builders/library/tests/options/declaration-map_spec.ts @@ -44,5 +44,43 @@ describeLibraryBuilder(executeLibraryBuilder, LIBRARY_BUILDER_INFO, (harness) => expect(dtsMap.sources).toContain('../../../projects/lib/src/lib/lib.component.ts'); harness.expectFile(join('dist/lib/types', dtsMap.sources[0])).toExist(); }); + + it('should respect declarationMap from tsconfig when not set in builder options', async () => { + await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.compilerOptions.declarationMap = true; + + return JSON.stringify(tsconfig, null, 2); + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/lib/types/lib.d.ts.map').toExist(); + }); + + it('should override declarationMap from tsconfig when declarationMap is false', async () => { + await harness.modifyFile('projects/lib/tsconfig.lib.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.compilerOptions.declarationMap = true; + + return JSON.stringify(tsconfig, null, 2); + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + declarationMap: false, + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/lib/fesm2022/lib.mjs.map').toExist(); + harness.expectFile('dist/lib/types/lib.d.ts.map').toNotExist(); + }); }); }); diff --git a/packages/angular/build/src/builders/library/types.ts b/packages/angular/build/src/builders/library/types.ts index dfe91c36f3c5..7ec8545a9c8e 100644 --- a/packages/angular/build/src/builders/library/types.ts +++ b/packages/angular/build/src/builders/library/types.ts @@ -74,8 +74,8 @@ export interface NormalizedLibraryOptions { styleIncludePaths: string[]; sass?: StylesheetPluginsass; assets: ReturnType; - compilationMode: 'partial' | 'full'; - declarationMap: boolean; + compilationMode?: 'partial' | 'full'; + declarationMap?: boolean; allowedNonPeerDependencies: RegExp[]; keepLifecycleScripts: boolean; watch: boolean; @@ -127,6 +127,9 @@ export interface SingleBuildState { /** Cached unified TypeScript and Angular compilation state. */ singleProgramCache?: SingleProgramCache; + /** Effective compilation mode resolved from builder options and tsconfig. */ + compilationMode?: 'partial' | 'full'; + /** Map of entry point names to their previous bundle results. */ previousBundleResults: Map; diff --git a/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts b/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts index d766680d1674..3da78cdf0275 100644 --- a/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts +++ b/packages/angular/build/src/tools/angular/compilation/angular-compilation.ts @@ -23,6 +23,7 @@ export interface FileTransformResult { export interface AngularCompilationOptions { allowJs?: boolean; + compilationMode?: 'full' | 'partial' | 'experimental-local'; declarationMap?: boolean; isolatedModules?: boolean; sourceMap?: boolean; diff --git a/packages/angular/build/src/tools/angular/compilation/compiler-options.ts b/packages/angular/build/src/tools/angular/compilation/compiler-options.ts index 1720a8bb0516..b2c83d616f08 100644 --- a/packages/angular/build/src/tools/angular/compilation/compiler-options.ts +++ b/packages/angular/build/src/tools/angular/compilation/compiler-options.ts @@ -71,6 +71,8 @@ export function transformCompilerOptions( compilerOptions.compilationMode = 'full'; } else if (overrides?.compilationMode) { compilerOptions.compilationMode = overrides.compilationMode; + } else if (isLibrary) { + compilerOptions.compilationMode ??= 'partial'; } // Enable incremental compilation by default if caching is enabled and incremental is not explicitly disabled @@ -114,7 +116,9 @@ export function transformCompilerOptions( compilerOptions.moduleResolution = typeScript.ModuleResolutionKind.Bundler; compilerOptions.importHelpers = true; compilerOptions.declaration = true; - compilerOptions.declarationMap = overrides?.declarationMap; + compilerOptions.declarationMap = !!( + overrides?.declarationMap ?? compilerOptions.declarationMap + ); compilerOptions.declarationDir = undefined; } diff --git a/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts b/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts index a74c032a1b70..475592bd478b 100644 --- a/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts +++ b/packages/angular/build/src/tools/angular/compilation/parallel-worker.ts @@ -125,6 +125,7 @@ export async function initialize(request: InitRequest): Promise