From cc7f1e736668b76452736045299358abb46c985c Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 20 Jun 2026 11:49:15 +0900
Subject: [PATCH] =?UTF-8?q?enhance(dev/frontend-js-size):=20diff=E3=81=8C?=
=?UTF-8?q?=E5=A4=A7=E3=81=8D=E3=81=84=E9=A0=86=E3=81=AB=E3=82=BD=E3=83=BC?=
=?UTF-8?q?=E3=83=88=E3=81=97=E3=81=9F=E4=B8=8A=E4=BD=8D10=E3=83=81?=
=?UTF-8?q?=E3=83=A3=E3=83=B3=E3=82=AF=E3=81=AE=E8=A1=A8=E3=82=92=E8=BF=BD?=
=?UTF-8?q?=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/frontend-js-size.yml | 53 ++++++++++++++++++++------
1 file changed, 41 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/frontend-js-size.yml b/.github/workflows/frontend-js-size.yml
index 7d3641355b..67d4e050c6 100644
--- a/.github/workflows/frontend-js-size.yml
+++ b/.github/workflows/frontend-js-size.yml
@@ -137,6 +137,11 @@ jobs:
return `${sign}${formatBytes(Math.abs(diff))}`;
}
+ function sizeDiff(beforeSize, afterSize) {
+ if (beforeSize == null && afterSize == null) return null;
+ return (afterSize ?? 0) - (beforeSize ?? 0);
+ }
+
function escapeCell(value) {
return String(value).replaceAll('|', '\\|').replaceAll('\n', '
');
}
@@ -251,19 +256,19 @@ jobs:
file: entryDisplayName(afterEntry ?? beforeEntry),
beforeSize,
afterSize,
- diff: beforeSize == null || afterSize == null ? null : afterSize - beforeSize,
+ diff: sizeDiff(beforeSize, afterSize),
sortSize: Math.max(beforeSize ?? 0, afterSize ?? 0),
};
});
}
- function markdownTable(rows) {
+ function markdownTable(rows, emptyMessage = '_No JavaScript chunks found._') {
if (rows.length === 0) {
- return '_No JavaScript chunks found._';
+ return emptyMessage;
}
const lines = [
- '| File | Size (before) | Size (after) | Size (diff) |',
+ '| File | Before | After | Diff |',
'| --- | ---: | ---: | ---: |',
];
for (const row of rows) {
@@ -283,6 +288,25 @@ jobs:
.map((row) => row.key);
}
+ function compareDiffRows(a, b) {
+ return Math.abs(b.diff ?? 0) - Math.abs(a.diff ?? 0)
+ || (b.diff ?? 0) - (a.diff ?? 0)
+ || b.sortSize - a.sortSize
+ || a.file.localeCompare(b.file);
+ }
+
+ function topDiffKeys(before, after) {
+ const allKeys = new Set([
+ ...Object.keys(before.chunks),
+ ...Object.keys(after.chunks),
+ ]);
+ return compareRows([...allKeys], before, after)
+ .filter((row) => row.diff !== 0 && row.diff != null)
+ .sort(compareDiffRows)
+ .slice(0, topLimit)
+ .map((row) => row.key);
+ }
+
const beforeDir = process.argv[2];
const afterDir = process.argv[3];
const outFile = process.argv[4];
@@ -295,6 +319,9 @@ jobs:
const topRows = compareRows(unionTopKeys(before, after), before, after)
.sort((a, b) => b.sortSize - a.sortSize || a.file.localeCompare(b.file));
+ const diffRows = compareRows(topDiffKeys(before, after), before, after)
+ .sort(compareDiffRows);
+
const startupKeys = new Set([
...before.startupKeys,
...after.startupKeys,
@@ -304,21 +331,23 @@ jobs:
const body = [
marker,
- '## Frontend JavaScript size',
+ '## Frontend size report',
'',
- `Compared locale: \`${locale}\``,
- `Before: \`${beforeSha}\``,
- `After: \`${afterSha}\``,
+ '### Top 10 largest chunk diffs',
'',
- '### Top 10 largest JS chunks',
+ markdownTable(diffRows, '_No JavaScript chunk size changes found._'),
'',
+ '### Top 10 largest chunks',
+ '',
markdownTable(topRows),
+ ' ',
'',
- '### Startup JS chunks',
- '',
+ '### Startup chunks',
+ '',
markdownTable(startupRows),
'',
- '_Top 10 is sorted by max(before, after) size. Startup chunks are the Vite entry for `src/_boot_.ts` and its static imports._',
+ '_Top 10 is sorted by max(before, after) size. Diff top 10 is sorted by absolute size diff, with missing chunks compared against 0 B. Startup chunks are the Vite entry for `src/_boot_.ts` and its static imports._',
+ ' ',
'',
].join('\n');