The 'JavaScript heap out of memory' error occurs when Node.js runs out of allocated memory during build or development processes. This commonly happens in Create React App projects with large codebases or many dependencies, requiring increased memory allocation.
The "CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory" error is Node.js's way of telling you that the V8 JavaScript engine has exhausted its allocated memory heap. When building or running a Create React App application, Node.js needs to process all your JavaScript code, dependencies, and assets - if this exceeds the default memory limit, the process crashes with this fatal error. By default, Node.js allocates approximately 512 MB of memory on 32-bit systems and around 1.4-2 GB on 64-bit systems. Create React App's build process, which involves transpiling JSX, bundling modules with webpack, optimizing assets, and potentially generating source maps, can easily exceed these limits for larger applications. The error specifically mentions "CALL_AND_RETRY_LAST" because V8 attempted garbage collection and memory compaction multiple times before finally giving up. This issue has become more common as React applications grow in complexity and as newer versions of react-scripts include more features that consume additional memory during builds. The problem is particularly acute in CI/CD environments with limited resources, or when running multiple build processes simultaneously.
The most direct solution is to increase the memory allocation for your build process by modifying your package.json scripts:
{
"scripts": {
"start": "react-scripts --max_old_space_size=4096 start",
"build": "react-scripts --max_old_space_size=4096 build",
"test": "react-scripts test"
}
}The --max_old_space_size=4096 flag allocates 4 GB of memory. Adjust this value based on your system's available RAM:
- 2048 for 2 GB (minimum recommended)
- 4096 for 4 GB (standard for medium projects)
- 8192 for 8 GB (for very large applications)
Alternatively, set the memory limit globally using an environment variable. This is especially useful for CI/CD pipelines:
# Linux/Mac
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build
# Windows Command Prompt
set NODE_OPTIONS=--max-old-space-size=4096
npm run build
# Windows PowerShell
$env:NODE_OPTIONS="--max-old-space-size=4096"
npm run buildFor permanent configuration, add to your .bashrc, .zshrc, or system environment variables.
Source map generation consumes significant memory. Disable them in production if you don't need them:
{
"scripts": {
"build": "GENERATE_SOURCEMAP=false react-scripts build"
}
}For Windows:
{
"scripts": {
"build": "set GENERATE_SOURCEMAP=false && react-scripts build"
}
}Or create a .env.production file:
GENERATE_SOURCEMAP=falseThis can reduce memory usage by 30-50% during builds.
Corrupted cache or leftover build artifacts can cause memory issues. Clean your environment:
# Remove node_modules and package lock
rm -rf node_modules package-lock.json
# Clear npm cache
npm cache clean --force
# Reinstall dependencies
npm install
# Clear Create React App cache
rm -rf node_modules/.cache
# Try building again
npm run buildFor yarn users:
rm -rf node_modules yarn.lock
yarn cache clean
yarn installReduce memory consumption by minimizing what needs to be processed:
# Analyze bundle size
npm install --save-dev webpack-bundle-analyzer
# Add to package.json scripts
"analyze": "source-map-explorer 'build/static/js/*.js'"Consider these optimizations:
- Use dynamic imports for code splitting
- Replace large libraries with lighter alternatives (e.g., date-fns instead of moment)
- Remove unused dependencies from package.json
- Enable tree shaking by using ES6 imports
- Lazy load components with React.lazy()
Check bundle size with:
npm run buildThe build output shows file sizes - look for unusually large chunks.
Newer Node.js versions have improved memory management and V8 optimizations:
# Check current version
node --version
# Using nvm (recommended)
nvm install --lts
nvm use --lts
# Or download from nodejs.org
# https://nodejs.org/Node.js 18+ includes better container-aware memory limits and garbage collection. After upgrading:
rm -rf node_modules package-lock.json
npm install
npm run buildIf building in CI/CD, ensure adequate resources are allocated:
GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_OPTIONS: --max-old-space-size=4096
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run buildNetlify (netlify.toml):
[build]
environment = { NODE_OPTIONS = "--max-old-space-size=4096" }Docker:
FROM node:18
ENV NODE_OPTIONS="--max-old-space-size=4096"
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run buildAlso ensure container/VM has sufficient RAM allocated (minimum 4 GB recommended).
### Understanding V8 Memory Architecture
The V8 JavaScript engine used by Node.js divides memory into multiple spaces. The "old space" is where long-lived objects are stored after surviving multiple garbage collection cycles. The --max_old_space_size flag specifically controls this space, which is typically where build processes accumulate large objects like AST (Abstract Syntax Tree) representations, bundled code, and webpack compilation artifacts.
### Why CRA Builds Use So Much Memory
Create React App's build process is memory-intensive because:
1. Webpack compilation loads all modules into memory simultaneously
2. Babel transpilation creates intermediate AST representations for every file
3. Minification requires additional memory for optimization passes
4. Source map generation doubles memory usage by maintaining mapping data
5. Tree shaking analyzes the entire dependency graph in memory
### Memory vs. Build Time Trade-offs
Increasing memory allocation doesn't slow down builds - in fact, it often speeds them up by reducing garbage collection pauses. However, disabling source maps (which saves memory) may slightly speed up builds but removes debugging capabilities in production.
### Container and Kubernetes Considerations
In containerized environments, Node.js 20+ automatically detects cgroup memory limits and adjusts its heap size accordingly. However, this automatic adjustment may still be insufficient for large builds. Explicitly set --max-old-space-size to override automatic detection, and ensure your container has at least 2x the heap size in total RAM (for other processes and overhead).
### When to Consider Ejecting or Alternatives
If you consistently need more than 8 GB of memory for builds, consider:
- Using Vite instead of Create React App (significantly lower memory usage)
- Ejecting from CRA to customize webpack configuration for incremental builds
- Splitting your application into multiple smaller apps or micro-frontends
- Moving large static assets to a CDN instead of bundling them
### Monitoring Memory Usage
To see actual memory consumption during builds:
# Linux/Mac
/usr/bin/time -v npm run build
# Shows maximum resident set size and other metricsFor continuous monitoring during development, use Node.js built-in profiling:
node --max-old-space-size=4096 --inspect node_modules/.bin/react-scripts buildThen open chrome://inspect in Chrome to see real-time memory usage.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React