El patrón Singleton garantiza una única instancia compartida de una clase en toda la aplicación.
1. El Problema de Partida
getAllMdxFiles recorre recursivamente content/knowledge/ leyendo el filesystem. Durante generateStaticParams, generateMetadata y el render de cada página, Next.js invoca esta función decenas de veces para la misma colección, repitiendo lecturas de disco idénticas en cada build.
// ANTES — cada llamada vuelve a recorrer el disco
export function getAllMdxFiles(dir) {
const files = [];
// ...recorrido recursivo con fs.readdirSync en cada invocación
return files;
}2. La Solución Singleton
Una clase MdxCache con constructor privado (simulado) expone getInstance() y memoriza el resultado del recorrido la primera vez; las siguientes llamadas devuelven el array cacheado en memoria.
// src/lib/MdxCache.js
import fs from 'fs';
import path from 'path';
class MdxCache {
static _instance;
_files = null;
static getInstance() {
if (!MdxCache._instance) {
MdxCache._instance = new MdxCache();
}
return MdxCache._instance;
}
getAllFiles(dir) {
if (this._files !== null) return this._files; // Ya cacheado
const walk = (current) =>
fs.readdirSync(current, { withFileTypes: true }).flatMap((entry) => {
const full = path.join(current, entry.name);
return entry.isDirectory() ? walk(full) : entry.name.endsWith('.mdx') ? [full] : [];
});
this._files = walk(dir);
return this._files;
}
}
export default MdxCache;3. Uso en lib/mdx.js
// src/lib/mdx.js — DESPUÉS
import MdxCache from './MdxCache';
export function getAllMdxFiles(dir) {
return MdxCache.getInstance().getAllFiles(dir);
}4. Ventajas
- Una sola lectura de disco por build: todas las rutas dinámicas comparten el mismo resultado.
- Punto de acceso global: cualquier módulo llama a
MdxCache.getInstance()sin pasar la caché como prop. - Cuidado en dev: con Hot Module Reloading el singleton puede persistir contenido obsoleto; conviene invalidarlo (
_files = null) ante cambios de archivo en modo desarrollo.