5 niveles de prioridad de JavaScript y cómo usarlos
No todos los scripts son iguales. Cárgalos en el orden correcto.

No todos los scripts son iguales
Una cosa siempre ha estado clara: no todos los scripts de JavaScript son iguales. Algunos scripts manejan interacciones críticas como la 'interacción con el menú' o 'añadir al carrito', mientras que otros scripts son mucho menos importantes. Tomemos como ejemplo el script emergente de 'intención de salida' que invita a los visitantes que están a punto de abandonar tu sitio a completar un cuestionario. Estoy seguro de que todos podríamos vivir sin estos últimos, pero sería muy difícil navegar por un sitio web sin los primeros.
Sin embargo, en 'tu sitio web promedio', a nivel técnico, casi nunca se hace esta distinción. Todos los scripts de JavaScript 'simplemente se añaden' a la página y se deja que el navegador resuelva el problema. Esto es un inconveniente porque tu navegador no tiene idea de qué es importante y qué no. Nosotros, como desarrolladores, sí la tenemos. ¡Así que vamos a solucionarlo!
Última revisión por Arjen Karel en marzo de 2026
La página móvil mediana carga 646 KB de JavaScript a través de 22 solicitudes, según el Web Almanac de 2025. Aproximadamente el 44% de ese JavaScript nunca llega a ejecutarse. Solo el 13% de las páginas superan la auditoría de recursos que bloquean el renderizado de Lighthouse. El problema no es solo cuánto JavaScript cargas, sino cuándo y en qué orden.
Cómo la prioridad de JavaScript puede impactar en las Core Web Vitals
El simple hecho de añadir scripts a la página sin la consideración adecuada puede afectar a las 3 Core Web Vitals. El Largest Contentful Paint, el Interaction to Next Paint y el Cumulative Layout Shift.

