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/compiler-plugin.ts index 434c377b6c36..9125b013228a 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/compiler-plugin.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/compiler-plugin.ts @@ -128,6 +128,7 @@ export function createCompilerPlugin( tsconfig: string; advancedOptimizations?: boolean; thirdPartySourcemaps?: boolean; + fileReplacements?: Record; }, styleOptions: BundleStylesheetOptions, ): Plugin { @@ -256,6 +257,13 @@ export function createCompilerPlugin( return { content: contents }; }; + // Augment TypeScript Host for file replacements option + if (pluginOptions.fileReplacements) { + // Temporary deep import for file replacements support + const { augmentHostWithReplacements } = require('@ngtools/webpack/src/ivy/host'); + augmentHostWithReplacements(host, pluginOptions.fileReplacements); + } + // Create the Angular specific program that contains the Angular compiler const angularProgram = new compilerCli.NgtscProgram(rootNames, compilerOptions, host); const angularCompiler = angularProgram.compiler; @@ -316,7 +324,9 @@ export function createCompilerPlugin( async (args) => { assert.ok(fileEmitter, 'Invalid plugin execution order'); - const typescriptResult = await fileEmitter(args.path); + const typescriptResult = await fileEmitter( + pluginOptions.fileReplacements?.[args.path] ?? args.path, + ); if (!typescriptResult) { // No TS result indicates the file is not part of the TypeScript program. // If allowJs is enabled and the file is JS then defer to the next load hook. diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/experimental-warnings.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/experimental-warnings.ts index 4fb4e5e12115..e7f200e9f2e6 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/experimental-warnings.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/experimental-warnings.ts @@ -13,7 +13,6 @@ const UNSUPPORTED_OPTIONS: Array = [ 'allowedCommonJsDependencies', 'budgets', 'extractLicenses', - 'fileReplacements', 'progress', 'scripts', 'statsJson', 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 cf87992d5d76..07a1880e2bb2 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 @@ -249,6 +249,17 @@ async function bundleCode( sourcemapOptions: SourceMapClass, tsconfig: string, ) { + let fileReplacements: Record | undefined; + if (options.fileReplacements) { + for (const replacement of options.fileReplacements) { + fileReplacements ??= {}; + fileReplacements[path.join(workspaceRoot, replacement.replace)] = path.join( + workspaceRoot, + replacement.with, + ); + } + } + return bundle({ absWorkingDir: workspaceRoot, bundle: true, @@ -288,6 +299,7 @@ async function bundleCode( thirdPartySourcemaps: sourcemapOptions.vendor, tsconfig, advancedOptimizations: options.buildOptimizer, + fileReplacements, }, // Component stylesheet options { diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/schema.json b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/schema.json index c392bd055d51..2fbb75a62927 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/schema.json +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/schema.json @@ -461,38 +461,19 @@ ] }, "fileReplacement": { - "oneOf": [ - { - "type": "object", - "properties": { - "src": { - "type": "string", - "pattern": "\\.(([cm]?j|t)sx?|json)$" - }, - "replaceWith": { - "type": "string", - "pattern": "\\.(([cm]?j|t)sx?|json)$" - } - }, - "additionalProperties": false, - "required": ["src", "replaceWith"] + "type": "object", + "properties": { + "replace": { + "type": "string", + "pattern": "\\.(([cm]?j|t)sx?|json)$" }, - { - "type": "object", - "properties": { - "replace": { - "type": "string", - "pattern": "\\.(([cm]?j|t)sx?|json)$" - }, - "with": { - "type": "string", - "pattern": "\\.(([cm]?j|t)sx?|json)$" - } - }, - "additionalProperties": false, - "required": ["replace", "with"] + "with": { + "type": "string", + "pattern": "\\.(([cm]?j|t)sx?|json)$" } - ] + }, + "additionalProperties": false, + "required": ["replace", "with"] }, "budget": { "type": "object",