When a site's JavaScript bundle feels heavy, the instinct is to reach for build-tool configuration — tree-shaking settings, minification levels, splitting strategies. Those matter, but they optimize what you've already decided to ship. The bigger win is almost always deciding to ship less in the first place.
A bundle analyzer will show you exactly what's in a JS bundle, sorted by size. Most teams have never run one against their own production build, which means most teams are shipping code they'd remove immediately if they could see it.
The usual suspects
- A full date/utility library (like a full moment.js or lodash import) when only two functions are actually used
- A component library imported wholesale for one component
- Duplicate copies of the same dependency at different versions, bundled separately
- Client-side code for functionality that could run entirely on the server (form validation, data formatting)
The most expensive JavaScript on a page is usually the JavaScript nobody remembers adding. Old A/B testing snippets and abandoned feature flags are common offenders.
Code-split by route, not by feeling
Most modern frameworks split JavaScript by route automatically, but heavy components — a rich text editor, a charting library, a video player — often get bundled into the main chunk anyway because nobody explicitly deferred them. Dynamic imports for anything not needed on first paint keep the initial bundle focused on what the first screen actually requires.
Measure before you refactor
Run a bundle analyzer before touching build configuration. The 20 minutes it takes to see what's actually shipped usually redirects the whole effort — from tuning a build pipeline to deleting three dependencies nobody remembers adding.