From a005b78504975492e40b9600e1041ad1ed2f5eda Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 10 Apr 2023 17:57:43 -0400 Subject: [PATCH 1/2] refactor(@angular-devkit/build-angular): move esbuild compiler plugin in angular directory Minor directory restructure to better organize the Angular compiler plugin code files. The remainder of the Angular specific files for the Angular esbuild compiler plugin are now within the `angular` subdirectory of the esbuild-based browser application builder. --- .../{ => angular}/angular-host.ts | 0 .../aot-compilation.ts} | 8 +++---- .../{ => angular}/compiler-plugin.ts | 22 +++++++++---------- .../angular/jit-compilation.ts | 4 ++-- .../src/builders/browser-esbuild/index.ts | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) rename packages/angular_devkit/build_angular/src/builders/browser-esbuild/{ => angular}/angular-host.ts (100%) rename packages/angular_devkit/build_angular/src/builders/browser-esbuild/{angular-compilation.ts => angular/aot-compilation.ts} (97%) rename packages/angular_devkit/build_angular/src/builders/browser-esbuild/{ => angular}/compiler-plugin.ts (96%) diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular-host.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts similarity index 100% rename from packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular-host.ts rename to packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular-compilation.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts similarity index 97% rename from packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular-compilation.ts rename to packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts index 69b0e860c92f..d7a6f0d70730 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular-compilation.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/aot-compilation.ts @@ -9,13 +9,13 @@ import type ng from '@angular/compiler-cli'; import assert from 'node:assert'; import ts from 'typescript'; -import { loadEsmModule } from '../../utils/load-esm'; +import { loadEsmModule } from '../../../utils/load-esm'; +import { profileAsync, profileSync } from '../profiling'; import { AngularHostOptions, createAngularCompilerHost, ensureSourceFileVersions, } from './angular-host'; -import { profileAsync, profileSync } from './profiling'; // Temporary deep import for transformer support // TODO: Move these to a private exports location or move the implementation into this package. @@ -42,7 +42,7 @@ export interface EmitFileResult { } export type FileEmitter = (file: string) => Promise; -export class AngularCompilation { +export class AotCompilation { static #angularCompilerCliModule?: typeof ng; #state?: AngularCompilationState; @@ -64,7 +64,7 @@ export class AngularCompilation { configurationDiagnostics?: ts.Diagnostic[], ): Promise<{ affectedFiles: ReadonlySet }> { // Dynamically load the Angular compiler CLI package - const { NgtscProgram, OptimizeFor } = await AngularCompilation.loadCompilerCli(); + const { NgtscProgram, OptimizeFor } = await AotCompilation.loadCompilerCli(); // Create Angular compiler host const host = createAngularCompilerHost(compilerOptions, hostOptions); diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/compiler-plugin.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts similarity index 96% rename from packages/angular_devkit/build_angular/src/builders/browser-esbuild/compiler-plugin.ts rename to packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts index 5242a2513efd..055bbaf4ae42 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/compiler-plugin.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts @@ -20,19 +20,19 @@ import { platform } from 'node:os'; import * as path from 'node:path'; import { pathToFileURL } from 'node:url'; import ts from 'typescript'; -import { maxWorkers } from '../../utils/environment-options'; -import { JitCompilation } from './angular/jit-compilation'; -import { setupJitPluginCallbacks } from './angular/jit-plugin-callbacks'; -import { AngularCompilation, FileEmitter } from './angular-compilation'; -import { AngularHostOptions } from './angular-host'; -import { JavaScriptTransformer } from './javascript-transformer'; +import { maxWorkers } from '../../../utils/environment-options'; +import { JavaScriptTransformer } from '../javascript-transformer'; import { logCumulativeDurations, profileAsync, profileSync, resetCumulativeDurations, -} from './profiling'; -import { BundleStylesheetOptions, bundleComponentStylesheet } from './stylesheets'; +} from '../profiling'; +import { BundleStylesheetOptions, bundleComponentStylesheet } from '../stylesheets'; +import { AngularHostOptions } from './angular-host'; +import { AotCompilation, FileEmitter } from './aot-compilation'; +import { JitCompilation } from './jit-compilation'; +import { setupJitPluginCallbacks } from './jit-plugin-callbacks'; /** * Converts TypeScript Diagnostic related information into an esbuild compatible note object. @@ -166,7 +166,7 @@ export function createCompilerPlugin( const javascriptTransformer = new JavaScriptTransformer(pluginOptions, maxWorkers); const { GLOBAL_DEFS_FOR_TERSER_WITH_AOT, readConfiguration } = - await AngularCompilation.loadCompilerCli(); + await AotCompilation.loadCompilerCli(); // Setup defines based on the values provided by the Angular compiler-cli build.initialOptions.define ??= {}; @@ -239,7 +239,7 @@ export function createCompilerPlugin( let stylesheetMetafiles: Metafile[]; - let compilation: AngularCompilation | undefined; + let compilation: AotCompilation | undefined; build.onStart(async () => { const result: OnStartResult = { @@ -291,7 +291,7 @@ export function createCompilerPlugin( if (pluginOptions.jit) { compilation ??= new JitCompilation(); } else { - compilation ??= new AngularCompilation(); + compilation ??= new AotCompilation(); } // Initialize the Angular compilation for the current build. diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts index af4ab1b816a5..afa79123afc0 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts @@ -8,9 +8,9 @@ import assert from 'node:assert'; import ts from 'typescript'; -import { AngularCompilation } from '../angular-compilation'; -import { AngularHostOptions, createAngularCompilerHost } from '../angular-host'; import { profileSync } from '../profiling'; +import { AngularCompilation } from './angular-compilation'; +import { AngularHostOptions, createAngularCompilerHost } from './angular-host'; import { createJitResourceTransformer } from './jit-resource-transformer'; class JitCompilationState { diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts index 91be8df20957..bd4d9c967c24 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/index.ts @@ -22,8 +22,8 @@ import { augmentAppWithServiceWorkerEsbuild } from '../../utils/service-worker'; import { Spinner } from '../../utils/spinner'; import { getSupportedBrowsers } from '../../utils/supported-browsers'; import { BundleStats, generateBuildStatsTable } from '../../webpack/utils/stats'; +import { SourceFileCache, createCompilerPlugin } from './angular/compiler-plugin'; import { checkCommonJSModules } from './commonjs-checker'; -import { SourceFileCache, createCompilerPlugin } from './compiler-plugin'; import { BundlerContext, logMessages } from './esbuild'; import { logExperimentalWarnings } from './experimental-warnings'; import { createGlobalScriptsBundleOptions } from './global-scripts'; From 71d35d720c41afd2e75af768d13fd839e1d74b9a Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 10 Apr 2023 21:40:17 -0400 Subject: [PATCH 2/2] refactor(@angular-devkit/build-angular): use base class for esbuild Angular JIT/AOT compilation Types and functionality that were used by both the AOT and JIT compilation classes within the esbuild Angular compiler plugin have been extracted into a common base class that both now extend. This removes duplicate code from both classes. --- .../angular/angular-compilation.ts | 45 +++++++++++++++++++ .../browser-esbuild/angular/angular-host.ts | 2 +- .../angular/aot-compilation.ts | 25 ++--------- .../angular/compiler-plugin.ts | 7 +-- .../angular/jit-compilation.ts | 11 +---- 5 files changed, 55 insertions(+), 35 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-compilation.ts diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-compilation.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-compilation.ts new file mode 100644 index 000000000000..27478e2f7e81 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-compilation.ts @@ -0,0 +1,45 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import type ng from '@angular/compiler-cli'; +import type ts from 'typescript'; +import { loadEsmModule } from '../../../utils/load-esm'; +import type { AngularHostOptions } from './angular-host'; + +export interface EmitFileResult { + content?: string; + map?: string; + dependencies: readonly string[]; +} + +export type FileEmitter = (file: string) => Promise; + +export abstract class AngularCompilation { + static #angularCompilerCliModule?: typeof ng; + + static async loadCompilerCli(): Promise { + // This uses a wrapped dynamic import to load `@angular/compiler-cli` which is ESM. + // Once TypeScript provides support for retaining dynamic imports this workaround can be dropped. + AngularCompilation.#angularCompilerCliModule ??= await loadEsmModule( + '@angular/compiler-cli', + ); + + return AngularCompilation.#angularCompilerCliModule; + } + + abstract initialize( + rootNames: string[], + compilerOptions: ts.CompilerOptions, + hostOptions: AngularHostOptions, + configurationDiagnostics?: ts.Diagnostic[], + ): Promise<{ affectedFiles: ReadonlySet }>; + + abstract collectDiagnostics(): Iterable; + + abstract createFileEmitter(onAfterEmit?: (sourceFile: ts.SourceFile) => void): FileEmitter; +} diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts index d0d1dd91466d..a61fcbe88883 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/angular-host.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import ng from '@angular/compiler-cli'; +import type ng from '@angular/compiler-cli'; import ts from 'typescript'; export type AngularCompilerOptions = ng.CompilerOptions; 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 d7a6f0d70730..c827885e3944 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 @@ -9,8 +9,8 @@ import type ng from '@angular/compiler-cli'; import assert from 'node:assert'; import ts from 'typescript'; -import { loadEsmModule } from '../../../utils/load-esm'; import { profileAsync, profileSync } from '../profiling'; +import { AngularCompilation, FileEmitter } from './angular-compilation'; import { AngularHostOptions, createAngularCompilerHost, @@ -35,28 +35,9 @@ class AngularCompilationState { } } -export interface EmitFileResult { - content?: string; - map?: string; - dependencies: readonly string[]; -} -export type FileEmitter = (file: string) => Promise; - -export class AotCompilation { - static #angularCompilerCliModule?: typeof ng; - +export class AotCompilation extends AngularCompilation { #state?: AngularCompilationState; - static async loadCompilerCli(): Promise { - // This uses a wrapped dynamic import to load `@angular/compiler-cli` which is ESM. - // Once TypeScript provides support for retaining dynamic imports this workaround can be dropped. - this.#angularCompilerCliModule ??= await loadEsmModule('@angular/compiler-cli'); - - return this.#angularCompilerCliModule; - } - - constructor() {} - async initialize( rootNames: string[], compilerOptions: ng.CompilerOptions, @@ -64,7 +45,7 @@ export class AotCompilation { configurationDiagnostics?: ts.Diagnostic[], ): Promise<{ affectedFiles: ReadonlySet }> { // Dynamically load the Angular compiler CLI package - const { NgtscProgram, OptimizeFor } = await AotCompilation.loadCompilerCli(); + const { NgtscProgram, OptimizeFor } = await AngularCompilation.loadCompilerCli(); // Create Angular compiler host const host = createAngularCompilerHost(compilerOptions, hostOptions); diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts index 055bbaf4ae42..ba7a5a47f7bb 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts @@ -29,8 +29,9 @@ import { resetCumulativeDurations, } from '../profiling'; import { BundleStylesheetOptions, bundleComponentStylesheet } from '../stylesheets'; +import { AngularCompilation, FileEmitter } from './angular-compilation'; import { AngularHostOptions } from './angular-host'; -import { AotCompilation, FileEmitter } from './aot-compilation'; +import { AotCompilation } from './aot-compilation'; import { JitCompilation } from './jit-compilation'; import { setupJitPluginCallbacks } from './jit-plugin-callbacks'; @@ -166,7 +167,7 @@ export function createCompilerPlugin( const javascriptTransformer = new JavaScriptTransformer(pluginOptions, maxWorkers); const { GLOBAL_DEFS_FOR_TERSER_WITH_AOT, readConfiguration } = - await AotCompilation.loadCompilerCli(); + await AngularCompilation.loadCompilerCli(); // Setup defines based on the values provided by the Angular compiler-cli build.initialOptions.define ??= {}; @@ -239,7 +240,7 @@ export function createCompilerPlugin( let stylesheetMetafiles: Metafile[]; - let compilation: AotCompilation | undefined; + let compilation: AngularCompilation | undefined; build.onStart(async () => { const result: OnStartResult = { diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts index afa79123afc0..8dc4dd2bcaec 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/jit-compilation.ts @@ -9,7 +9,7 @@ import assert from 'node:assert'; import ts from 'typescript'; import { profileSync } from '../profiling'; -import { AngularCompilation } from './angular-compilation'; +import { AngularCompilation, FileEmitter } from './angular-compilation'; import { AngularHostOptions, createAngularCompilerHost } from './angular-host'; import { createJitResourceTransformer } from './jit-resource-transformer'; @@ -21,14 +21,7 @@ class JitCompilationState { ) {} } -export interface EmitFileResult { - content?: string; - map?: string; - dependencies: readonly string[]; -} -export type FileEmitter = (file: string) => Promise; - -export class JitCompilation { +export class JitCompilation extends AngularCompilation { #state?: JitCompilationState; async initialize(