Ir al contenido
angel.library

HTTP y ciclo completo de carga del navegador

Cuando escribes una URL y presionas Enter no ocurre una sola petición aislada. El recorrido habitual es:

URL
↓
políticas, cachés y service worker
↓
DNS → dirección IP
↓
TCP + TLS, o QUIC
↓
request HTTP
↓
CDN / WAF / proxy / balanceador / aplicación / datos
↓
response HTTP
↓
HTML → DOM + CSSOM → render tree → layout → paint → composite
↓
JavaScript, eventos, hidratación e interacción

No todas las navegaciones recorren cada paso. DNS y conexiones pueden estar reutilizados; una caché o service worker puede responder sin red; una SPA puede actualizar la vista sin solicitar otro documento HTML.

https://docs.example.com:443/guides/http?page=2#cache
└─┬─┘ └───────┬───────┘ └┬┘ └────┬────┘ └──┬──┘ └─┬─┘
scheme host port path query fragment
ParteViaja en HTTPFunción
esquemadetermina conexiónhttp, https
hostsí, como autoridad/Hostdominio de destino
puertoforma parte de autoridad443 por defecto en HTTPS
pathsírecurso solicitado
querysífiltros o parámetros
fragmentnonavegación dentro del documento, solo cliente

El navegador normaliza la URL, aplica políticas como HSTS, comprueba esquemas especiales, consulta historial y decide si la navegación puede ser interceptada por un service worker.

const url = new URL("https://docs.example.com/guides/http?page=2#cache")
url.origin // 'https://docs.example.com'
url.pathname // '/guides/http'
url.search // '?page=2'
url.hash // '#cache'

Nunca pongas secretos en query o fragmentos suponiendo que son privados. Una query puede quedar en historial, logs, analítica y encabezados de referencia según la política aplicada.

Antes de abrir una conexión, el navegador puede consultar:

  • memory cache del proceso actual;
  • disk cache persistente;
  • preloaded resources;
  • caché administrada por un service worker;
  • reglas de navegación y redirecciones conocidas;
  • conexión ya abierta al mismo origen.

La etiqueta “from memory cache” o “from disk cache” en DevTools indica que gran parte del recorrido de red no fue necesario. Un service worker puede responder desde Cache Storage, crear una respuesta o ir a red según su estrategia.

DNS traduce docs.example.com a direcciones IPv4 o IPv6. Puede consultar cachés del navegador, sistema operativo, router, proveedor o resolver recursivo antes de llegar a servidores autoritativos.

RegistroFunción habitual
Adominio → IPv4
AAAAdominio → IPv6
CNAMEalias hacia otro nombre
HTTPS / SVCBparámetros modernos del servicio y alternativas
TXTverificación y políticas de correo, entre otros

Un CDN suele responder con una dirección cercana o adecuada para la red del usuario. El TTL define por cuánto tiempo puede conservarse una respuesta DNS, aunque cada capa puede aplicar límites propios.

Optimizar DNS solo importa cuando hay dominios nuevos. Añadir muchos orígenes de terceros aumenta búsquedas, conexiones, privacidad expuesta y puntos de fallo.

<link
rel="dns-prefetch"
href="//cdn.example.com"
/>
<link
rel="preconnect"
href="https://cdn.example.com"
crossorigin
/>

preconnect adelanta DNS y conexión, pero consume recursos; resérvalo para pocos orígenes críticos que realmente se usarán pronto.

TCP establece una conexión confiable. HTTPS añade un handshake TLS para autenticar el servidor y acordar cifrado. Certificados, SNI, ALPN y reanudación de sesión forman parte de esta negociación.

HTTP/3 utiliza QUIC sobre UDP e integra seguridad. Reduce algunos costos de conexión y evita que la pérdida de un paquete bloquee todos los streams de la misma conexión como puede ocurrir a nivel TCP.

VersiónTransporteMultiplexaciónCaracterística práctica
HTTP/1.1TCPlimitada; varias conexionestexto, una respuesta activa por conexión sin pipelining práctico
HTTP/2TCPvarios streamscompresión de headers y multiplexación
HTTP/3QUIC/UDPvarios streams independientesmejor comportamiento ante pérdida y cambios de red

La versión negociada no cambia la semántica de GET, headers o status. Cambia cómo se transportan los mensajes.

Una conexión puede reutilizarse para muchos recursos. Por eso Navigation Timing puede mostrar duración DNS o conexión igual a cero: no significa necesariamente que no exista DNS/TLS, sino que ya estaba resuelto.

Una request contiene método, destino, headers y, para algunas operaciones, body.

