The five expensive habits killing your web app's speed
By the Imustech web engineering team · Updated December 2025
Whenever we inherit a codebase, we run the same one-week performance audit before we ship a single feature. In eight out of ten cases we recover 40% or more of Time-to-Interactive in that first week — often without any real refactor. Here are the five habits we look for first.
1. Everything imported everywhere.
Node modules pulled into the client bundle: `lodash`, `moment`, entire UI libraries, tree-shakeable icon packs that never got tree-shaken. Symptom: a `main.js` bundle over 500 KB gzipped. Fix: run `npm-check`, replace `moment` with `date-fns` or `dayjs`, migrate icons to on-demand imports. Cost: a day. Reward: 200–400 ms of TTI.
The single fastest way to slow a web app down is to say "yes" to every npm package a developer suggests. The second is to say "yes" to every dashboard chart library.
2. Server-rendering things that should be static.
Marketing pages, docs, product landing pages hitting a full SSR render on every visit. Every one of these should be either statically generated (SSG) or incremental static regeneration (ISR). Fix: identify pages that don't need per-request data and shift them to `getStaticProps`, `generateStaticParams` or your framework's equivalent.
3. The infinite waterfall on first load.
User lands on the homepage. Browser requests HTML → HTML requests JS → JS requests API → API triggers a second API → second API needs auth → auth roundtrip. Six sequential hops. Fix: preload critical data on the server, hydrate the client with it, and never let auth be more than one round-trip.
4. Images without discipline.
Full-resolution 4000×3000 JPGs served to phones. No `srcset`. No lazy-loading. No modern format (AVIF/WebP). This is the single biggest LCP killer we see. Fix: use your framework's image component (Next.js `Image`, Nuxt `NuxtImg`), set explicit sizes, and serve modern formats.
5. Blocking third-party scripts loaded synchronously.
Marketing loaded a chat widget, an analytics tool, an experimentation platform and a heat-mapper. All synchronous. All in `<head>`. Cumulative cost: 1.5 seconds of TTI. Fix: audit every third-party. Load asynchronously with `defer`, or better, only after user interaction. Kill the ones no-one has looked at in a year.
The one-week audit
- Day 1: Bundle analysis (webpack-bundle-analyzer or equivalent).
- Day 2: Route audit — SSR vs SSG vs CSR for every page.
- Day 3: Network waterfall analysis on cold and warm loads.
- Day 4: Image + font audit with Lighthouse + WebPageTest.
- Day 5: Third-party script inventory + kill list.
- Day 6–7: Ship the top five wins behind a feature flag.
The result
A tangible LCP drop, a smaller bundle, a cleaner network waterfall — usually delivered before you've had time to argue about whether to migrate off React. Do this audit before you do anything ambitious. It changes the conversation.
Fixed-fee, one week, keep the report.
We audit, prioritise and ship the top wins — with a written report you keep, whether or not we work together afterwards.
Book a performance audit →