How to Reduce Bundle Size in Next js

When I first started working with Next.js, I loved how fast it was out of the box. But as the project grew, I noticed something — the bundle size kept increasing. Bigger bundles meant slower load times, worse performance on mobile, and sometimes even lower SEO scores. That’s when I realized: reducing bundle size isn’t just a technical tweak, it’s necessary for delivering a smooth user experience.
In this blog, I’ll share practical steps I use to cut down bundle size in Next.js projects. These are simple, effective techniques that can make your app feel lighter and faster.
Why Bundle Size Matters?
A heavy bundle makes your app slow before users even start interacting with it. Here’s why:
- Slower first load: The browser takes longer to download and parse JavaScript.
- Worse Core Web Vitals: Google cares about performance for SEO ranking.
- Bad mobile experience: On slow connections, big bundles are painful.
That’s why trimming bundle size directly impacts user satisfaction and search rankings.
Step 1: Analyze Your Bundle
You can’t optimize blindly. The first step is to see what’s inside your bundle.
- Use
@next/bundle-analyzer
: - Install it with
npm install @next/bundle-analyzer
. Updatenext.config.js
like this:
- Now run
ANALYZE=true npm run build
and you’ll see a treemap of your bundle. - Try
source-map-explorer
: - Another tool that helps you understand which files are contributing to bundle size.
The point is: know your biggest offenders before trying to fix things.
Step 2: Import Smarter
One common mistake is importing whole libraries when you only need a function or two.
- Bad way:
- Better way:
The second approach includes only what’s needed.
Next.js also supports tree-shaking and the optimizePackageImports
option in next.config.js
to automatically trim unused parts of libraries.
Step 3: Use Dynamic Imports
Not all code needs to load on the first page render. If something is only used after interaction, load it later.
- Dynamic component import:
This keeps the chart code out of your initial bundle. It’s only loaded when the component is actually used.
Dynamic imports are perfect for:
- Modals
- Charts / graphs
- Third-party widgets
- Rarely visited sections
Step 4: Keep Heavy Code on the Server
Next.js is powerful because of server and client separation. Use that wisely.
- Do data fetching in
getServerSideProps
orgetStaticProps
instead of fetching everything on the client. - Use Server Components (in the App Router) for logic that doesn’t need to run in the browser.
- Don’t ship unnecessary business logic to the client.
This not only reduces bundle size but also improves security and performance.
Step 5: Externalize or Replace Heavy Dependencies
Some libraries are simply too big. You have two choices: lazy-load them or replace them.
- Charts: Instead of a massive charting library, use a lighter one (or load only on demand).
- Date libraries: Moment.js is heavy; consider Day.js or date-fns.
- React → Preact: Some projects replace React with Preact for smaller bundles (though compatibility must be checked).
In next.config.js
, you can also externalize certain server-only packages so they don’t end up in the client bundle.
Step 6: Optimize Assets (Not Just JavaScript)
While this blog focuses on JS bundle size, optimizing assets helps overall performance too.
- Images: Always use Next.js
<Image>
component. It handles lazy loading, compression, and responsive sizing automatically. - Fonts: Import only the characters and weights you need. Google Fonts can also be self-hosted for better performance.
- CSS: Use Tailwind’s purge feature or other CSS tree-shaking to remove unused styles.
Step 7: Continuous Monitoring
Optimizing once isn’t enough. Every new dependency or feature can add weight.
- Set budgets: Use tools like
size-limit
to warn you if a bundle grows beyond a set size. - Re-run analyzer: Make it part of your workflow before deploying.
- Track performance: Keep an eye on Lighthouse scores, LCP (Largest Contentful Paint), and TTI (Time To Interactive).
Quick Checklist
Here’s a simple checklist I personally follow:
- Analyze with
@next/bundle-analyzer
. - Replace big dependencies with lighter ones.
- Import only what’s needed.
- Use
next/dynamic
for non-critical UI. - Keep heavy logic server-side.
- Optimize images, fonts, and CSS.
- Monitor bundle size continuously.
Final Thoughts
Reducing bundle size in Next.js isn’t about obsessing over every single byte. It’s about focusing on what really matters: faster load times, better SEO, and happier users.
Start with the big wins like lazy-loading components and trimming dependencies. Then fine-tune with import optimizations and asset handling. Once you put these into practice, you’ll notice a clear difference in how smooth and snappy your app feels.