diff --git a/.github/scripts/frontend-js-size.mjs b/.github/scripts/frontend-js-size.mjs index 75744bfcba..e12f30896c 100644 --- a/.github/scripts/frontend-js-size.mjs +++ b/.github/scripts/frontend-js-size.mjs @@ -189,6 +189,13 @@ function removedKeys(before, after) { .filter((key) => after.chunks[key] == null); } +function rowChangeType(beforeEntry, afterEntry, beforeSize, afterSize) { + if (beforeEntry == null) return 'added'; + if (afterEntry == null) return 'removed'; + if (beforeSize !== afterSize) return 'updated'; + return 'unchanged'; +} + function getChunkComparisonRows(keys, before, after) { return keys.map((key) => { const beforeEntry = before.chunks[key]; @@ -201,11 +208,31 @@ function getChunkComparisonRows(keys, before, after) { chunkFile: beforeEntry?.file ?? afterEntry?.file, beforeSize, afterSize, + changeType: rowChangeType(beforeEntry, afterEntry, beforeSize, afterSize), sortSize: Math.max(beforeSize, afterSize), }; }); } +function summarizeChanges(rows) { + return { + updated: rows.filter((row) => row.changeType === 'updated').length, + added: rows.filter((row) => row.changeType === 'added').length, + removed: rows.filter((row) => row.changeType === 'removed').length, + }; +} + +function formatChangeSummary(label, summary) { + return `${label} (${summary.updated} updated, ${summary.added} added, ${summary.removed} removed)`; +} + +function compareComparisonRows(a, b) { + return Math.abs(b.afterSize - b.beforeSize) - Math.abs(a.afterSize - a.beforeSize) + || (b.afterSize - b.beforeSize) - (a.afterSize - a.beforeSize) + || b.sortSize - a.sortSize + || a.name.localeCompare(b.name); +} + function markdownTable(rows, total) { if (rows.length === 0) return '_No data_'; @@ -218,32 +245,13 @@ function markdownTable(rows, total) { lines.push('| | | | | |'); } for (const row of rows) { - lines.push(`|
\`${escapeCell(row.name)}\` \`${escapeCell(row.chunkFile)}\`
| ${formatBytes(row.beforeSize)} | ${formatBytes(row.afterSize)} | ${formatDiff(row.afterSize - row.beforeSize)} | ${formatDiffPercent(row.beforeSize, row.afterSize)} |`); - } - return lines.join('\n'); -} - -function chunkRows(keys, report) { - return keys.map((key) => { - const entry = report.chunks[key]; - return { - key, - name: entryDisplayName(entry), - chunkFile: entry.file, - size: entry.size, - }; - }); -} - -function markdownChunkTable(rows) { - if (rows.length === 0) return '_No data_'; - - const lines = [ - '| Chunk | Size |', - '| --- | ---: |', - ]; - for (const row of rows) { - lines.push(`|
\`${escapeCell(row.name)}\` \`${escapeCell(row.chunkFile)}\`
| ${formatBytes(row.size)} |`); + if (row.changeType === 'added') { + lines.push(`|
\`${escapeCell(row.name)}\` \`${escapeCell(row.chunkFile)}\`
| ${formatBytes(row.beforeSize)} | ${formatBytes(row.afterSize)} | ${formatDiff(row.afterSize - row.beforeSize)} | $\\color{orange}{\\text{(+)}}$ |`); + } else if (row.changeType === 'removed') { + lines.push(`|
\`${escapeCell(row.name)}\` \`${escapeCell(row.chunkFile)}\`
| ${formatBytes(row.beforeSize)} | ${formatBytes(row.afterSize)} | ${formatDiff(row.afterSize - row.beforeSize)} | $\\color{green}{\\text{(-)}}$ |`); + } else { + lines.push(`|
\`${escapeCell(row.name)}\` \`${escapeCell(row.chunkFile)}\`
| ${formatBytes(row.beforeSize)} | ${formatBytes(row.afterSize)} | ${formatDiff(row.afterSize - row.beforeSize)} | ${formatDiffPercent(row.beforeSize, row.afterSize)} |`); + } } return lines.join('\n'); } @@ -258,37 +266,40 @@ const before = await collectReport(beforeDir); const after = await collectReport(afterDir); const commonChunkKeys = commonKeys(before, after); +const allChunkKeys = [ + ...commonChunkKeys, + ...addedKeys(before, after), + ...removedKeys(before, after), +]; const comparisonRows = getChunkComparisonRows(commonChunkKeys, before, after); +const allComparisonRows = getChunkComparisonRows(allChunkKeys, before, after); -const diffRows = comparisonRows - .filter((row) => row.beforeSize !== row.afterSize) - .sort((a, b) => Math.abs(b.afterSize - b.beforeSize) - Math.abs(a.afterSize - a.beforeSize) - || (b.afterSize - b.beforeSize) - (a.afterSize - a.beforeSize) - || b.sortSize - a.sortSize - || a.name.localeCompare(b.name)) - .slice(0, 30); +const changedRows = allComparisonRows + .filter((row) => row.changeType !== 'unchanged'); +const diffRows = [ + ...changedRows + .filter((row) => row.changeType === 'updated') + .sort(compareComparisonRows) + .slice(0, 30), + ...changedRows + .filter((row) => row.changeType !== 'updated') + .sort(compareComparisonRows), +].sort(compareComparisonRows); +const diffSummary = summarizeChanges(changedRows); const diffTotal = { - beforeSize: comparisonRows.reduce((sum, row) => sum + row.beforeSize, 0), - afterSize: comparisonRows.reduce((sum, row) => sum + row.afterSize, 0), + beforeSize: allComparisonRows.reduce((sum, row) => sum + row.beforeSize, 0), + afterSize: allComparisonRows.reduce((sum, row) => sum + row.afterSize, 0), }; -const addedRows = chunkRows(addedKeys(before, after), after) - .sort((a, b) => b.size - a.size || a.name.localeCompare(b.name)); - -const removedRows = chunkRows(removedKeys(before, after), before) - .sort((a, b) => b.size - a.size || a.name.localeCompare(b.name)); - const startupKeys = new Set([ ...before.startupKeys, ...after.startupKeys, ]); const startupComparisonRows = getChunkComparisonRows([...startupKeys], before, after); const startupRows = startupComparisonRows - .sort((a, b) => Math.abs(b.afterSize - b.beforeSize) - Math.abs(a.afterSize - a.beforeSize) - || (b.afterSize - b.beforeSize) - (a.afterSize - a.beforeSize) - || b.sortSize - a.sortSize - || a.name.localeCompare(b.name)); + .sort(compareComparisonRows); +const startupSummary = summarizeChanges(startupComparisonRows); const startupTotal = { beforeSize: startupComparisonRows.reduce((sum, row) => sum + row.beforeSize, 0), afterSize: startupComparisonRows.reduce((sum, row) => sum + row.afterSize, 0), @@ -300,31 +311,17 @@ const largeRows = comparisonRows const body = [ marker, - `## Frontend chunk report (${locale})`, + `## Frontend Chunk Report`, '', '
', - `Diffs`, + `${formatChangeSummary('Diffs', diffSummary)}`, '', markdownTable(diffRows, diffTotal), '', '
', '', '
', - `Added (${addedRows.length})`, - '', - markdownChunkTable(addedRows), - '', - '
', - '', - '
', - `Removed (${removedRows.length})`, - '', - markdownChunkTable(removedRows), - '', - '
', - '', - '
', - `Startup`, + `${formatChangeSummary('Startup', startupSummary)}`, '', markdownTable(startupRows, startupTotal), '',