Skip to content

Commit bd0cde3

Browse files
make size-limit checks the loading and running time of bundles and use size-limit for comparison
1 parent fdb9082 commit bd0cde3

File tree

3 files changed

+89
-33
lines changed

3 files changed

+89
-33
lines changed

.size-limit.json

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,104 +4,121 @@
44
"path": "packages/react-on-rails/lib/*.js",
55
"webpack": false,
66
"gzip": false,
7-
"brotli": false
7+
"brotli": false,
8+
"running": false
89
},
910
{
1011
"name": "react-on-rails (gzip)",
1112
"path": "packages/react-on-rails/lib/*.js",
1213
"webpack": false,
13-
"gzip": true
14+
"gzip": true,
15+
"running": false
1416
},
1517
{
1618
"name": "react-on-rails (brotli)",
1719
"path": "packages/react-on-rails/lib/*.js",
1820
"webpack": false,
19-
"brotli": true
21+
"brotli": true,
22+
"running": false
2023
},
2124
{
2225
"name": "react-on-rails-pro (raw)",
2326
"path": "packages/react-on-rails-pro/lib/*.js",
2427
"webpack": false,
2528
"gzip": false,
26-
"brotli": false
29+
"brotli": false,
30+
"running": false
2731
},
2832
{
2933
"name": "react-on-rails-pro (gzip)",
3034
"path": "packages/react-on-rails-pro/lib/*.js",
3135
"webpack": false,
32-
"gzip": true
36+
"gzip": true,
37+
"running": false
3338
},
3439
{
3540
"name": "react-on-rails-pro (brotli)",
3641
"path": "packages/react-on-rails-pro/lib/*.js",
3742
"webpack": false,
38-
"brotli": true
43+
"brotli": true,
44+
"running": false
3945
},
4046
{
4147
"name": "react-on-rails-pro-node-renderer (raw)",
4248
"path": "packages/react-on-rails-pro-node-renderer/lib/*.js",
4349
"webpack": false,
4450
"gzip": false,
45-
"brotli": false
51+
"brotli": false,
52+
"running": false
4653
},
4754
{
4855
"name": "react-on-rails-pro-node-renderer (gzip)",
4956
"path": "packages/react-on-rails-pro-node-renderer/lib/*.js",
5057
"webpack": false,
51-
"gzip": true
58+
"gzip": true,
59+
"running": false
5260
},
5361
{
5462
"name": "react-on-rails-pro-node-renderer (brotli)",
5563
"path": "packages/react-on-rails-pro-node-renderer/lib/*.js",
5664
"webpack": false,
57-
"brotli": true
65+
"brotli": true,
66+
"running": false
5867
},
5968
{
6069
"name": "react-on-rails/client bundled (gzip)",
6170
"path": "packages/react-on-rails/lib/ReactOnRails.client.js",
6271
"import": "ReactOnRails",
63-
"gzip": true
72+
"gzip": true,
73+
"running": false
6474
},
6575
{
6676
"name": "react-on-rails/client bundled (brotli)",
6777
"path": "packages/react-on-rails/lib/ReactOnRails.client.js",
6878
"import": "ReactOnRails",
69-
"brotli": true
79+
"brotli": true,
80+
"running": false
7081
},
7182
{
7283
"name": "react-on-rails-pro/client bundled (gzip)",
7384
"path": "packages/react-on-rails-pro/lib/ReactOnRails.client.js",
7485
"import": "ReactOnRails",
75-
"gzip": true
86+
"gzip": true,
87+
"running": false
7688
},
7789
{
7890
"name": "react-on-rails-pro/client bundled (brotli)",
7991
"path": "packages/react-on-rails-pro/lib/ReactOnRails.client.js",
8092
"import": "ReactOnRails",
81-
"brotli": true
93+
"brotli": true,
94+
"running": false
8295
},
8396
{
8497
"name": "registerServerComponent/client bundled (gzip)",
8598
"path": "packages/react-on-rails-pro/lib/registerServerComponent/client.js",
8699
"import": "registerServerComponent",
87-
"gzip": true
100+
"gzip": true,
101+
"running": false
88102
},
89103
{
90104
"name": "registerServerComponent/client bundled (brotli)",
91105
"path": "packages/react-on-rails-pro/lib/registerServerComponent/client.js",
92106
"import": "registerServerComponent",
93-
"brotli": true
107+
"brotli": true,
108+
"running": false
94109
},
95110
{
96111
"name": "wrapServerComponentRenderer/client bundled (gzip)",
97112
"path": "packages/react-on-rails-pro/lib/wrapServerComponentRenderer/client.js",
98113
"import": "wrapServerComponentRenderer",
99-
"gzip": true
114+
"gzip": true,
115+
"running": false
100116
},
101117
{
102118
"name": "wrapServerComponentRenderer/client bundled (brotli)",
103119
"path": "packages/react-on-rails-pro/lib/wrapServerComponentRenderer/client.js",
104120
"import": "wrapServerComponentRenderer",
105-
"brotli": true
121+
"brotli": true,
122+
"running": true
106123
}
107124
]

bin/compare-bundle-sizes

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ BLUE='\033[0;34m'
2525
NC='\033[0m' # No Color
2626

