diff --git a/packages/angular_devkit/build_angular/src/browser/index.ts b/packages/angular_devkit/build_angular/src/browser/index.ts index 4d8f73059355..873f4e1ff296 100644 --- a/packages/angular_devkit/build_angular/src/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/browser/index.ts @@ -69,6 +69,7 @@ import { NgBuildAnalyticsPlugin } from '../webpack/plugins/analytics'; import { markAsyncChunksNonInitial } from '../webpack/utils/async-chunks'; import { BundleStats, + ChunkType, generateBundleStats, statsErrorsToString, statsHasErrors, @@ -592,11 +593,11 @@ export function buildWebpackBrowser( const chunk = webpackStats.chunks?.find((chunk) => chunk.id.toString() === result.name); if (result.original) { - bundleInfoStats.push(generateBundleInfoStats(result.original, chunk)); + bundleInfoStats.push(generateBundleInfoStats(result.original, chunk, 'modern')); } if (result.downlevel) { - bundleInfoStats.push(generateBundleInfoStats(result.downlevel, chunk)); + bundleInfoStats.push(generateBundleInfoStats(result.downlevel, chunk, 'legacy')); } } @@ -605,7 +606,7 @@ export function buildWebpackBrowser( ) || []; for (const chunk of unprocessedChunks) { const asset = webpackStats.assets?.find(a => a.name === chunk.files[0]); - bundleInfoStats.push(generateBundleStats({ ...chunk, size: asset?.size }, true)); + bundleInfoStats.push(generateBundleStats({ ...chunk, size: asset?.size })); } // Check for budget errors and display them to the user. @@ -773,6 +774,7 @@ type ArrayElement = A extends ReadonlyArray ? T : never; function generateBundleInfoStats( bundle: ProcessBundleFile, chunk: ArrayElement | undefined, + chunkType: ChunkType, ): BundleStats { return generateBundleStats( { @@ -782,8 +784,8 @@ function generateBundleInfoStats( entry: !!chunk?.names.includes('runtime'), initial: !!chunk?.initial, rendered: true, + chunkType, }, - true, ); } export default createBuilder(buildWebpackBrowser); diff --git a/packages/angular_devkit/build_angular/src/webpack/utils/stats.ts b/packages/angular_devkit/build_angular/src/webpack/utils/stats.ts index 51de97cf2851..93901d887033 100644 --- a/packages/angular_devkit/build_angular/src/webpack/utils/stats.ts +++ b/packages/angular_devkit/build_angular/src/webpack/utils/stats.ts @@ -29,9 +29,12 @@ export function formatSize(size: number): string { export type BundleStatsData = [files: string, names: string, size: number | string]; +export type ChunkType = 'modern' | 'legacy' | 'unknown'; + export interface BundleStats { initial: boolean; stats: BundleStatsData; + chunkType: ChunkType; }; export function generateBundleStats( @@ -42,15 +45,17 @@ export function generateBundleStats( entry: boolean; initial: boolean; rendered?: boolean; + chunkType?: ChunkType, }, - colors: boolean, ): BundleStats { const size = typeof info.size === 'number' ? info.size : '-'; const files = info.files.filter(f => !f.endsWith('.map')).map(f => path.basename(f)).join(', '); const names = info.names?.length ? info.names.join(', ') : '-'; const initial = !!(info.entry || info.initial); + const chunkType = info.chunkType || 'unknown'; return { + chunkType, initial, stats: [files, names, size], } @@ -65,9 +70,11 @@ function generateBuildStatsTable(data: BundleStats[], colors: boolean, showTotal const changedEntryChunksStats: BundleStatsData[] = []; const changedLazyChunksStats: BundleStatsData[] = []; - let initialTotalSize = 0; + let initialModernTotalSize = 0; + let initialLegacyTotalSize = 0; + let modernFileSuffix: string | undefined; - for (const { initial, stats } of data) { + for (const { initial, stats, chunkType } of data) { const [files, names, size] = stats; const data: BundleStatsData = [ @@ -80,9 +87,23 @@ function generateBuildStatsTable(data: BundleStats[], colors: boolean, showTotal changedEntryChunksStats.push(data); if (typeof size === 'number') { - initialTotalSize += size; + switch (chunkType) { + case 'modern': + initialModernTotalSize += size; + if (!modernFileSuffix) { + const match = files.match(/-(es20\d{2}|esnext)/); + modernFileSuffix = match?.[1].toString().toUpperCase(); + } + break; + case 'legacy': + initialLegacyTotalSize += size; + break; + default: + initialModernTotalSize += size; + initialLegacyTotalSize += size; + break; + } } - } else { changedLazyChunksStats.push(data); } @@ -99,7 +120,14 @@ function generateBuildStatsTable(data: BundleStats[], colors: boolean, showTotal if (showTotalSize) { bundleInfo.push([]); - bundleInfo.push([' ', 'Initial Total', formatSize(initialTotalSize)].map(bold)); + if (initialModernTotalSize === initialLegacyTotalSize) { + bundleInfo.push([' ', 'Initial Total', formatSize(initialModernTotalSize)].map(bold)); + } else { + bundleInfo.push( + [' ', 'Initial ES5 Total', formatSize(initialLegacyTotalSize)].map(bold), + [' ', `Initial ${modernFileSuffix} Total`, formatSize(initialModernTotalSize)].map(bold), + ); + } } } @@ -142,7 +170,7 @@ function statsToString(json: any, statsConfig: any, bundleState?: BundleStats[]) const assets = json.assets.filter((asset: any) => chunk.files.includes(asset.name)); const summedSize = assets.filter((asset: any) => !asset.name.endsWith(".map")).reduce((total: number, asset: any) => { return total + asset.size }, 0); - changedChunksStats.push(generateBundleStats({ ...chunk, size: summedSize }, colors)); + changedChunksStats.push(generateBundleStats({ ...chunk, size: summedSize })); } unchangedChunkNumber = json.chunks.length - changedChunksStats.length; } diff --git a/tests/legacy-cli/e2e/tests/basic/build.ts b/tests/legacy-cli/e2e/tests/basic/build.ts index 94bb74df0fb6..fee2be7abcf5 100644 --- a/tests/legacy-cli/e2e/tests/basic/build.ts +++ b/tests/legacy-cli/e2e/tests/basic/build.ts @@ -19,10 +19,18 @@ export default async function() { 'IE 11', ); // Production build - const { stderr: stderrProgress } = await ng('build', '--prod', '--progress'); + const { stderr: stderrProgress, stdout } = await ng('build', '--prod', '--progress'); await expectFileToMatch('dist/test-project/index.html', /main-es5\.[a-zA-Z0-9]{20}\.js/); await expectFileToMatch('dist/test-project/index.html', /main-es2015\.[a-zA-Z0-9]{20}\.js/); + if (!stdout.includes('Initial ES5 Total')) { + throw new Error(`Expected stdout not to contain 'Initial ES5 Total' but it did.\n${stdout}`); + } + + if (!stdout.includes('Initial ES2015 Total')) { + throw new Error(`Expected stdout not to contain 'Initial ES2015 Total' but it did.\n${stdout}`); + } + const logs: string[] = [ 'Browser application bundle generation complete', 'ES5 bundle generation complete',