Why Your Next.js App is Slow: Real Fixes π
We love React because of its ecosystem, but importing heavy libraries can silently kill your performance.
The Problem I Faced
My portfolio score on Lighthouse dropped to 65. The "Time to Interactive" was 4 seconds. I hadn't realized that importing a single icon from a large library or a heavy date formatter was bloating the entire initial load.
Understanding Bundle Analysis
I used @next/bundle-analyzer to visualize what was ending up in the client's browser.
Code Example 1: Dynamic Imports
Heavy components (like a Map or a large Chart) shouldn't load until they are needed or visible.
tsx
import dynamic from 'next/dynamic';
// This component won't poison the initial bundle
const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
loading: () => <p>Loading Chart...</p>,
ssr: false // If it relies on window/browser APIs
});
export default function Analytics() {
return (
<div>
<h1>Stats</h1>
<HeavyChart />
</div>
)
}Code Example 2: Optimizing Imports
Bad:
ts
import { format } from 'date-fns'; // Often tree-shakes well, but verify!
import * as Lodash from 'lodash'; // Imports EVERYTHING βGood:
ts
import format from 'date-fns/format';
import debounce from 'lodash/debounce'; // Import specific function β
Common Pitfalls
-
Mistake 1: Optimization before measurement.
- Don't: Guess what's slow.
- Do: Run the analyzer first.
-
Mistake 2: Large Lottie Files.
- JSON animations can be huge. Use
.lottie(dotLottie) format or lazy load the player.
- JSON animations can be huge. Use
Pro Tips
- Fonts: Use
next/font! It automatically optimizes and hosts Google fonts, removing layout shift (CLS). - Images: Always use
next/image. It handles resizing and lazy loading automatically.
Wrapping Up
Performance isn't a one-time fix; it's a habit. Keep an eye on your bundle size with every PR.
Tech Stack: Next.js, Webpack, Lighthouse
