From 68877fe7906be999bc7a34c14cc017eb13b7cc4b Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 30 May 2023 15:03:21 -0400 Subject: [PATCH] fix(@angular-devkit/build-angular): preemptively remove AOT metadata in esbuild builder The Angular compiler generates two types of metadata calls when it generates AOT code. This metadata is not used in fully AOT compiled applications and can contain direct references to components, services, etc. that may affect the output chunk layout of the application. While this currently has not lead to any problems, it could in the future and the Webpack bundler already performs a transform that preemptively removes these calls. To remain consistent, the esbuild-based build system will now also perform this transform. This also updates the autoprefixer behavior tests to check the actual runtime style text instead of the style text within the metadata calls. (cherry picked from commit c462d9cb90377342980384c6bccb3ddfef533282) --- .../browser-esbuild/angular/aot-compilation.ts | 13 +++++++++---- .../behavior/stylesheet_autoprefixer_spec.ts | 17 +++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts index a91a2566eecf..9369959d097f 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts @@ -19,7 +19,10 @@ import { // Temporary deep import for transformer support // TODO: Move these to a private exports location or move the implementation into this package. -const { mergeTransformers, replaceBootstrap } = require('@ngtools/webpack/src/ivy/transformation'); +const { + mergeTransformers, + createAotTransformers, +} = require('@ngtools/webpack/src/ivy/transformation'); class AngularCompilationState { constructor( @@ -153,9 +156,11 @@ export class AotCompilation extends AngularCompilation { assert(this.#state, 'Angular compilation must be initialized prior to emitting files.'); const { angularCompiler, typeScriptProgram } = this.#state; - const transformers = mergeTransformers(angularCompiler.prepareEmit().transformers, { - before: [replaceBootstrap(() => typeScriptProgram.getProgram().getTypeChecker())], - }); + const transformers = mergeTransformers( + angularCompiler.prepareEmit().transformers, + // The default behavior is to replace JIT bootstraping and remove AOT metadata calls + createAotTransformers(typeScriptProgram, {}), + ); return async (file: string) => { const sourceFile = typeScriptProgram.getSourceFile(file); diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/tests/behavior/stylesheet_autoprefixer_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/tests/behavior/stylesheet_autoprefixer_spec.ts index bf08b78bd19b..84aa4039d406 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/tests/behavior/stylesheet_autoprefixer_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/tests/behavior/stylesheet_autoprefixer_spec.ts @@ -106,12 +106,10 @@ describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => { harness .expectFile('dist/main.js') - .content.toMatch( - /section\s*{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/, - ); + .content.toMatch(/{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/); harness .expectFile('dist/main.js') - .content.toMatch(/div\s*{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/); + .content.toMatch(/{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/); }); it(`should not add prefixes if not required by browsers in external component styles [${ext}]`, async () => { @@ -137,10 +135,8 @@ describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => { const { result } = await harness.executeOnce(); expect(result?.success).toBeTrue(); - harness - .expectFile('dist/main.js') - .content.toMatch(/section\s*{\\n\s*hyphens:\s*none;\\n\s*}/); - harness.expectFile('dist/main.js').content.toMatch(/div\s*{\\n\s*hyphens:\s*none;\\n\s*}/); + harness.expectFile('dist/main.js').content.toMatch(/{\\n\s*hyphens:\s*none;\\n\s*}/); + harness.expectFile('dist/main.js').content.toMatch(/{\\n\s*hyphens:\s*none;\\n\s*}/); }); } @@ -169,7 +165,8 @@ describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => { harness .expectFile('dist/main.js') - .content.toMatch(/div\s*{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/); + // div[_ngcontent-%COMP%] {\n -webkit-hyphens: none;\n hyphens: none;\n}\n + .content.toMatch(/{\\n\s*-webkit-hyphens:\s*none;\\n\s*hyphens:\s*none;\\n\s*}/); }); it('should not add prefixes if not required by browsers in inline component styles', async () => { @@ -193,7 +190,7 @@ describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => { const { result } = await harness.executeOnce(); expect(result?.success).toBeTrue(); - harness.expectFile('dist/main.js').content.toMatch(/div\s*{\\n\s*hyphens:\s*none;\\n\s*}/); + harness.expectFile('dist/main.js').content.toMatch(/{\\n\s*hyphens:\s*none;\\n\s*}/); }); }); });