GET /guides/http?page=2 HTTP/1.1
Host: docs.example.com
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, br
Accept-Language: es-CO,es;q=0.9
Cookie: session=...
User-Agent: ...
MétodoIntenciónSeguroIdempotenteBody habitual
GETleer representaciónsísíno
HEADheaders de un GET sin bodysísíno
POSTcrear o ejecutar acciónnono necesariamentesí
PUTreemplazar recurso conocidonosísí
PATCHmodificar parcialmentenodepende del contratosí
DELETEeliminarnodebería serloopcional
OPTIONScapacidades y preflight CORSsísíno habitual

“Seguro” significa que no debería cambiar estado de negocio; “idempotente” significa que repetir la misma operación produce el mismo efecto final. Una request idempotente todavía puede generar logs, métricas o costos.

No realices mutaciones con GET: crawlers, prefetch y cachés pueden ejecutarlo sin intención de confirmar una acción.

La request puede atravesar varias capas:

  1. CDN o edge: contenido cacheado, compresión, routing geográfico.
  2. WAF y protección DDoS: filtra patrones y limita abuso.
  3. Reverse proxy / gateway: termina TLS, enruta y aplica políticas.
  4. Balanceador: elige una instancia saludable.
  5. Aplicación: autentica, autoriza, valida y ejecuta el caso de uso.
  6. Caché de aplicación: evita trabajo repetido cuando es válido.
  7. Base de datos o servicios: obtienen o cambian estado.
  8. Serialización: produce HTML, JSON, archivo o stream.

Cada salto puede agregar latencia, timeout y un tipo de error. Usa un request id o trace id para seguir una operación entre servicios sin registrar secretos.

El Time to First Byte combina red hasta el servidor, colas, procesamiento y regreso del primer byte. Un TTFB alto no demuestra por sí solo que la base de datos sea lenta; hay que medir cada segmento.

El header Server-Timing permite exponer duraciones controladas a DevTools y Performance API:

Server-Timing: db;dur=32, app;dur=48, cache;desc="miss"

No expongas nombres internos o detalles sensibles innecesarios.

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: br
Cache-Control: no-cache
ETag: "page-v42"
Content-Security-Policy: default-src 'self'
<!doctype html>...
RangoSignificadoEjemplos
1xxinformación provisional100, 103
2xxoperación aceptada o completada200, 201, 204, 206
3xxredirección o caché301, 302, 304, 307, 308
4xxproblema atribuible a la request400, 401, 403, 404, 409, 422, 429
5xxservidor o upstream no pudo responder500, 502, 503, 504
StatusUso habitual
200 OKrespuesta normal con body
201 Createdrecurso creado; puede incluir Location
202 Acceptedtrabajo aceptado pero aún no terminado
204 No Contentéxito sin body
206 Partial Contentrango parcial, común en media
304 Not Modifiedusa la representación cacheada; sin body nuevo
400 Bad Requestsintaxis o entrada inválida
401 Unauthorizedfalta autenticación válida
403 Forbiddenidentidad conocida sin permiso
404 Not Foundrecurso inexistente o deliberadamente oculto
409 Conflictconflicto con el estado actual
422 Unprocessable Contentestructura válida con errores semánticos
429 Too Many Requestslímite excedido; puede incluir Retry-After
500 Internal Server Errorfallo no esperado
502 Bad Gatewayrespuesta inválida de upstream
503 Service Unavailableindisponibilidad temporal
504 Gateway Timeoutupstream excedió el tiempo

No devuelvas 200 para todos los resultados. El status permite a clientes, cachés, proxies y observabilidad entender la operación.

ÁreaHeaders frecuentes
tipo y tamañoContent-Type, Content-Length
compresiónAccept-Encoding, Content-Encoding
cachéCache-Control, ETag, Last-Modified, Vary, Age
negociaciónAccept, Accept-Language
autenticaciónAuthorization, WWW-Authenticate, Cookie, Set-Cookie
rangoRange, Accept-Ranges, Content-Range
redirecciónLocation
seguridadContent-Security-Policy, Strict-Transport-Security, X-Content-Type-Options
CORSAccess-Control-Allow-Origin y familia
descargaContent-Disposition
referenciaReferer, Referrer-Policy

Los nombres de header no distinguen mayúsculas. Algunos son hop-by-hop y no deben reenviarse indiscriminadamente entre proxies.

DirectivaSignificado práctico
max-age=Nfrescura en segundos desde navegador/origen
s-maxage=Nfrescura para cachés compartidas
publicpuede almacenarse en caché compartida
privatesolo caché privada del usuario
no-cachepuede guardar, pero debe revalidar antes de reutilizar
no-storeno almacenar
immutableno cambiará durante su vida fresca
must-revalidateno servir stale una vez vencido sin validar
stale-while-revalidate=Nservir stale mientras actualiza en segundo plano
stale-if-error=Npermitir stale durante un error

