05 Capítulo 5 · Lección 14

Escenas para producción

Redactado por
Author Sebastian V.
Fecha de publicación

06/03/2026

Tiempo de lectura

7 min

Tema

Three.js

Dejando de jugar, empezando a profesionalizar

Hacer un cubo que gira en un archivo HTML es fácil. Mantener una experiencia Three.js compleja dentro de un framework moderno como Astro, React o Vue requiere disciplina arquitectónica. Si construyes tu código a lo bruto en un solo archivo, tendrás Memory Leaks, ventiladores sonando fuerte y una web inmanejable.

El problema de la basura (Garbage Collection)

A diferencia de los elementos del DOM que desaparecen cuando cambias de página, WebGL es terco. Si instancias Geometrías y Materiales en la memoria de la tarjeta gráfica (VRAM) y cambias de ruta en tu web, esa memoria NO se libera automáticamente.

Si el usuario entra y sale de tu página 3D varias veces, llenará la VRAM y el navegador cerrará la pestaña por seguridad (el clásico "Aw, Snap!" en Chrome).

El arte del Dispose

Todo lo que tenga una geometría, un material, o un renderer, tiene un método llamado .dispose(). Cuando la página se destruye (o el componente se desmonta), es TU responsabilidad recorrer la escena y ejecutar dispose en cada cosa.

Organización con Clases

En producción, no metemos todo en un archivo script.js. Creamos una clase WebGLApp o usamos patrones de arquitectura (como react-three-fiber en React). Separamos responsabilidades: un archivo para la escena, otro para la luz, y otro para manejar el resize.

Consejo profesional

En Astro, las View Transitions hacen que la página nunca recargue realmente. Esto agrava el problema de los memory leaks. Usa el evento astro:before-swap para cancelar el requestAnimationFrame y hacer el dispose completo de la escena antes de que cambie la ruta.

El Cleanup Perfecto

> _
let animationId;

function animate() {
  animationId = requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

// Cuando el usuario sale de la página...
function cleanUp() {
  // 1. Detener el bucle, la CPU descansa
  cancelAnimationFrame(animationId);
  
  // 2. Liberar eventos del navegador
  window.removeEventListener('resize', handleResize);
  
  // 3. Recorrer y destruir geometrías y materiales de la VRAM
  scene.traverse((child) => {
    if (child.isMesh) {
      child.geometry.dispose();
      
      // Los materiales pueden ser un array
      if (Array.isArray(child.material)) {
        child.material.forEach(mat => mat.dispose());
      } else {
        child.material.dispose();
      }
    }
  });
  
  // 4. Destruir el proyector
  renderer.dispose();
}
> _

Una escena optimizada con cleanup completo. Navega fuera para ver el dispose en acción.

Errores comunes

01
Ventiladores a toda potencia Significa que perdiste control del requestAnimationFrame. Al cambiar de página, dejaste el bucle corriendo infinitamente renderizando una escena que ya ni siquiera es visible.
02
VRAM Exhausta Crear texturas nuevas o materiales nuevos DENTRO de la función animate. En 1 minuto tendrás miles de objetos en memoria colapsando la web.

Practica lo aprendido

Sé un profesional responsable.

01 Guarda el ID devuelto por requestAnimationFrame en una variable externa.
02 En el evento unmount (o before-swap en Astro), llama a cancelAnimationFrame(id).
03 Recorre la escena con scene.traverse() y llama .dispose() en cada geometría y material.