vibecheck0.3.0
Performanceresource-bloatwarning

Large JavaScript bundles in Vanilla JS

Every kilobyte of JavaScript has to be downloaded, parsed, compiled, and executed before the page is interactive — and on a mid-range phone that work is many times slower than on your laptop. When one bundle ships the whole app up front, first interaction is delayed for everyone. AI-built apps balloon here by importing entire libraries for one helper and never code-splitting by route.

Symptoms

  • A single .js chunk is hundreds of KB or more in the Network panel
  • Slow time-to-interactive; the page looks ready but doesn’t respond yet
  • The whole app’s code loads on the first route, before it’s needed
  • A bundle analyzer shows one or two dependencies dominating the graph

How VibeCheck catches it

In your widget · Problems

warningresource-bloatLarge JS resource (250KB)

To your coding agent · MCP

agent › get_detected_issues
{ detector: "resource-bloat", issue: "Large JS resource (250KB)", threshold: "≥ 100KB transferred per JS/CSS resource in production (≥ 500KB in dev)" }

The same string in your widget and in your agent’s context — no screenshot, no copy-paste.

Root causes

  • No route-level code splitting — the entire app ships in one chunk
  • Barrel/whole-library imports that defeat tree-shaking
  • Heavy components (editors, charts, maps) bundled into the initial load
  • Duplicate copies of a dependency at different versions

The fix for Vanilla JS

Use dynamic import() to load heavy modules only when needed; modern bundlers split them into separate chunks automatically.

js
button.addEventListener('click', async () => {
  const { openEditor } = await import('./editor.js') // separate chunk
  openEditor()
})

Steps

  1. Run a bundle analyzer to identify the largest chunks and dependencies
  2. Code-split by route and lazy-load heavy, non-critical components
  3. Replace whole-library imports with named/deep imports and remove duplicates

See the general, framework-agnostic fix →

FAQ

Why is the threshold higher in development?
Dev bundles are unminified and include source maps and HMR runtime, so they’re legitimately large. VibeCheck raises the bar to 500KB on localhost and uses 100KB for production, where the size actually ships to users.
What’s the fastest win?
Route-level code splitting. It ensures a user landing on one page doesn’t download the code for every other page. After that, lazy-load the heaviest individual components (editors, charts, maps).
How do I find what’s making the bundle big?
Run a bundle analyzer (@next/bundle-analyzer, rollup-plugin-visualizer, or source-map-explorer). It shows a treemap of every module so you can spot an oversized dependency or an accidental whole-library import.