no-cache no significa “no guardar”; significa “revalidar”. Para datos altamente sensibles, revisa no-store, historial, Service Worker y cachés intermedias como un conjunto.

Cache-Control: public, max-age=31536000, immutable

Un archivo como app.a1b2c3.js puede cachearse por largo tiempo porque un cambio genera otra URL.

Cache-Control: no-cache
ETag: "home-v42"

En la siguiente navegación:

If-None-Match: "home-v42"

Si no cambió:

HTTP/1.1 304 Not Modified
ETag: "home-v42"

El navegador reutiliza el body existente. Last-Modified y If-Modified-Since ofrecen otra validación, menos precisa que un ETag bien definido.

Vary: Accept-Encoding, Accept-Language

Indica qué headers cambian la representación. Vary: * impide reutilización normal; variar por cookies o demasiados headers puede fragmentar el caché y reducir su eficacia.

El cliente anuncia formatos:

Accept-Encoding: gzip, br
Accept: text/html,application/xhtml+xml

El servidor selecciona:

Content-Type: text/html; charset=utf-8
Content-Encoding: br
Vary: Accept-Encoding

Brotli o gzip reducen HTML, CSS, JS, SVG y JSON. Formatos ya comprimidos como JPEG, WebP, AVIF, video o ZIP suelen ganar poco al recomprimirse en HTTP.

Envía el Content-Type correcto y X-Content-Type-Options: nosniff cuando corresponda; no confíes en que el navegador adivine contenido ejecutable.

StatusMétodo en siguiente requestUso
301clientes históricos pueden convertir POST en GETmovimiento permanente
302clientes históricos pueden convertir POST en GETredirección temporal general
303cambia a GETpatrón Post/Redirect/Get
307conserva método y bodytemporal estricta
308conserva método y bodypermanente estricta

Cada redirección puede añadir otra vuelta de red. Evita cadenas como HTTP → HTTPS → www → locale cuando el primer salto puede ir directamente al destino.

El navegador puede empezar a parsear HTML antes de recibir el documento completo. El preload scanner descubre recursos mientras el parser principal trabaja.

<link
rel="stylesheet"
href="/styles.css"
/>
<script
type="module"
src="/app.js"
></script>
<img
src="/hero.avif"
alt=""
fetchpriority="high"
/>

El orden del HTML, los hints y la prioridad influyen en cuándo se descubren y solicitan recursos. No marques todo como prioridad alta: la prioridad solo tiene sentido por comparación.

El parser convierte tokens en nodos. HTML inválido puede ser reparado de forma distinta a la estructura que imaginabas; revisa el DOM final en DevTools.

Las hojas de estilo aplicables participan en el CSSOM y suelen bloquear el primer render para evitar pintar una página sin estilos. Divide por necesidad real, elimina CSS no usado y evita imports en cascada.

TipoBloquea parserOrdenMomento
clásico sin atributosídocumentoal encontrarlo
clásico defernoconserva ordendespués de parsear, antes de DOMContentLoaded
clásico asyncnoorden de descargaal terminar de descargar
módulono por defectografo y dependenciasdiferido por defecto
módulo asyncnoal estar listono espera orden normal
<script
src="/legacy.js"
defer
></script>
<script
type="module"
src="/app.js"
></script>

Un script puede bloquear el hilo principal aunque se descargue de forma asíncrona. async y defer cambian descarga/ejecución respecto al parser, no vuelven barato el trabajo ejecutado.

DOM + CSSOM
↓
render tree
↓
layout
↓
paint
↓
composite
PasoDecide
DOMestructura y contenido
CSSOMreglas y valores calculados
render treequé cajas visibles participan
layouttamaño y posición
paintpíxeles de texto, fondos, bordes y sombras
compositecombinación de capas en pantalla

Cambiar texto, clases o estilos puede invalidar parte de este trabajo. Propiedades geométricas suelen provocar layout; colores y sombras pueden requerir paint; transform y opacity pueden resolverse mediante composición cuando la capa está disponible.

No agregues will-change indiscriminadamente: promover capas consume memoria y puede empeorar el rendimiento.

  • Una imagen sin dimensiones conocidas puede producir cambios de layout; define width/height o aspect-ratio.
  • loading="lazy" es adecuado para imágenes fuera del primer viewport, no para el elemento LCP principal.
  • srcset y sizes evitan descargar una imagen mayor de lo necesario.
  • Las fuentes pueden bloquear texto o cambiar métricas; usa formatos modernos, subconjuntos y una estrategia de font-display.
  • Un iframe o script de terceros puede abrir nuevas conexiones y ejecutar trabajo no controlado.
