Skip to content

The console "performance budget" weighs only the index-*.js entry chunk, so it is structurally blind to the other ~3.8 MB gzipped the entry pulls in statically #5324

Description

@os-support-ai

Found while measuring #5266 (PR #5323). Filing rather than fixing — out of that card's scope.

.github/workflows/performance-budget.yml is named Bundle Analysis and its step is Check console performance budget, but what it actually measures is one file:

MAX_ENTRY_GZIP_KB=350
ENTRY_FILE=$(find "$DIST_DIR" -name 'index-*.js' -not -name '*.gz' -not -name '*.br'| head -1)
GZIP_BYTES=$(gzip -c "$ENTRY_FILE"| wc -c)

The entry chunk is not what a page load costs. index-*.js statically imports a closure of other chunks, and index.html cannot render without them — the browser fetches and parses all of it before the app runs.

Measured on 3fbbea1f3, walking static imports only from index.html:

gzipped
index-*.js alone — what the budget weighs~110 KB, comfortably under the 350 KB line
the full eager closure — 58 chunks3,957,301 bytes

So the budget passes on ~2.8% of the payload it claims to govern.

This is not theoretical: #5266 was 89.0 KiB gzipped added to every console page load, and it landed in vendor-objectstack-*.js. The budget could not have caught it, and did not. Any regression that lands outside index-*.js — which is most of them, since advancedChunks deliberately routes vendor and workspace code into named chunks — is invisible to this gate.

Worth deciding rather than assuming: a budget over the whole eager closure would need a threshold set from the current 3.96 MB, which is a different conversation from the 350 KB entry number. Options include budgeting the closure as a whole, budgeting per named chunk, or ratcheting (fail only on growth vs. main). The ratchet form is probably the most useful and the least likely to need re-tuning, but that is a call for whoever picks this up.

PR #5323 adds a targeted build-time assertion for the specific @objectstack/lint case, which is why that one is now guarded. This issue is about the general gate.

Reproduction of the closure figure is in PR #5323 — eager closure = BFS from the <script type="module"> in dist/index.html over static imports only (es-module-lexer, d === -1), gzip read from the build's own emitted .gz siblings.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions