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 71989ccc3ee1..451ca096d331 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 @@ -7,6 +7,7 @@ */ import type { + Metafile, OnStartResult, OutputFile, PartialMessage, @@ -237,6 +238,8 @@ export function createCompilerPlugin( // The stylesheet resources from component stylesheets that will be added to the build results output files let stylesheetResourceFiles: OutputFile[]; + let stylesheetMetafiles: Metafile[]; + let compilation: AngularCompilation | undefined; build.onStart(async () => { @@ -252,6 +255,7 @@ export function createCompilerPlugin( // Reset stylesheet resource output files stylesheetResourceFiles = []; + stylesheetMetafiles = []; // Create Angular compiler host options const hostOptions: AngularHostOptions = { @@ -276,6 +280,9 @@ export function createCompilerPlugin( (result.errors ??= []).push(...errors); (result.warnings ??= []).push(...warnings); stylesheetResourceFiles.push(...resourceFiles); + if (stylesheetResult.metafile) { + stylesheetMetafiles.push(stylesheetResult.metafile); + } return contents; }, @@ -403,10 +410,19 @@ export function createCompilerPlugin( ); build.onEnd((result) => { + // Add any component stylesheet resource files to the output files if (stylesheetResourceFiles.length) { result.outputFiles?.push(...stylesheetResourceFiles); } + // Combine component stylesheet metafiles with main metafile + if (result.metafile && stylesheetMetafiles.length) { + for (const metafile of stylesheetMetafiles) { + result.metafile.inputs = { ...result.metafile.inputs, ...metafile.inputs }; + result.metafile.outputs = { ...result.metafile.outputs, ...metafile.outputs }; + } + } + logCumulativeDurations(); }); }, 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 637b1b1d3029..1db7b0b52f31 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 @@ -15,7 +15,6 @@ const UNSUPPORTED_OPTIONS: Array = [ 'extractLicenses', 'progress', 'scripts', - 'statsJson', // * i18n support 'localize', 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 6cd5fd5fe45e..c54daf74f643 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 @@ -7,7 +7,7 @@ */ import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect'; -import type { BuildInvalidate, BuildOptions, OutputFile } from 'esbuild'; +import type { BuildInvalidate, BuildOptions, Metafile, OutputFile } from 'esbuild'; import assert from 'node:assert'; import * as fs from 'node:fs/promises'; import * as path from 'node:path'; @@ -141,6 +141,12 @@ async function execute( const initialFiles: FileInfo[] = [...codeResults.initialFiles, ...styleResults.initialFiles]; const outputFiles: OutputFile[] = [...codeResults.outputFiles, ...styleResults.outputFiles]; + // Combine metafiles used for the stats option as well as bundle budgets and console output + const metafile = { + inputs: { ...codeResults.metafile?.inputs, ...styleResults.metafile?.inputs }, + outputs: { ...codeResults.metafile?.outputs, ...styleResults.metafile?.outputs }, + }; + // Generate index HTML file if (indexHtmlOptions) { // Create an index HTML generator that reads from the in-memory output files @@ -191,6 +197,10 @@ async function execute( await Promise.all( outputFiles.map((file) => fs.writeFile(path.join(outputPath, file.path), file.contents)), ); + // Write metafile if stats option is enabled + if (options.stats) { + await fs.writeFile(path.join(outputPath, 'stats.json'), JSON.stringify(metafile, null, 2)); + } // Augment the application with service worker support // TODO: This should eventually operate on the in-memory files prior to writing the output files @@ -258,6 +268,7 @@ function createCodeBundleOptions( mainFields: ['es2020', 'browser', 'module', 'main'], conditions: ['es2020', 'es2015', 'module'], resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'], + metafile: true, logLevel: options.verbose ? 'debug' : 'silent', minify: optimizationOptions.scripts, pure: ['forwardRef'], diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/options.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/options.ts index ec6351ceca53..c752b35e01af 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/options.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/options.ts @@ -139,6 +139,7 @@ export async function normalizeOptions( inlineStyleLanguage = 'css', poll, preserveSymlinks, + statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, @@ -153,6 +154,7 @@ export async function normalizeOptions( crossOrigin, externalDependencies, inlineStyleLanguage, + stats: !!statsJson, poll, // If not explicitly set, default to the Node.js process argument preserveSymlinks: preserveSymlinks ?? process.execArgv.includes('--preserve-symlinks'), diff --git a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/stylesheets.ts b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/stylesheets.ts index c4390e80fcfd..381d4cf632ee 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser-esbuild/stylesheets.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser-esbuild/stylesheets.ts @@ -34,6 +34,7 @@ export function createStylesheetBundleOptions( assetNames: options.outputNames?.media, logLevel: 'silent', minify: options.optimization, + metafile: true, sourcemap: options.sourcemap, outdir: options.workspaceRoot, write: false, @@ -140,5 +141,6 @@ export async function bundleComponentStylesheet( map, path: outputPath, resourceFiles, + metafile: result.outputFiles && result.metafile, }; }