Tại sao quá trình build bị crashBạn đang chạy npm run build, quạt tản nhiệt trên MacBook bắt đầu quay mạnh, và rồi mọi thứ đóng băng. Thay vì hoàn tất bundle thành công, terminal của bạn xuất hiện một bảng log crash khổng lồ kết thúc bằng lỗi cấp phát bộ nhớ. Đây không phải là bug trong code của bạn. Đó là vấn đề về giới hạn tài nguyên.
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
Các frontend framework hiện đại như Next.js hoặc các ứng dụng Angular nặng rất tiêu tốn tài nguyên. Theo mặc định, Node.js (v12 trở lên) thường tự giới hạn ở mức khoảng 2GB bộ nhớ trên hệ thống 64-bit. Khi Webpack hoặc Vite cố gắng duyệt qua cây phụ thuộc với hơn 10.000 tệp, nó sẽ chạm trần 2GB đó và dừng hoạt động.
Cách sửa nhanh: Trong phiên làm việc tạm thờiNếu bạn cần đẩy một bản hotfix ngay lập tức, đừng can thiệp vào các tệp cấu hình. Bạn có thể ghi đè giới hạn cho tab terminal hiện tại. Lệnh này sẽ tăng giới hạn lên 4GB, mức đủ cho 95% các dự án cấp doanh nghiệp.
export NODE_OPTIONS="--max-old-space-size=4096"npm run build
Nếu dự án của bạn cực kỳ lớn—như hàng trăm trang và source map nặng—hãy tăng con số đó lên 8192. Chỉ cần đảm bảo máy Mac của bạn có ít nhất 16GB RAM vật lý trước khi thực hiện.
Cách sửa cho toàn hệ thống (zsh)Hầu hết người dùng macOS chạy zsh. Bạn có thể thiết lập việc tăng bộ nhớ này vĩnh viễn để không bao giờ gặp lại lỗi này khi phát triển cục bộ. Cách tiếp cận này rất tuyệt nếu bạn làm việc trên nhiều repository lớn.
- Mở cấu hình zsh của bạn trong trình soạn thảo:
nano ~/.zshrc- Dán dòng này vào cuối tệp:export NODE_OPTIONS="--max-old-space-size=4096"- Lưu và thoát (NhấnCtrl+O,Enter, sau đó làCtrl+X).- Áp dụng các thay đổi ngay lập tức:source ~/.zshrc## Cách sửa cho cả nhóm: package.jsonThiết lập biến toàn hệ thống thì tiện lợi, nhưng nó không giúp ích cho đồng đội của bạn. Nếu một người chạm giới hạn bộ nhớ, mọi người cũng sẽ bị. Cách tốt nhất là xác định giới hạn trực tiếp trong tệppackage.jsoncủa dự án. Điều này đảm bảo quá trình build hoạt động trên các pipeline CI/CD và máy của các nhà phát triển khác. Cập nhật các script của bạn như sau:
{
"scripts": {
"build": "NODE_OPTIONS=--max-old-space-size=4096 next build",
"dev": "NODE_OPTIONS=--max-old-space-size=4096 next dev"
}
}
Bạn dùng cả Windows? Hãy cài đặt gói cross-env. Sau đó thay đổi script thành cross-env NODE_OPTIONS=--max-old-space-size=4096 next build để nó có thể hoạt động trên mọi nền tảng.
Xác minh thay đổiRất dễ để kiểm tra xem Node.js đã thực sự chấp nhận cài đặt mới của bạn chưa. Bạn có thể chạy một lệnh duy nhất để xem giới hạn tính bằng gigabyte.
node -e 'console.log((require("v8").getHeapStatistics().heap_size_limit / 1024 / 1024 / 1024).toFixed(2) + " GB")'
Nếu kết quả hiển thị 4.00 GB, bạn đã sẵn sàng. Các bản build của bạn giờ đây sẽ ổn định hơn.
Cảnh báo cho người dùng Apple Silicon (M1/M2/M3)Hãy kiểm tra kiến trúc Node.js của bạn. Nếu bạn chuyển từ máy Mac dùng chip Intel sang, có thể bạn đang chạy phiên bản Node x64 thông qua Rosetta 2. Điều này làm giảm hiệu năng nghiêm trọng. Chạy Node x64 trên chip M2 tiêu tốn nhiều bộ nhớ hơn đáng kể và chạy chậm hơn khoảng 20-30%.
Chạy lệnh sau:
node -p "process.arch"
Nếu kết quả trả về x64, bạn nên cài đặt lại Node.js. Sử dụng một trình quản lý như nvm hoặc fnm để cài đặt phiên bản arm64. Các bản binary gốc (native) xử lý bộ nhớ hiệu quả hơn nhiều, thường giải quyết được các lỗi 'out of memory' mà không cần phải tăng kích thước heap.