2727
cleanup() {
28+
git restore .size-limit.json
2829
echo -e "\n${BLUE}Cleaning up...${NC}"
2930
git checkout "$CURRENT_BRANCH" --quiet 2>/dev/null || true
3031
if [ "$STASHED" = true ]; then
@@ -62,8 +63,7 @@ git checkout "$CURRENT_BRANCH" --quiet
6263
pnpm install --frozen-lockfile 2>&1 | grep -v "^$" | head -5 || true
6364
pnpm run build 2>&1 | grep -v "^$" | tail -3 || true
6465

65-
echo -e "${BLUE}Measuring current branch sizes...${NC}"
66-
pnpm exec size-limit --json > /tmp/current-sizes.json
66+
echo -e "${BLUE}Updating limits${NC}"
67+
node scripts/bundle-size.mjs set-limits --base /tmp/base-sizes.json
6768

68-
# Compare sizes using the bundle-size script
69-
node scripts/bundle-size.mjs compare --base /tmp/base-sizes.json --current /tmp/current-sizes.json
69+
pnpm exec size-limit

scripts/bundle-size.mjs

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import fs from 'fs';
2121
// Intentionally strict to catch any bundle size changes early.
2222
// For intentional size increases, use bin/skip-bundle-size-check to bypass the CI check.
2323
const DEFAULT_THRESHOLD = 512;
24+
const DEFAULT_TIME_PERCENTAGE_THRESHOLD = 0.1;
2425
const DEFAULT_CONFIG = '.size-limit.json';
2526

2627
// ANSI color codes
@@ -42,6 +43,16 @@ function formatSize(bytes) {
4243
return `${bytes} B`;
4344
}
4445

46+
/**
47+
* Format time to human-readable string
48+
*/
49+
function formatTime(ms) {
50+
if (ms >= 1000) {
51+
return `${(ms / 1000).toFixed(2)} s`;
52+
}
53+
return `${ms.toFixed(0)} ms`;
54+
}
55+
4556
/**
4657
* Format size difference with percentage
4758
*/
@@ -95,6 +106,32 @@ function readJsonFileOrExit(filePath) {
95106
}
96107
}
97108

109+
function createLimitEntry(entry, baseEntry, threshold, timePercentageThreshold) {
110+
const limit = baseEntry.size + threshold;
111+
console.log(`${entry.name}:`);
112+
console.log(` base size: ${formatSize(baseEntry.size)}`);
113+
console.log(` limit: ${formatSize(limit)}\n`);
114+
const sizeLimitEntry = { ...entry, limit: `${limit} B` };
115+
if (!sizeLimitEntry.running) {
116+
return sizeLimitEntry;
117+
}
118+
119+
const { loading, running } = baseEntry;
120+
const loadingMs = loading * 1000;
121+
const runningMs = running * 1000;
122+
console.log(` base loading time: ${formatTime(loadingMs)}`);
123+
console.log(` base running time: ${formatTime(runningMs)}`);
124+
const totalTime = loadingMs + runningMs;
125+
return [
126+
sizeLimitEntry,
127+
{
128+
...entry,
129+
name: `${entry.name} (time)`,
130+
limit: `${(totalTime * (1 + timePercentageThreshold)).toFixed(0)} ms`,
131+
},
132+
];
133+
}
134+
98135
/**
99136
* Command: set-limits
100137
* Updates .size-limit.json with dynamic limits based on base sizes
@@ -103,6 +140,8 @@ function setLimits(options) {
103140
const basePath = options.base;
104141
const configPath = options.config || DEFAULT_CONFIG;
105142
const threshold = parseInt(options.threshold, 10) || DEFAULT_THRESHOLD;
143+
const timePercentageThreshold =
144+
Number(options.timePercentageThreshold) || DEFAULT_TIME_PERCENTAGE_THRESHOLD;
106145

107146
if (!basePath) {
108147
console.error(`${colors.red}Error: --base <file> is required${colors.reset}`);
@@ -114,18 +153,18 @@ function setLimits(options) {
114153

115154
console.log(`${colors.blue}Setting dynamic limits (base + ${formatSize(threshold)}):${colors.reset}\n`);
116155

117-
const updatedConfig = config.map((entry) => {
118-
const baseEntry = baseSizes.find((b) => b.name === entry.name);
119-
if (baseEntry) {
120-
const limit = baseEntry.size + threshold;
121-
console.log(`${entry.name}:`);
122-
console.log(` base size: ${formatSize(baseEntry.size)}`);
123-
console.log(` limit: ${formatSize(limit)}\n`);
124-
return { ...entry, limit: `${limit} B` };
125-
}
126-
console.log(`${colors.yellow}${entry.name}: No base entry found, keeping original limit${colors.reset}`);
127-
return entry;
128-
});
156+
const updatedConfig = config
157+
.map((entry) => {
158+
const baseEntry = baseSizes.find((b) => b.name === entry.name);
159+
if (baseEntry) {
160+
return createLimitEntry(entry, baseEntry, threshold, timePercentageThreshold);
161+
}
162+
console.log(
163+
`${colors.yellow}${entry.name}: No base entry found, keeping original limit${colors.reset}`,
164+
);
165+
return entry;
166+
})
167+
.flat();
129168

130169
fs.writeFileSync(configPath, `${JSON.stringify(updatedConfig, null, 2)}\n`);
131170
console.log(`${colors.green}Updated ${configPath}${colors.reset}`);

0 commit comments

Comments
 (0)