Skip to main content

Bundle Baseline — 2026-07-07

Reference numbers for the performance TODO (performance-improvements-todo.md). Re-measure against this after each work block.

Build: npm run build:analyze (Next.js 16.2.10, webpack, production). Note: Next.js 16 removed the per-route size / First Load JS columns from next build output (deemed inaccurate with RSC). The numbers below are computed from .next/build-manifest.json and the emitted chunk files; analyzer reports live in .next/analyze/ (regenerate with the same command).

Shared first-load JS (every app route ships this)

From build-manifest.jsonrootMainFiles:

ChunkRawGzipped
webpack-*.js6.7 KB3.8 KB
4bd1b696-*.js (React/framework)195.2 KB62.1 KB
3794-*.js (shared app/vendor)217.5 KB59.8 KB
main-app-*.js0.5 KB0.2 KB
Total420.0 KB125.9 KB

Whole client build: 243 JS chunks, 3,206 KB raw.

Largest chunks (raw, on-demand unless noted)

ChunkRawContains
8600-*.js757.4 KB (266.8 KB gz)monaco-editor, sanitize-html, handlebars
1683-*.js370.2 KB (109.7 KB gz)libphonenumber-js, jszip
1863-*.js252.6 KBqrcode, handlebars
3794-*.js217.5 KBshared (in first load)
4bd1b696-*.js195.2 KBReact framework (in first load)
framework-*.js185.3 KBReact framework
5205-*.js137.7 KB
main-*.js129.9 KBwebpack runtime + chunk map
polyfills-*.js110.0 KB
574-*.js94.6 KB@clerk/nextjs
9055-*.js70.3 KB@mui/material

Findings against the TODO gates

  • 2.2 Monaco: chunk 8600 is async/on-demand — not in rootMainFiles and not referenced by any route's page_client-reference-manifest; only the webpack runtime chunk map in main-*.js knows its URL. Monaco is bundled locally (served from /_next/static/chunks/), not CDN. The barrel export does not put Monaco in any route's first load → restoring next/dynamic is not needed for first-load reasons. Caveat: 8600 also carries sanitize-html + handlebars; whichever route imports those client-side pulls the whole 757 KB chunk.
  • 2.3 Clerk localizations: not present in any client chunk — the ~50 locale imports in [locale]/layout.tsx cost server module evaluation and RSC payload only (a single locale object crosses to the client). Client bundle is unaffected; the per-locale import remains a server-side win.
  • 2.4 Small deps: i18n-iso-countries — not in any client chunk (server-only, confirmed). libphonenumber-js + jszip — client-side in async chunk 1683 (370 KB raw); subset entry point for libphonenumber is the candidate. qrcode, handlebars, sanitize-html — present in client chunks (1863, 8600), contrary to the "stay server-only" assumption; worth tracing which client imports pull them.