InnovaWebb, ir al inicio

El build que no usaba CPU

El síntoma

Un pnpm build que no avanza.

No da error. No escupe una traza. No se cae. Simplemente se queda quieto, y lo desconcertante es que el ventilador tampoco suena. El Monitor de Actividad confirma lo que ya sospechas: el proceso no está usando procesador.

Un build lento consume CPU. Uno parado sin consumirla no está trabajando: está esperando algo.

La pista que lo convierte en un rompecabezas de verdad llega al intentar empezar de cero:

rm -rf .next

Tampoco termina.

Borrar una carpeta es de las operaciones más simples que hace un sistema de archivos. Si eso se cuelga, el problema no está en tu código, ni en tu gestor de paquetes, ni en el compilador.

Qué estaba pasando

El repositorio vivía en ~/Documents/. En macOS, esa carpeta y el Escritorio los sincroniza iCloud Drive cuando está activada la opción «Carpetas Escritorio y Documentos».

Y .next son miles de archivos de compilación que se reescriben enteros en cada build.

Mientras iCloud mantiene un archivo abierto para subirlo, el sistema no permite sobrescribirlo ni borrarlo. La operación no falla: espera. Por eso no hay mensaje de error y por eso no hay consumo de procesador. Hay dos programas trabajando sobre los mismos miles de archivos: uno intenta reescribirlos y el otro intenta subirlos a la nube.

Cuando medimos qué se estaba sincronizando, el reparto era este:

CarpetaTamaño¿Se regenera sola?
.next503 MBSí
node_modules465 MBSí
.git11 MBNo
El trabajo real (código, contenido, documentación)~9 MBNo
Total987 MB

.next se regenera en cada build y node_modules con un install. .git no: es el historial del proyecto.

De casi un gigabyte sincronizándose, el trabajo real eran nueve megabytes. El 99 % restante eran archivos que la máquina reconstruye sola en un par de minutos.

Nada de esto afecta al sitio publicado. Es un problema de la máquina en la que se desarrolla, no de lo que recibe el visitante.

El riesgo que todavía no habíamos tenido

Hasta aquí, todo lo que has leído nos pasó. Lo de esta sección, no. No es una experiencia nuestra: es un comportamiento documentado de macOS, y lo contamos porque, si te ocurre, es peor que lo anterior y más difícil de diagnosticar.

iCloud tiene una opción llamada «Optimizar el almacenamiento del Mac». Cuando el disco se queda corto, el sistema retira la copia local de los archivos que considera poco usados y deja solo la de la nube. El archivo sigue apareciendo en el Finder; simplemente ya no está en el disco.

Si eso le ocurriera a un archivo de node_modules, el build fallaría diciendo que un módulo no existe. Existe, y además lo verías en pantalla, pero no estaría en la máquina. Es un error difícil de rastrear precisamente porque todo lo que miras parece correcto.

Para que quede claro: a nosotros el proyecto se nos bloqueó, pero nunca nos faltó un archivo. Ese es el riesgo que evitamos al mover el proyecto, no uno que hayamos sufrido.

Cómo reconocerlo

Tres señales que juntas no dejan lugar a dudas:

du -sh .next                     # cientos de MB
pwd | grep -q Documents && echo "⚠️  dentro de iCloud"
brctl log --last 2m -q           # actividad reciente de iCloud

brctl es la herramienta de línea de comandos de iCloud, y casi nadie la conoce. macOS oculta parte de los nombres de archivo en ese registro, pero si el build está parado y ahí ves actividad continua de iCloud, ya tienes el diagnóstico.

La solución

Borrar .next y volver a compilar no sirve: se regenera y vuelve a bloquearse. Hay que sacar el proyecto de las carpetas que sincroniza iCloud.

mkdir -p ~/Developer
mv ~/Documents/mi-proyecto ~/Developer/
cd ~/Developer/mi-proyecto
rm -rf .next                     # ahora sí termina
pnpm build

Elegimos ~/Developer porque macOS la reconoce como carpeta de desarrollo y le pone su propio icono, pero sirve cualquier ruta fuera de Documents y Desktop.

Mover la carpeta no rompe nada: Git guarda sus rutas de forma interna y el historial viaja dentro de .git, así que el repositorio sigue funcionando exactamente igual en su nueva ubicación.

El primer build después de mover compiló en 2,5 segundos.

Si después de mover node_modules da errores raros, puede que iCloud hubiera retirado ya la copia local de algún archivo, el riesgo de la sección anterior. Un install lo reconstruye.

La regla que queda

La pregunta no es «¿dónde guardo mis proyectos?». Es otra, y vale para cualquier servicio de sincronización:

Lo que se regenera solo no se respalda.

node_modules, .next, .turbo, dist, build y __pycache__ no son tus datos. Son el resultado de aplicar un comando a tus datos. Si desaparecieran ahora mismo, un install y un build los traerían de vuelta.

Tus datos son el código, el contenido y el historial de Git, y ese historial ya está respaldado en el servidor remoto, que es mejor copia de seguridad que cualquier carpeta sincronizada.

Dicho de otro modo: es el mismo criterio que ya aplicas en el .gitignore. Lo que no merece entrar en el repositorio tampoco merece entrar en la nube. La lista es casi la misma, y por la misma razón.

El principio más general

Más allá de iCloud, este caso enseña a leer una categoría entera de problemas.

Un proceso parado que no consume procesador no está trabajando: está esperando. Y lo que espera casi nunca es la CPU: es un archivo, un puerto, un bloqueo o la red.

Cuando algo se cuelga, la primera pregunta no es «¿qué estoy haciendo mal?». Es «¿quién más está tocando esto?». La respuesta suele estar fuera del programa que estás mirando.

← Todos los artículos