"use strict"; /** * @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.dev/license */ Object.defineProperty(exports, "__esModule", { value: true }); exports.generateEsbuildBuildStatsTable = generateEsbuildBuildStatsTable; exports.generateBuildStatsTable = generateBuildStatsTable; const node_util_1 = require("node:util"); const color_1 = require("./color"); const format_bytes_1 = require("./format-bytes"); function generateEsbuildBuildStatsTable([browserStats, serverStats], colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose) { const bundleInfo = generateBuildStatsData(browserStats, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose); if (serverStats.length) { const m = (x) => (colors ? color_1.colors.magenta(x) : x); if (browserStats.length) { bundleInfo.unshift([m('Browser bundles')]); // Add seperators between browser and server logs bundleInfo.push([], []); } bundleInfo.push([m('Server bundles')], ...generateBuildStatsData(serverStats, colors, false, false, undefined, verbose)); } return generateTableText(bundleInfo, colors); } function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures) { const bundleInfo = generateBuildStatsData(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, true); return generateTableText(bundleInfo, colors); } function generateBuildStatsData(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose) { if (data.length === 0) { return []; } const g = (x) => (colors ? color_1.colors.green(x) : x); const c = (x) => (colors ? color_1.colors.cyan(x) : x); const r = (x) => (colors ? color_1.colors.redBright(x) : x); const y = (x) => (colors ? color_1.colors.yellowBright(x) : x); const bold = (x) => (colors ? color_1.colors.bold(x) : x); const dim = (x) => (colors ? color_1.colors.dim(x) : x); const getSizeColor = (name, file, defaultColor = c) => { const severity = budgets.get(name) || (file && budgets.get(file)); switch (severity) { case 'warning': return y; case 'error': return r; default: return defaultColor; } }; const changedEntryChunksStats = []; const changedLazyChunksStats = []; let initialTotalRawSize = 0; let changedLazyChunksCount = 0; let initialTotalEstimatedTransferSize; const maxLazyChunksWithoutBudgetFailures = 15; const budgets = new Map(); if (budgetFailures) { for (const { label, severity } of budgetFailures) { // In some cases a file can have multiple budget failures. // Favor error. if (label && (!budgets.has(label) || budgets.get(label) === 'warning')) { budgets.set(label, severity); } } } // Sort descending by raw size data.sort((a, b) => { if (a.stats[2] > b.stats[2]) { return -1; } if (a.stats[2] < b.stats[2]) { return 1; } return 0; }); for (const { initial, stats } of data) { const [files, names, rawSize, estimatedTransferSize] = stats; if (!initial && !verbose && changedLazyChunksStats.length >= maxLazyChunksWithoutBudgetFailures && !budgets.has(names) && !budgets.has(files)) { // Limit the number of lazy chunks displayed in the stats table when there is no budget failure and not in verbose mode. changedLazyChunksCount++; continue; } const getRawSizeColor = getSizeColor(names, files); let data; if (showEstimatedTransferSize) { data = [ g(files), dim(names), getRawSizeColor(typeof rawSize === 'number' ? (0, format_bytes_1.formatSize)(rawSize) : rawSize), c(typeof estimatedTransferSize === 'number' ? (0, format_bytes_1.formatSize)(estimatedTransferSize) : estimatedTransferSize), ]; } else { data = [ g(files), dim(names), getRawSizeColor(typeof rawSize === 'number' ? (0, format_bytes_1.formatSize)(rawSize) : rawSize), '', ]; } if (initial) { changedEntryChunksStats.push(data); if (typeof rawSize === 'number') { initialTotalRawSize += rawSize; } if (showEstimatedTransferSize && typeof estimatedTransferSize === 'number') { if (initialTotalEstimatedTransferSize === undefined) { initialTotalEstimatedTransferSize = 0; } initialTotalEstimatedTransferSize += estimatedTransferSize; } } else { changedLazyChunksStats.push(data); changedLazyChunksCount++; } } const bundleInfo = []; const baseTitles = ['Names', 'Raw size']; if (showEstimatedTransferSize) { baseTitles.push('Estimated transfer size'); } // Entry chunks if (changedEntryChunksStats.length) { bundleInfo.push(['Initial chunk files', ...baseTitles].map(bold), ...changedEntryChunksStats); if (showTotalSize) { const initialSizeTotalColor = getSizeColor('bundle initial', undefined, (x) => x); const totalSizeElements = [ ' ', 'Initial total', initialSizeTotalColor((0, format_bytes_1.formatSize)(initialTotalRawSize)), ]; if (showEstimatedTransferSize) { totalSizeElements.push(typeof initialTotalEstimatedTransferSize === 'number' ? (0, format_bytes_1.formatSize)(initialTotalEstimatedTransferSize) : '-'); } bundleInfo.push([], totalSizeElements.map(bold)); } } // Seperator if (changedEntryChunksStats.length && changedLazyChunksStats.length) { bundleInfo.push([]); } // Lazy chunks if (changedLazyChunksStats.length) { bundleInfo.push(['Lazy chunk files', ...baseTitles].map(bold), ...changedLazyChunksStats); if (changedLazyChunksCount > changedLazyChunksStats.length) { bundleInfo.push([ dim(`...and ${changedLazyChunksCount - changedLazyChunksStats.length} more lazy chunks files. ` + 'Use "--verbose" to show all the files.'), ]); } } return bundleInfo; } function generateTableText(bundleInfo, colors) { const skipText = (value) => value.includes('...and '); const longest = []; for (const item of bundleInfo) { for (let i = 0; i < item.length; i++) { if (item[i] === undefined) { continue; } const currentItem = item[i].toString(); if (skipText(currentItem)) { continue; } const currentLongest = (longest[i] ??= 0); const currentItemLength = (0, node_util_1.stripVTControlCharacters)(currentItem).length; if (currentLongest < currentItemLength) { longest[i] = currentItemLength; } } } const seperator = colors ? color_1.colors.dim(' | ') : ' | '; const outputTable = []; for (const item of bundleInfo) { for (let i = 0; i < longest.length; i++) { if (item[i] === undefined) { continue; } const currentItem = item[i].toString(); if (skipText(currentItem)) { continue; } const currentItemLength = (0, node_util_1.stripVTControlCharacters)(currentItem).length; const stringPad = ' '.repeat(longest[i] - currentItemLength); // Values in columns at index 2 and 3 (Raw and Estimated sizes) are always right aligned. item[i] = i >= 2 ? stringPad + currentItem : currentItem + stringPad; } outputTable.push(item.join(seperator)); } return outputTable.join('\n'); }