Why Your NextJS Builds Went From Fast to Fucked

I was debugging a build that was taking 45+ minutes on a good day, sometimes longer. This was during our Black Friday deploy and everything went to shit. The build that used to finish in maybe 3-4 minutes was now eating up our entire CI budget and killing deployments.

Here's the thing about NextJS build performance - it sneaks up on you. You add a few dependencies, maybe some custom webpack config, a couple of dynamic imports, and suddenly your builds are crawling. But the real killer isn't usually what you think it is.

Build Performance Issues

The Real Culprits Behind Slow Builds

TypeScript compilation eating memory like a starved beast. I've seen builds where TypeScript was consuming 6GB+ of RAM trying to type-check everything at once. The default TypeScript config in NextJS is way too aggressive for large codebases.

Dependency resolution hell. One project I worked on was resolving packages 50+ times during build. Same package, same version, but webpack couldn't figure its shit out. This adds minutes to every build and is a common NextJS performance bottleneck.

CSS-in-JS libraries doing way too much work. Looking at you, @emotion/react. These libraries are convenient until they start parsing and generating CSS for every single component during build time.

Static analysis tools running in the wrong order. ESLint + TypeScript + Prettier all fighting each other during build instead of working together. I've seen this add 10+ minutes to builds when not properly configured.

Source map generation for files that don't need it. NextJS generates source maps for everything by default, including vendor chunks. This is insane for production builds and a major performance killer.

The worst part? Most of the "solutions" you'll find online are either outdated or written by people who haven't actually dealt with large NextJS apps in production. Half the advice breaks in Next 14, and the other half only works if you're building a todo app. The official performance docs are better but still miss the production gotchas.

TypeScript Logo

What Actually Breaks in Real Projects

Memory exhaustion during large imports. Node runs out of heap space when processing large dependency trees. The default Node heap limit is usually too small for modern NextJS apps with heavy dependencies.

GitHub Actions timing out after 6 hours. Yeah, builds can get that slow. I've seen it happen when webpack optimization goes wrong and starts building circular dependencies.

Development server taking 5+ minutes to start. This isn't just a build issue - it kills developer productivity when you're waiting half your standup for the dev server to boot. NextJS dev server optimization is critical for team velocity.

Hot reloading breaking completely. Fast refresh stops working when your build config gets too complex, forcing full page reloads for every change. This is usually a sign your webpack configuration is fucked.

The solutions I'm about to show you actually work because I've used them to fix real production builds that were completely fucked.

Solutions That Actually Work (No Bullshit)

These fixes are ranked by what actually works in production. I've wasted way too many hours on solutions that sound good in theory but break everything in practice.

Node.js Memory Management

Fix #1: Stop TypeScript From Destroying Your Build

TypeScript is probably your biggest performance killer. The default config is way too aggressive for large projects.

First, bump your Node heap limit:

export NODE_OPTIONS=\"--max_old_space_size=8192\"

Next, fix your TypeScript config. Add this to your tsconfig.json:

{
  \"compilerOptions\": {
    \"incremental\": true,
    \"tsBuildInfoFile\": \".next/cache/tsconfig.tsbuildinfo\"
  },
  \"ts-node\": {
    \"swc\": true
  }
}

This enables incremental compilation and uses SWC instead of the slower TypeScript compiler. Cut our build times from like 20 minutes down to maybe 6-7 minutes. More details on TypeScript performance optimization.

Webpack Bundle Optimization

Fix #2: Make Webpack Less Stupid

NextJS webpack config is optimized for small projects, not real applications. The default webpack configuration needs tweaking for production workloads.

