Code Splitting, Dynamic Imports & Bundle Analysis



This content originally appeared on DEV Community and was authored by Sachin Maurya

✍ Intro:

Ever noticed your website feels heavy even when it’s mostly static content?
That’s because you’re shipping everything at once, even if the user only needs 10%.

In this part of the series, we’ll explore Code Splitting, Dynamic Imports, and Bundle Analysis in React & Next.js — essential techniques that helped me shave off 40–80% of loading time across real projects.

You’ll learn:

  • What code splitting is and why it matters
  • How to use next/dynamic for dynamic imports
  • How to analyze and reduce your JavaScript bundles
  • Real examples from a live project I worked on at my company

⚙ What Is Code Splitting?

Code Splitting is a technique where your app is divided into small chunks instead of one big JavaScript file.

Benefits:

  • Faster initial load time
  • Load only what’s needed
  • Reduces Time to Interactive (TTI)

📦 Dynamic Imports with next/dynamic

✨ Real-World Use Case:

In one of our projects (Kreate Energy, built with Next.js + GraphQL), we had a heavy modal component that included chart libraries.

We didn’t want to load it until needed.

💡 The Fix:

import dynamic from 'next/dynamic';

const HeavyModal = dynamic(() => import('../components/HeavyModal'), {
  ssr: false,
  loading: () => <p>Loading...</p>,
});

This delayed the load until the modal was actually triggered.

Result?

  • ~45% reduction in initial JS size
  • ~2.5s faster TTI on mobile

🧠 How Dynamic Imports Work

When using dynamic(), Next.js creates a separate bundle for that module.

This chunk is only loaded when the component is rendered.

Bonus: Add ssr: false if it uses browser-only features like window or navigator.

🔍 Bundle Analysis

Use this to see what’s bloating your app.

🔧 Setup:

Install:

npm install @next/bundle-analyzer

Add this to next.config.js:

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
  // your config
});

Run:

ANALYZE=true npm run build

🧪 Insights:

  • You’ll get an interactive visualization of all packages
  • Identify huge libraries you can replace or lazy load
  • Example: Replacing moment.js with date-fns saved us 180 KB

🧰 Bonus Tips for Bundle Slimming

  • Avoid unnecessary dependencies (lodash → lodash-es or selective imports)
  • Move feature-rich pages to dynamic()
  • Compress images and lazy-load them
  • Remove unused code or dead routes

📊 Real-World Win: Kreate Technologies Website

I applied this on our corporate site:

  • Broke major sections into lazy-loaded dynamic components
  • Used next/image + responsive sizing
  • Preloaded only critical routes

Result:

  • 85 → 97 Lighthouse performance score
  • Faster page-to-page transitions
  • Easier debugging of production builds

💡 Takeaways

  • Use next/dynamic to split components like charts, modals, maps
  • Analyze your build output regularly — don’t ship what you don’t need
  • Don’t optimize too early — measure first, act later

🔮 What’s Next?

In Part 6, I’ll cover State Management Battle: Redux Toolkit vs Zustand vs React Query — real comparisons from my day job, with wins, fails, and how to choose wisely.

🙌 Let’s Connect

If you found this helpful, drop a 💬 below or DM me on LinkedIn.
I post real-world frontend struggles and solutions weekly.

🔗 Related Posts in This Series:


This content originally appeared on DEV Community and was authored by Sachin Maurya