Ejemplo: el recurso de red del LCP se retrasa por culpa de scripts de JavaScript que bloquean el renderizado
El Largest Contentful Paint es propenso a la competencia por el ancho de banda y la CPU. Cuando demasiados scripts compiten por los recursos de red tempranos, se retrasará el recurso de red del Largest Contentful Paint, y el trabajo temprano de la CPU retrasará el LCP al bloquear el hilo principal.
El Interaction to Next Paint puede verse afectado por scripts que se ejecutan justo antes de una interacción. Cuando los scripts se ejecutan, bloquean el hilo principal y retrasarán cualquier interacción durante ese tiempo de ejecución.
Los scripts también pueden causar un Cumulative Layout Shift si 'cambian el aspecto de la página'. Los scripts de anuncios que inyectan banners en la página y los sliders son conocidos por hacer esto.
5 tipos de prioridades de JavaScript
Me gusta distinguir entre 5 tipos de prioridades de JavaScript.
- Críticos para el renderizado: estos scripts se encuentran entre los peores que puedes tener. Cambian el diseño de la página y sin cargar estos scripts el diseño será completamente diferente. Ejemplo: algunos scripts de sliders o un test A/B.
- Scripts críticos: Estos scripts manejan la funcionalidad crítica de la página y sin ellos no son posibles tareas críticas como agregar un producto al carrito, la búsqueda en el sitio o la navegación.
- Scripts importantes: Estos scripts manejan lógica de negocio importante y tu sitio depende de ellos. Por ejemplo: Analytics.
- Scripts agradables de tener: Estos scripts son útiles, pero si llega el momento de la verdad, no los necesitamos realmente para que la página funcione. Por ejemplo, un widget de chat o una intención de salida.
- Scripts futuros: Estos scripts pueden ser críticos o agradables de tener, pero no los necesitamos en este momento porque se deben tomar 'otros pasos' antes de que podamos utilizarlos realmente. Por ejemplo, un script de checkout de múltiples etapas.
Antes de analizar cada nivel de prioridad, aquí te mostramos cómo Chrome asigna la prioridad de red a diferentes tipos de scripts:
| Tipo de script | Prioridad en Chrome | ¿Bloquea el renderizado? |
|---|---|---|
<script> en el <head> | Highest | Sí |
<script async> | Low (descarga) / High (ejecución) | No |
<script defer> | Low | No |
<script> al final del <body> | Medium / High | No |
Entender estos valores predeterminados es la clave para la priorización de recursos.
1. Scripts críticos para el renderizado
Estos scripts cambian directamente el diseño de la página. Sin ellos, la página se ve completamente diferente a su diseño previsto. Los ejemplos incluyen scripts para sliders o frameworks de testing A/B que alteran el diseño al principio del proceso de carga.
El problema con estos scripts es que no pueden ser diferidos ni retrasados. Cualquier retraso provocará que el diseño del sitio web cambie, causando una mala UX y el fallo de las Core Web Vitals.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Page Title</title>
<link href="styles.css" rel="stylesheet" />
<script src="render-critical.js"></script>
</head>
<body></body>
</html>
Mejores prácticas:
- Evita los scripts críticos para el renderizado siempre que sea posible. Reescribe tu código para eliminar la dependencia de este tipo de scripts.
- Si no hay forma de evitarlo, incluye en línea o carga solo las partes absolutamente necesarias de estos scripts.
- No uses defer o async en estos scripts y colócalos en la parte superior del head para desencadenar una descarga 'lo antes posible'.
2. Scripts críticos
Estos scripts habilitan interacciones fundamentales. Sin ellos, tareas críticas como la navegación del sitio, añadir artículos a un carrito, el aviso de cookies o realizar una búsqueda se vuelven imposibles. Son indispensables para la funcionalidad principal del sitio.
Estos scripts deben colocarse en el head de la página con el atributo async o defer. Para una comparación completa de estos dos enfoques, consulta async frente a defer y cómo afectan a las Core Web Vitals.
<script defer src="critical.js"></script> <script async src="critical.js"></script>
Mejores prácticas:
- Mantén scripts como estos al mínimo y no combines esta funcionalidad con otra funcionalidad menos crítica.
- Carga estos scripts de manera temprana utilizando
asyncodefer, dependiendo de sus dependencias. - Utiliza Real User Monitoring para identificar cuellos de botella en la ejecución y asegurarte de que su rendimiento se alinea con las necesidades del usuario.
3. Scripts importantes
Estos scripts apoyan tu negocio pero no son necesarios para que la página funcione. Los scripts de analíticas, por ejemplo, proporcionan datos esenciales pero no necesitan cargarse antes que elementos visuales más importantes. La distinción entre scripts críticos e importantes puede ser un tema de debate, ¡así que asegúrate de hablar con todas las partes interesadas antes de establecer esta prioridad!
Hay 2 formas fiables de reducir la prioridad para estos tipos de scripts.
<html>
<head>
<!-- method 1: inject after DOMContentLoaded -->
<script>
document.addEventListener('DOMContentLoaded', function() {
var script = document.createElement('script');
script.src = 'important.js';
document.body.appendChild(script);
});
</script>
</head>
<body>
<!-- method 2: place at the bottom of the page -->
<script defer src="important.js"></script>
</body>
</html>
1: Inyectar después de DOMContentLoaded
Al inyectar el script después del evento DOMContentLoaded, te aseguras de que el script comience a descargarse directamente después de que el HTML haya sido completamente analizado. Esto permite que los recursos descubribles, como imágenes y fuentes, tengan prioridad. Este método proporciona un equilibrio: el script comienza a cargarse lo suficientemente temprano como para evitar retrasos en la funcionalidad, pero no compite con recursos tempranos que son cruciales para el renderizado inicial de la página.
2: Colocar en la parte inferior de la página
Esta técnica clásica difiere la carga del script hasta que el navegador ha procesado todo el documento y logra aproximadamente el mismo resultado que la técnica 1. La única diferencia es que la técnica 1 omite el escáner de precarga de tu navegador, mientras que esta técnica no lo hace. El escáner de precarga es un escáner rápido y ligero que tu navegador usa para identificar y encolar rápidamente los recursos críticos. Omitir el escáner de precarga podría ser una buena idea si existe la posibilidad de que haya imágenes con carga diferida en la ventana gráfica (viewport), mientras que usar el escáner de precarga acelerará la carga de este script.
Una nota sobre fetchpriority: podrías esperar que fetchpriority="low" en un script diferido redujera su prioridad. No lo hace. Los scripts con defer y async ya se cargan con prioridad Low en Chrome. Añadirles fetchpriority="low" no hace nada. El atributo fetchpriority solo marca la diferencia en scripts bloqueantes, donde puede reducir la prioridad de Highest a High. Para conocer más formas de diferir JavaScript, consulta nuestra guía completa.
4. Scripts agradables de tener
Estos scripts mejoran la user experience pero no son necesarios para que el sitio funcione. Los ejemplos incluyen widgets de chat, ventanas emergentes de comentarios de clientes o animaciones opcionales.
Estos scripts son un candidato ideal para un patrón llamado 'carga en inactividad' (lazy on load). Esto significa: esperar al evento de carga (load) de la página y luego, durante el tiempo de inactividad (idle), inyectar el script. Esperar al evento de carga asegura que el script no compita por el ancho de banda y la CPU con recursos tempranos más importantes. Esperar a un momento de inactividad asegura que el navegador no esté manejando tareas más importantes como la entrada del usuario.
Aquí hay un ejemplo funcional:
window.addEventListener("load", () => {
const idle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));
idle(() => {
const script = document.createElement("script");
script.src = "/path/to/script.js";
document.head.appendChild(script);
});
});
El fallback de setTimeout es necesario porque Safari no soporta requestIdleCallback. Para los scripts que también necesitan dividir su ejecución en fragmentos más pequeños, considera usar scheduler.yield() para mantener el hilo principal receptivo y proteger tu puntuación INP.
Mejores prácticas:
- Carga de forma diferida (lazy-load) estos scripts una vez que la página haya cargado y espera a un momento de inactividad.
- Entiende que los scripts cargados con este patrón no tienen garantía de cargarse rápido.
En los sitios monitorizados por CoreDash, las páginas que difieren los scripts no críticos para después del evento de carga obtienen una puntuación INP 'buena' en un 84%, en comparación con el 61% de las páginas que cargan todos los scripts de forma ansiosa.
5. Scripts futuros
Los scripts futuros son aquellos que no serán necesarios hasta que se cumplan condiciones específicas. Por ejemplo, un script de checkout de múltiples etapas solo se vuelve relevante después de que un usuario ha añadido artículos a su carrito. Estos scripts pueden esperar hasta mucho más tarde en el recorrido del usuario.
Echa un vistazo a este ejemplo. Utiliza el IntersectionObserver para cargar la lógica JS solo cuando se necesita: cuando el formulario está en la ventana gráfica visible (viewport).
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.querySelector("form");
const observer = new IntersectionObserver(function (entries) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const script = document.createElement("script");
script.src = "/sign-up.js";
document.head.appendChild(script);
observer.unobserve(form);
}
});
});
observer.observe(form);
});
</script>
</head>
<body>
<form action="/sign-up" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required />
<button type="submit">Sign Up</button>
</form>
</body>
</html>
Mejores prácticas:
- Carga estos scripts bajo demanda, desencadenados por las acciones del usuario.
- Usa técnicas de división de código (code-splitting) para entregar solo las partes requeridas en cada paso.
- Inyéctalos dinámicamente solo cuando sea necesario, como cuando un usuario se desplaza a una sección específica.
La mayoría de los sitios solo necesitan dos patrones: defer para cualquier cosa funcional y el patrón de carga + inactividad (load+idle) para todo lo demás. Si estás pasando tiempo afinando fetchpriority en los scripts, probablemente te estés complicando demasiado. Consigue primero las grandes victorias: difiere lo que puedas, retrasa lo que puedas, y elimina lo que no necesites.
Your Lighthouse score is not the full picture.
Your real users are on Android phones over 4G. I analyze what they actually experience.
Analyze field data