// next.config.js
module.exports = {
  webpack: (config, { dev, isServer }) => {
    // Stop webpack from being an idiot about caching
    config.cache = {
      type: 'filesystem',
      buildDependencies: {
        config: [__filename]
      }
    }
    
    // Split chunks properly - this shit will murder build times otherwise
    if (!dev && !isServer) {
      config.optimization.splitChunks.chunks = 'all'
      config.optimization.splitChunks.cacheGroups = {
        framework: {
          chunks: 'all',
          name: 'framework',
          test: /(?<!node_modules.*)[\\/]node_modules[\\/](react|react-dom|scheduler|prop-types|use-subscription)[\\/]/,
          priority: 40,
          enforce: true
        }
      }
    }

    return config
  }
}

This enables filesystem caching and fixes the chunk splitting that NextJS fucks up by default. Learn more about webpack optimization.

CSS-in-JS Optimization

Fix #3: Deal With CSS-in-JS Performance

CSS-in-JS libraries are convenient until they destroy your build times. Here's what actually works for styled-components performance and Emotion optimization:

For styled-components: Enable the SWC plugin:

// next.config.js
const nextConfig = {
  compiler: {
    styledComponents: true
  }
}

For Emotion: Switch to the SWC version:

npm uninstall @emotion/babel-plugin
npm install @emotion/react @emotion/styled

Then update your config:

// next.config.js
const nextConfig = {
  compiler: {
    emotion: true
  }
}

This cut CSS processing time by more than half on projects I've worked on. The SWC compiler is much faster than Babel for CSS-in-JS processing.

Code Splitting Strategy

Fix #4: Fix Your Import Strategy

Dynamic imports are great until you have hundreds of them. Here's what I learned the hard way about code splitting optimization:

Batch your dynamic imports:

// Instead of this (slow as hell)
const ComponentA = dynamic(() => import('./ComponentA'))
const ComponentB = dynamic(() => import('./ComponentB'))
const ComponentC = dynamic(() => import('./ComponentC'))

// Do this (much faster)
const DynamicComponents = dynamic(() => 
  Promise.all([
    import('./ComponentA'),
    import('./ComponentB'), 
    import('./ComponentC')
  ]).then(([A, B, C]) => ({ A: A.default, B: B.default, C: C.default }))
)

Pre-bundle heavy dependencies:

// next.config.js
module.exports = {
  experimental: {
    optimizePackageImports: ['lodash', 'date-fns', 'react-icons']
  }
}

This tells NextJS to pre-bundle these packages instead of processing them every time.

Fix #5: Stop Generating Useless Source Maps

Source maps are great for debugging but they're killing your production builds:

// next.config.js
module.exports = {
  productionBrowserSourceMaps: false, // Disable this shit in production
  webpack: (config, { dev }) => {
    if (!dev) {
      config.devtool = false // Nuclear option - no source maps at all
    }
    return config
  }
}

For projects where you need some source mapping:

// Only for your code, not vendor code
config.devtool = 'hidden-source-map'

GitHub Actions CI/CD

Fix #6: Make CI Actually Usable

If you're using GitHub Actions, the default setup is trash for NextJS builds:

## .github/workflows/build.yml
- name: Setup Node.js
  uses: actions/setup-node@v3
  with:
    node-version: '18'
    cache: 'npm'

- name: Configure build environment
  run: |
    export NODE_OPTIONS=\"--max_old_space_size=8192\"
    export NEXT_TELEMETRY_DISABLED=1

- name: Install dependencies
  run: npm ci --prefer-offline --no-audit

- name: Build
  run: |
    npm run build
  env:
    NODE_OPTIONS: --max_old_space_size=8192

The key is disabling telemetry (saves a few seconds) and using npm ci with offline preference.

Performance Monitoring

When Nothing Works: Nuclear Options

Sometimes your build is just fundamentally broken. Here's when to give up and try something else:

If you're on Next 12 or older: Upgrade. Seriously. The build improvements in Next 13+ are worth the migration pain.

If you're using too many dynamic imports: Consider switching to static imports with code splitting at the page level instead.

If your bundle size is over 10MB: You probably need to rethink your architecture. Consider micro-frontends or splitting your app into multiple Next apps.

If builds still take 30+ minutes after all this: Your codebase might be too big for NextJS. Consider Vite or switching to a different build tool entirely.

I've seen projects where the answer was literally "start over with a different framework" because the technical debt was too deep to fix economically.

Quick Fixes for Common Build Problems

Q

Why is my NextJS build suddenly taking forever?

A

Usually it's one of three things: you added a heavy dependency that's not tree-shaking properly, your Type

Script config is too aggressive, or you hit a memory limit. Check your bundle analyzer first

  • run npm run build and look at what's actually being bundled.
Q

My build runs out of memory and crashes. What do I do?

A

Bump your Node heap size: export NODE_OPTIONS="--max_old_space_size=8192". If that doesn't work, you probably have a memory leak in your webpack config or a circular dependency. Use --inspect to debug where memory is being eaten.

Q

GitHub Actions keeps timing out after 6 hours. Is this normal?

A

Fuck no. A NextJS build should not take 6 hours. You've got something seriously wrong with your dependency resolution or webpack is stuck in an infinite loop. Check your webpack bundle analyzer and look for circular dependencies.

Q

Should I use Turbopack for faster builds?

A

Only if you're on Next 13+ and willing to deal with beta stability issues. Turbopack is faster when it works but breaks with complex webpack configs. I'd fix your existing build first before adding more experimental tools.

Q

My dev server takes 5+ minutes to start. Help?

A

This usually means your initial bundle is too big or you have too many dynamic imports. Try reducing your page-level imports and lazy load heavy components. Also check if you have any synchronous file operations in your components.

Q

Does upgrading NextJS versions help with build performance?

A

Usually yes, but not always. Next 13+ has better bundling and caching. Next 14 improved TypeScript performance significantly. But migrations can break shit, so test thoroughly. I've seen builds get slower after upgrades when custom webpack configs break.

Q

My builds work locally but fail in CI. Why?

A

Different Node versions, different memory limits, or missing environment variables. CI environments usually have less RAM than your laptop. Make sure you're setting NODE_OPTIONS in your CI config and using the same Node version everywhere.

Q

How do I know if webpack caching is working?

A

Look for .next/cache directory growth between builds. If it's not growing or gets deleted, your caching is broken. Check that you're not clearing the cache unnecessarily in your CI config.

Q

My CSS builds are taking forever. What's wrong?

A

CSS-in-JS libraries like styled-components or Emotion can kill build performance if not configured properly. Make sure you're using the SWC compiler plugins instead of Babel transforms. PostCSS with too many plugins can also be slow as hell.

Q

Should I disable source maps for production?

A

Probably. Source maps can double your build time and bundle size. Unless you really need them for debugging production issues, set productionBrowserSourceMaps: false in your Next config.

Q

My bundle size keeps growing. How do I stop it?

A

Use @next/bundle-analyzer to see what's actually being bundled. Look for duplicate dependencies, unused code that's not being tree-shaken, and libraries that import everything (looking at you, Lodash). Consider using lodash-es or individual function imports instead.

Q

Can I run builds in parallel to speed things up?

A

Not really with NextJS. The build process is sequential by design. You can parallelize things like linting and testing, but the actual NextJS build has to run single-threaded. Focus on making the build itself faster instead.

Q

Is there a way to skip unnecessary rebuilds?

A

NextJS has built-in caching, but it's not always smart about it. You can use tools like nx or turborepo for better caching strategies, but they add complexity. For most projects, fixing the core build performance issues is more effective than adding build orchestration tools.

What Actually Works vs What's a Waste of Time

Impact Level

Fix/Option

Description

High Impact Fixes

Node memory increase

Takes 30 seconds to implement, cuts build times by 30%+ if you're hitting memory limits. Literally just export NODE_OPTIONS="--max_old_space_size=8192" and you're done.

High Impact Fixes

TypeScript incremental compilation

Enable this in your tsconfig and watch your rebuilds get stupid fast. Goes from recompiling everything to only compiling what changed. Saves me like 15 minutes on large codebases.

High Impact Fixes

Webpack filesystem caching

This one's a game changer if you're doing repeated builds. First build still sucks, but subsequent builds fly. Perfect for CI environments where you can cache between runs.

High Impact Fixes

CSS-in-JS SWC plugins

If you're using styled-components or Emotion, switching from Babel to SWC transforms cuts CSS processing time in half. Maybe more depending on how much CSS-in-JS you're using.

Medium Impact

Bundle splitting optimization

Helps with final bundle size and can speed up builds by reducing duplicate work. More complex to set up right, but worth it for larger apps.

Medium Impact

Dynamic import batching

Instead of hundreds of individual dynamic imports, batch them together. Reduces the number of chunks webpack has to manage. Can shave off a few minutes on apps with tons of lazy loading.

Medium Impact

Production source map removal

Disabling source maps in production can cut build times significantly. Trade-off is harder debugging, but most apps don't need production source maps anyway.

Medium Impact

Dependency optimization

Using optimizePackageImports for heavy libraries like Lodash or date-fns. Prevents NextJS from processing these every time. Moderate setup effort, decent payoff.

Low Impact

Turbopack

Still beta, breaks with complex webpack configs. When it works it's fast, but I've wasted more time debugging Turbopack issues than I've saved from faster builds. Wait until it's stable.

Low Impact

Parallel webpack plugins

Sounds good in theory, doesn't help much in practice with NextJS because of how their build process works. Plus adds complexity that's not worth the minimal gains.

Low Impact

Module federation

Overkill for most projects and adds a lot of complexity. Only worth it if you're building a true micro-frontend architecture with multiple teams.

Low Impact

Custom webpack loaders for optimization

Usually breaks more than it helps. NextJS already has decent default loaders. Only mess with this if you really know what you're doing.

Complete Waste of Time

Upgrading hardware to fix software problems

Yeah, throwing more CPU cores at a bad webpack config doesn't magically make it fast. Fix the config first, upgrade hardware later if needed.

Complete Waste of Time

Complicated caching strategies

Most projects don't need Redis caching or distributed build caches. The built-in NextJS caching works fine if you configure it properly.

Complete Waste of Time

Precompiled dependency serving

Serving pre-bundled versions of your dependencies sounds smart but adds way too much complexity for minimal gains. Not worth the maintenance overhead.

Complete Waste of Time

Build-time code optimization

Running additional optimization passes during build. This stuff usually makes builds slower while providing marginal runtime performance gains.

The "Fuck It" Options

Switch to Vite

If your NextJS build is fundamentally broken and you can't fix it economically, Vite builds are usually way faster. Migration effort varies but might be worth it.

The "Fuck It" Options

Split your monolith

If your app is too big for NextJS to handle efficiently, consider splitting it into multiple smaller NextJS apps or switching to micro-frontends.

The "Fuck It" Options

Give up on SSG

Static generation can be slow as hell for large sites. Consider switching to SSR or client-side rendering for pages that don't actually need to be static.

The "Fuck It" Options

Rewrite with different tools

Sometimes the answer is "this codebase has too much technical debt to fix economically." Starting fresh with better practices might be faster than debugging build performance forever.

Related Tools & Recommendations

compare
Similar content

Next.js, Nuxt, SvelteKit, Remix vs Gatsby: Enterprise Guide

18 months in Gatsby hell, 6 months testing everything else - here's what actually works for enterprise teams

Next.js
/compare/nextjs/nuxt/sveltekit/remix/gatsby/enterprise-team-scaling
100%
review
Recommended

Vite vs Webpack vs Turbopack: Which One Doesn't Suck?

I tested all three on 6 different projects so you don't have to suffer through webpack config hell

Vite
/review/vite-webpack-turbopack/performance-benchmark-review
73%
tool
Similar content

Webpack Performance Optimization: Fix Slow Builds & Bundles

Optimize Webpack performance: fix slow builds, reduce giant bundle sizes, and implement production-ready configurations. Improve app loading speed and user expe

