A veces, las mejoras de rendimiento traen efectos secundarios inesperados. Recientemente, al migrar Becommerce.es a una infraestructura más rápida, una funcionalidad crítica dejó de funcionar: el buscador.
El síntoma era extraño: al hacer clic en la lupa, el modal se abría, pero el campo de texto para escribir no aparecía.
El Sospechoso: Race Condition
Una Race Condition (condición de carrera) ocurre cuando el comportamiento del software depende de la secuencia o el tiempo de eventos incontrolables. En este caso, la carga de la página vs. la ejecución del script.
El código original para iniciar el buscador (Pagefind) era este:
window.addEventListener('DOMContentLoaded', (event) => {
new PagefindUI({ element: "#search" });
});
Este código le dice al navegador: “Espera a que el contenido esté listo (DOMContentLoaded), y entonces inicia el buscador”.
¿Por qué falló?
En el nuevo servidor, la página cargaba tan rápido que el evento DOMContentLoaded se disparaba antes de que el navegador llegara a leer y ejecutar nuestro bloque de script.
Cuando el script finalmente se ejecutaba y decía “avísame cuando cargues”, el navegador ya había terminado de cargar hacía milisegundos. El evento ya había pasado, y el aviso nunca llegaba. Resultado: el buscador nunca se iniciaba.
La Solución
La solución robusta es no asumir nada sobre el estado de la página. Debemos preguntar: “¿Ya estás lista? Si es así, ejecuta ahora. Si no, avísame cuando lo estés”.
Aquí está el código corregido que implementamos:
function initPagefind() {
new PagefindUI({ element: "#search" });
}
// Comprobamos el estado actual antes de añadir el listener
if (document.readyState === 'loading') {
// Aún cargando, esperamos al evento
window.addEventListener('DOMContentLoaded', initPagefind);
} else {
// Ya cargado (interactive o complete), ejecutamos inmediatamente
initPagefind();
}
Al verificar document.readyState, cubrimos ambos escenarios: carga lenta (esperar evento) y carga rápida (ejecución inmediata), eliminando efectivamente la condición de carrera.
Actualización: Cuando Rocket Loader complica las cosas
Incluso con la solución anterior, en entornos que usan herramientas como Cloudflare Rocket Loader (que difiere la carga de scripts), es posible que la librería PagefindUI aún no esté definida cuando intentamos ejecutarla, independientemente del estado del DOM.
En estos casos, la solución definitiva es la perseverancia: un mecanismo de polling (reintento).
function initPagefind() {
// Verificamos si la librería ya existe
if (typeof PagefindUI !== "undefined") {
new PagefindUI({ element: "#search" });
} else {
// Si no existe, esperamos 50ms y volvemos a intentarlo
setTimeout(initPagefind, 50);
}
}
initPagefind();
Este enfoque no confía en eventos ni estados del navegador, simplemente insiste cortésmente hasta que la herramienta necesaria está disponible. Esta técnica de “polling” ha demostrado ser la más efectiva contra los retrasos de carga introducidos por optimizaciones agresivas.
Te podría interesar
-
La Guía Definitiva: Comentarios en Jekyll y Migración Híbrida con Giscus
Una de las grandes “pérdidas” al migrar de WordPress a un sitio estático como Jekyll es el sistema de comentarios. Al no tener base de...
-
Docker Swarm contenedor php-fpm infectado 100% CPU
Cómo Arreglar Docker Swarm Infectado con Malware PHP-FPM
-
Illuminate \ Database \ QueryException PHP SQLSTATE[HY000] [2002] No such file or directory select * from sessions where id = B9e limit 1
¡Arregla el error de Database No such file or directory select!
-
Problema comando: git Fetch --all regresa: error: cannot lock ref 'refs/remotes/origin/main: is at sd78f7u... but expected s9.... From https://GitHub.com/... (Unable to update local ref)
Problema al ejecutar git fetch --all
-
Como crear un PDF con documentación en formato .rst desde GitHub usando ibis-next, por ejemplo del repo symfony-docs - gratis
Cómo crear un PDF con documentación en formato rst desde GitHub usando Ibis-Next