# Adaugă limită de memorie pentru Node și păstrează cache-ul
export NODE_OPTIONS='--max-old-space-size=3072'
# Nu șterge tot folderul .next, șterge doar server/static dacă e neapărat nevoie
# rm -rf .next/server
next buildAm dat recent de o chestie super frustrantă la un client cu un proiect Next.js (App Router) la vreo 8k useri activi. În local, npm run dev se lansează în 12 secunde, iar npm run build durează maxim 45 de secunde pe un M1. Cum am urcat proiectul pe un VPS ieftin de la Hetzner (2 vCPU, 4GB RAM), pipeline-ul de build a sărit direct la 8 minute și jumătate, ba uneori chiar crăpa fără nicio eroare explicită.
Vreau să vă las mai jos pașii pe care i-am parcurs eu ca să cobor build-ul la 1 minut și 20 de secunde și să vă întreb dacă ați mai găsit și alte trucuri pe partea asta.
1. RAM-ul și limita de Swap (Moartea tăcută a build-urilor)
Prima chestie pe care o verifici când Next.js „agăță” pe un VPS este memoria. SWC și Webpack mănâncă resurse agresiv în faza de compilare. Când VPS-ul rămâne fără RAM fizic, kernel-ul de Linux începe să folosească intensiv Swap-ul de pe disc.
Un SSD, oricât de NVMe este el, e de sute de ori mai lent decât memoria RAM. Procesorul stă 90% din timp în iowait în loc să compileze JS. Dă o comandă de htop sau free -m în timp ce rulează build-ul. Dacă vezi că Swap-ul e plin și RAM-ul e la 98%, acolo e prima ta barieră.
Soluția rapidă a fost să limitez memoria folosită de Node.js, prevenind intrarea procesului în swap thrashing. Am setat parametrul --max-old-space-size=3072 în variabila de mediu înainte de executare.
2. Păstrarea folderului .next/cache între deployment-uri
Dacă folosești un CI/CD simplu (un script de bash pe VPS lansat din GitHub Actions sau Webhook), ai grijă să nu dai rm -rf .next complet înainte de comandă.
Next.js folosește un cache intern foarte agresiv pentru linters, type-checking și compilarea paginilor. Dacă ștergi folderul de cache la fiecare run, îi forțezi compilatorul să o ia de la zero cu fiecare fișier TSX și fiecare modul din node_modules. Am pățit asta când rulam build-ul într-un container Docker unde uitasem să montez un volum persistent pentru .next/cache. Economisești instant peste 50% din timp doar păstrând acel folder de la o rulare la alta.
3. Paralelismul din SWC și output: 'standalone'
Pe un VPS cu doar 2 nuclee, SWC încearcă implicit să spawneze worker threads ca și cum ar fi pe o mașină cu 16 nuclee. Asta duce la context switching masiv și sufocă procesorul micului server.
Trade-off-ul direct: dacă faci build-ul direct pe VPS, economisești bani pe stocarea imaginilor de Docker și nu depinzi de un runner extern, dar îți mănânci din resursele serverului exact când site-ul e live și are trafic. În schimb, dacă faci build-ul într-un GitHub Actions runner și împingi doar artifactul compilat cu output: 'standalone', VPS-ul nici nu simte deployment-ul.
Voi cum gestionați asta pe serverele de producție mici? Preferați să faceți build-ul direct pe VPS ca să fie simplu, sau împingeți doar artifactul gata compilat dintr-un runner extern?