Webpack
/tool/webpack/performance-optimization
60%
compare
Similar content

Remix vs SvelteKit vs Next.js: SSR Performance Showdown

I got paged at 3AM by apps built with all three of these. Here's which one made me want to quit programming.

Remix
/compare/remix/sveltekit/ssr-performance-showdown
57%
tool
Similar content

Vite: The Fast Build Tool - Overview, Setup & Troubleshooting

Dev server that actually starts fast, unlike Webpack

Vite
/tool/vite/overview
57%
tool
Similar content

Next.js Overview: Features, Benefits & Next.js 15 Updates

Explore Next.js, the powerful React framework with built-in routing, SSR, and API endpoints. Understand its core benefits, when to use it, and what's new in Nex

Next.js
/tool/nextjs/overview
53%
integration
Recommended

Stop Your APIs From Breaking Every Time You Touch The Database

Prisma + tRPC + TypeScript: No More "It Works In Dev" Surprises

Prisma
/integration/prisma-trpc-typescript/full-stack-architecture
51%
tool
Similar content

Turbopack: Why Switch from Webpack? Migration & Future

Explore Turbopack's benefits over Webpack, understand migration, production readiness, and its future as a standalone bundler. Essential insights for developers

Turbopack
/tool/turbopack/overview
51%
tool
Similar content

Remix Overview: Modern React Framework for HTML Forms & Nested Routes

Finally, a React framework that remembers HTML exists

Remix
/tool/remix/overview
47%
tool
Similar content

Astro Overview: Static Sites, React Integration & Astro 5.0

Explore Astro, the static site generator that solves JavaScript bloat. Learn about its benefits, React integration, and the game-changing content features in As

Astro
/tool/astro/overview
44%
integration
Similar content

Supabase Next.js 13+ Server-Side Auth Guide: What Works & Fixes

Here's what actually works (and what will break your app)

Supabase
/integration/supabase-nextjs/server-side-auth-guide
44%
tool
Similar content

SvelteKit: Fast Web Apps & Why It Outperforms Alternatives

I'm tired of explaining to clients why their React checkout takes 5 seconds to load

SvelteKit
/tool/sveltekit/overview
42%
compare
Similar content

Astro, Next.js, Gatsby: Static Site Generator Benchmark

Just use fucking Astro. Next.js if you actually need server shit. Gatsby is dead - seriously, stop asking.

Astro
/compare/astro/nextjs/gatsby/static-generation-performance-benchmark
42%
tool
Similar content

Migrate from Create React App to Vite & Next.js: A Practical Guide

Stop suffering with 30-second dev server startup. Here's how to migrate to tools that don't make you want to quit programming.

Create React App
/tool/create-react-app/migration-guide
42%
tool
Recommended

TypeScript - JavaScript That Catches Your Bugs

Microsoft's type system that catches bugs before they hit production

TypeScript
/tool/typescript/overview
41%
tool
Recommended

JavaScript to TypeScript Migration - Practical Troubleshooting Guide

This guide covers the shit that actually breaks during migration

TypeScript
/tool/typescript/migration-troubleshooting-guide
41%
review
Recommended

Which JavaScript Runtime Won't Make You Hate Your Life

Two years of runtime fuckery later, here's the truth nobody tells you

Bun
/review/bun-nodejs-deno-comparison/production-readiness-assessment
40%
troubleshoot
Similar content

Fix Next.js App Router Hydration Mismatch Errors & Debug Guide

Your Components Work Fine Until You Deploy Them? Welcome to Hydration Hell

Next.js App Router
/troubleshoot/nextjs-app-router-migration-issues/hydration-mismatch-solutions
33%
tool
Recommended

Webpack - The Build Tool You'll Love to Hate

depends on Webpack

Webpack
/tool/webpack/overview
30%
tool
Similar content

React Production Debugging: Fix App Crashes & White Screens

Five ways React apps crash in production that'll make you question your life choices.

React
/tool/react/debugging-production-issues
27%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization