JavaScript Heap Out of Memory
The Error: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
This kills your builds when dealing with large codebases or problematic dependencies. This is a well-documented Node.js limitation that affects many JavaScript build tools. Here's what actually works:
Quick Fix:
NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build
Permanent Fix (add to package.json):
{
\"scripts\": {
\"build\": \"NODE_OPTIONS='--max-old-space-size=8192' rollup -c\"
}
}
Why This Happens:
- Large TypeScript projects with complex type checking (TypeScript performance docs)
- Circular dependencies creating memory loops (Rollup circular dependency handling)
- Bad plugins that don't clean up properly (Plugin development best practices)
- Processing massive files (like huge JSON imports) (JSON plugin limitations)
Real Example: Had a client with a 15MB JSON config file being imported directly. Moving it to dynamic imports fixed the memory issue and cut build time from 12 minutes to 2.
Build Hangs Forever
Symptoms: Build starts, shows progress, then freezes at 90% with no error
Nuclear Option (works 90% of the time):
rm -rf node_modules package-lock.json
npm install
npm run build
Smarter Debugging:
## Run with verbose logging
rollup -c --verbose
## Check for circular dependencies
npm install --save-dev madge
madge --circular --format es6 src/
Circular dependency detection is crucial - the madge tool integrates well with most build systems and helps identify problematic import cycles.
Common Causes:
- Circular imports creating infinite loops (ES module circular dependency behavior)
- Plugin conflicts (especially TypeScript + Babel) (known plugin compatibility issues)
- Corrupted node_modules cache (npm cache issues)
- File watchers on Windows getting confused (Node.js file watching limitations)
Pro Tip: If madge
finds circular dependencies, draw them on paper. Seriously. Visual debugging works when your brain is fried at 3 AM.
Bundle Size Explosion
Problem: Bundle went from 300KB to 3MB overnight
Immediate Diagnosis:
npm install --save-dev rollup-plugin-visualizer
Add to rollup.config.js:
import { visualizer } from 'rollup-plugin-visualizer';
export default {
plugins: [
// ... other plugins
visualizer({
filename: 'dist/stats.html',
open: true,
gzipSize: true
})
]
}
What You'll Usually Find:
- Someone imported
moment
instead ofdate-fns
(adds 500KB) (bundle size comparison) - Lodash imported wrong:
import _ from 'lodash'
vsimport { debounce } from 'lodash-es'
(tree-shaking guide) - A dev dependency leaked into production bundle (Rollup external configuration)
- Tree-shaking broke because of side effects (side effects documentation)
Real War Story: Deployed on Friday, users complained site was slow on Monday. Bundle analyzer showed we were importing the entire @mui/icons-material
package (2.1MB) because someone used a barrel import. One line change: import HomeIcon from '@mui/icons-material/Home'
→ import HomeIcon from '@mui/icons-material/Home'
. Bundle dropped to 200KB.
Plugin Hell Debugging
When Plugins Break Everything:
Plugin order matters more than Rollup admits. This order works for 95% of projects:
export default {
plugins: [
resolve({ preferBuiltins: false }),
commonjs(),
typescript(),
babel(),
terser() // Always last
]
}
Plugin Conflict Debugging:
## Test each plugin individually
rollup -c rollup.config.minimal.js
Create rollup.config.minimal.js
:
export default {
input: 'src/index.js',
output: { file: 'dist/test.js', format: 'esm' },
plugins: [
// Add plugins one by one until it breaks
]
}
Common Plugin Issues:
- @rollup/plugin-commonjs gives up on weird packages (looking at you,
react-dom
) - @rollup/plugin-typescript ignores half your tsconfig.json settings
- rollup-plugin-postcss breaks with CSS modules sometimes
- @rollup/plugin-json crashes on huge JSON files
CI/CD Build Failures
GitHub Actions Running Out of Memory:
- name: Build with more memory
run: NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build
This is a common issue with GitHub Actions default runners that have memory limitations.
Vercel Deployment Failures:
Check your build output size. Vercel has a 250MB limit for the entire build directory.
## Check build size locally
du -sh dist/
See Vercel build troubleshooting for more deployment issues and build optimization strategies.
Docker Build Issues:
FROM node:18-alpine
## Increase memory for build step
ENV NODE_OPTIONS=\"--max-old-space-size=4096\"
RUN npm run build
Source Map Problems
Missing Source Maps in Production:
export default {
output: {
sourcemap: true, // or 'inline' for debugging
sourcemapExcludeSources: true // Don't leak source code
}
}
Source Maps Too Large:
export default {
output: {
sourcemap: process.env.NODE_ENV === 'development'
}
}
Debugging with Source Maps:
When your production error points to line 1 column 47293, you need source maps to find the real location. Source maps are essential for production debugging and error tracking.
## Install source-map-cli for debugging
npm install -g source-map-cli
smc --source-map dist/bundle.js.map --line 1 --column 47293
For comprehensive error tracking, consider integrating Sentry source maps or Bugsnag source maps. This helps with production error monitoring.