Estado/eventoQué garantiza
readyState: 'loading'parser todavía trabaja
readyState: 'interactive'DOM parseado
DOMContentLoadedDOM parseado y scripts diferidos ejecutados
readyState: 'complete'documento y subrecursos principales terminaron
loadrecursos como imágenes y hojas terminaron o fallaron
pageshowdocumento se muestra, incluso desde back-forward cache

DOMContentLoaded no espera todas las imágenes. No esperes load para conectar una interfaz que solo necesita DOM.

document.addEventListener(
"DOMContentLoaded",
() => {
document.readyState // 'interactive'
},
{ once: true }
)
window.addEventListener(
"load",
() => {
document.readyState // 'complete'
},
{ once: true }
)

Una navegación tradicional reemplaza el documento. Una SPA puede interceptar un enlace, llamar history.pushState, obtener datos y cambiar el DOM sin recargar HTML principal.

Aunque no exista recarga completa, la SPA debe conservar:

  • URL compartible;
  • historial atrás/adelante;
  • título y metadatos relevantes;
  • foco y anuncio del cambio de vista;
  • cancelación de requests anteriores;
  • manejo de error y carga;
  • render inicial rápido.

La back-forward cache puede conservar una página completa en memoria al navegar y restaurarla. Usa pageshow/pagehide y evita asumir que todo inicio viene de una carga de red.

const [navigation] = performance.getEntriesByType("navigation")
const metrics = {
dns: navigation.domainLookupEnd - navigation.domainLookupStart,
connection: navigation.connectEnd - navigation.connectStart,
tls:
navigation.secureConnectionStart > 0
? navigation.connectEnd - navigation.secureConnectionStart
: 0,
ttfb: navigation.responseStart - navigation.requestStart,
download: navigation.responseEnd - navigation.responseStart,
domReady: navigation.domContentLoadedEventEnd - navigation.startTime,
total: navigation.loadEventEnd - navigation.startTime,
protocol: navigation.nextHopProtocol,
transferSize: navigation.transferSize
}
metrics
// por ejemplo:
// {
// dns: 12,
// connection: 48,
// tls: 30,
// ttfb: 120,
// download: 25,
// domReady: 430,
// total: 780,
// protocol: 'h2',
// transferSize: 18420
// }

Estas duraciones son del navegador actual, no una verdad universal. Conexiones reutilizadas, caché, privacidad y navegaciones especiales pueden producir ceros o datos limitados.

const slowResources = performance
.getEntriesByType("resource")
.filter((resource) => resource.duration > 500)
.map((resource) => ({
name: resource.name,
type: resource.initiatorType,
duration: Math.round(resource.duration),
bytes: resource.transferSize
}))
slowResources
// recursos que tardaron más de 500 ms

Los recursos cross-origin necesitan Timing-Allow-Origin para exponer algunas métricas detalladas.

FasePosible causa si es alta
Queueing/Stalleddemasiadas prioridades o conexiones, límite del navegador
DNS Lookupdominio nuevo o resolución lenta
Initial connectionlatencia y handshake
SSLnegociación TLS y certificados
Request sentbody grande o subida lenta
Waiting/TTFBred + cola + servidor
Content Downloadrespuesta grande o conexión lenta

Revisa también initiator, prioridad, protocol, tamaño transferido, compresión, caché y redirects. Optimizar el segmento equivocado no mejora el resultado.

  • HTTPS cifra en tránsito, pero no corrige XSS, inyección ni autorización.
  • Mixed content puede bloquear recursos HTTP dentro de una página HTTPS.
  • CORS controla lectura desde otro origen en navegadores; no autentica ni protege el servidor de requests directas.
  • CSP reduce impacto de inyección al limitar fuentes ejecutables.
  • Cookies de sesión deben revisar HttpOnly, Secure, SameSite, dominio, path y expiración.
  • El servidor debe validar host, método, body, tipo, tamaño, autenticación y autorización.
  • Proxies y CDN necesitan límites, timeouts y claves de caché correctas para evitar mezclar respuestas de usuarios.
SíntomaRevisa primero
tarda antes del primer byteredirects, DNS/conexión, CDN, servidor, base de datos
HTML llega rápido pero nada se veCSS bloqueante, JS síncrono, fuente, render crítico
contenido aparece y saltadimensiones de media, fuentes, contenido insertado tarde
carga rápida pero interacción lentatareas largas, hidratación, listeners y JavaScript enviado
segunda visita no mejoraheaders de caché, ETag, hash de assets, service worker
solo falla cross-originCORS, cookies, credentials, preflight y certificados
funciona con recarga pero no al volverbfcache, estado conservado, pageshow y cleanup

La carga termina técnicamente en load, pero la experiencia continúa: interacción, requests posteriores, lazy loading, fuentes y tareas de JavaScript también determinan si la página se siente rápida y estable.