fix(build): stabilize release bundle gates

This commit is contained in:
Marc-André Bombeck committed 2026-07-29 16:19:30 +02:00
1 parent 271f0ed28a
commit f54555d187
4 files changed
+20 -4

No files matched your search

+4 -1
View File
@@ -74,7 +74,10 @@ jobs:
# the versioned service-worker stamp AND the static i18n catalog
# assets (public/i18n/<locale>.js) the client boots from — without
# them every UI interaction waits on missing catalogs.
- run: pnpm build
# The repository-wide Next type worker exceeds V8's ~4 GiB default
# old-space ceiling. Keep the larger heap scoped to this production
# build only; tests and the runtime retain their normal limits.
- run: NODE_OPTIONS=--max-old-space-size=8192 pnpm build
# Client-bundle budget gate — rides this job because it is the one
# place CI already has a production build on disk. Catches the
+4 -1
View File
@@ -43,7 +43,10 @@ RUN pnpm db:generate
# Build Next.js
ENV NEXT_TELEMETRY_DISABLED=1
RUN pnpm build
# Keep the larger V8 heap build-only. Next's repository-wide TypeScript
# worker exceeds the default ~4 GiB old-space ceiling; the runner stage below
# starts fresh and therefore does not inherit this setting.
RUN NODE_OPTIONS=--max-old-space-size=8192 pnpm build
# ── Stage 3: Production runner ─────────────────────────────
FROM node:22-alpine@sha256:16e22a550f3863206a3f701448c45f7912c6896a62de43add43bb9c86130c3e2 AS runner
+2 -2
View File
@@ -1,11 +1,11 @@
{
"$comment": "Client-bundle budgets, enforced by scripts/check-bundle-budget.mjs (--check) after `next build` in CI. Values are KB gzip and include the shared rootMainFiles baseline. Re-measured at v1.34.0: / 430, /insights 417, /measurements 417, /insights/mood 435, total 3130, baseline 130. The aggregate rose 70 KB from v1.33.2's 3060 for the same reason the v1.33.0 raise did: new surfaces, not a duplicated library. This release adds the reference-composite health-score card (per-pillar detail cards, method notes), the structured anamnesis facts editor, custom-metric correlation opt-in, and pattern-dismissal controls on two card types. Every per-route cap still passes with 23-30 KB headroom, and the Recharts chunk count is still 1 and structurally guarded. Raised 3120 to 3140 for that reason, not to make a red gate pass — the per-route budgets are the real ceiling on any single page; the aggregate exists to catch exactly the duplicated-library case that did not happen here.",
"$comment": "Client-bundle budgets, enforced by scripts/check-bundle-budget.mjs (--check) after `next build` in CI. Values are KB gzip and include every emitted lazy route and locale chunk, while route budgets include the shared rootMainFiles baseline. Re-measured at v1.34.1: / 431, /insights 420, /measurements 417, /insights/mood 438, total 3238, baseline 130, lazy catalogs 792. The 108 KB aggregate rise from v1.34.0's 3130 is not one user load: the explicit assessment error/timeout/poll-exhaustion contract adds 2.7-4.4 KB to each of roughly forty mutually exclusive metric route chunks, which the whole-build sum counts independently. Catalogs account for only about 2 KB of the delta, no catalog is statically route-referenced, and Recharts remains exactly one fingerprinted chunk. A measured single next/dynamic assessment boundary was reverted because it raised the artifact further to 3243 KB while saving only about 1 KB per route. The aggregate cap therefore moves narrowly from 3140 to 3260 (22 KB headroom); per-route ceilings, the static-catalog guard, and the one-Recharts-chunk guard remain unchanged.",
"routesKbGz": {
"/page": 460,
"/insights/page": 445,
"/measurements/page": 445,
"/insights/mood/page": 460
},
"totalClientKbGz": 3140,
"totalClientKbGz": 3260,
"maxRechartsChunks": 1
}
+10
View File
@@ -133,12 +133,18 @@ for (const { route, file } of manifests) {
const chunkDir = join(BUILD_DIR, "static", "chunks");
let totalGz = 0;
let rechartsChunks = 0;
let catalogChunks = 0;
let catalogGz = 0;
let largest = { file: "-", gz: 0 };
for (const f of readdirSync(chunkDir)) {
if (!f.endsWith(".js")) continue;
const info = chunkInfo(join("static", "chunks", f));
totalGz += info.gz;
if (info.recharts) rechartsChunks += 1;
if (info.catalog) {
catalogChunks += 1;
catalogGz += info.gz;
}
if (info.gz > largest.gz) largest = { file: f, gz: info.gz };
}
const rootCatalogRef = rootFiles.some((f) => chunkInfo(f).catalog);
@@ -150,6 +156,10 @@ const budget = existsSync(BUDGET_PATH)
console.log(`shared baseline (rootMainFiles): ${fmt(rootGz)} gz`);
console.log(`all client chunks: ${fmt(totalGz)} gz`);
console.log(
` lazy message catalogs: ${fmt(catalogGz)} gz (${catalogChunks} chunks)`,
);
console.log(` other client chunks: ${fmt(totalGz - catalogGz)} gz`);
console.log(
`largest chunk: ${fmt(largest.gz)} gz ${largest.file}`,
);