flowchart LR U["URL + Enter"] --> N["1. Network<br/>GET index.html, app.js, styles.css"] N --> P["2. Parse<br/>HTML → árbol DOM"] P --> J["3. Motor JS<br/>ejecuta app.js<br/>(puede tocar el DOM)"] J --> R["4. Render<br/>DOM + CSS → píxeles"]
1 F1. El navegador es un runtime
Qué pasa de verdad cuando escribes una URL y le das Enter
Vas a entender qué hace el navegador con tu código: descarga archivos, construye el DOM, ejecuta JavaScript y pinta píxeles. Cuando entiendas que el navegador es un runtime (como Node, pero con pantalla), todo lo demás del frontend se acomoda solo.
1.1 El problema
Escribes localhost:5173, le das Enter, y aparece tu app. ¿Qué pasó en el medio? La mayoría de la gente que “sabe frontend” no puede responder esto completo — y es la base de todo lo que viene.
localhost significa “esta misma máquina” — es la dirección que tu computadora usa para hablarse a sí misma. Cuando desarrollas, el “servidor” y el “cliente” viven en tu laptop: por eso todo es localhost:3000.
Escribes URL → el navegador pide archivos → los interpreta → pinta
Ese flujo simple esconde cuatro actores: la red (HTTP), el parser (HTML→DOM), el motor JS (que ejecuta tu código) y el motor de renderizado (que pinta). Aquí los destapamos uno por uno — sin teoría vacía, cada uno con algo que puedes ver ahora en tu navegador.
El DOM es la página como árbol de objetos vivos: HTML es el papel, el DOM es lo que JavaScript puede tocar. element.textContent = "hola" cambia el DOM y el navegador repinta — el HTML original no se entera.
1.2 Cómo lo resuelve un equipo
Cuando algo “no se ve”, un frontend senior no adivina: abre las DevTools y mira qué etapa falló:
- ¿Llegaron los archivos? → pestaña Network (¿algún request rojo 404/500?)
- ¿Se construyó el DOM? → pestaña Elements (¿el HTML tiene lo esperado?)
- ¿Corrió el JS? → pestaña Console (¿algún error rojo?)
- ¿Se pintó pero mal? → pestaña Styles/Computed
Esa división (red / estructura / lógica / pintura) es el mapa del navegador — y del debugging de frontend entero.
1.3 Conceptos nuevos
- U Runtime: el programa que ejecuta tu código. El navegador es el runtime del frontend; Node es el mismo motor (V8) sin pantalla.
El runtime es el motor que ejecuta tu código: Node.js es el runtime de JavaScript fuera del navegador; CPython es el de Python; Go compila a binario y el runtime va empaquetado dentro. Es “quien corre” lo que escribiste.
- U DOM: el árbol de objetos que el navegador construye al leer tu HTML — lo que JavaScript puede tocar.
- U Render blocking: el navegador pausa cuando encuentra
<script>— por eso importa dónde pones los scripts. - U DevTools: el debugger que ya llevas instalado — Network, Elements, Console, Sources.
1.4 La explicación visual
Míralo en vivo: abre cualquier página, presiona F12 → pestaña Network, recarga. Cada fila es un archivo que el navegador pidió — ese es el paso 1.
1.5 Implementación
La página mínima que demuestra las 4 etapas — crea index.html y ábrela:
<!DOCTYPE html>
<html>
<head>
<style>
.card { border: 2px solid #2563eb; padding: 1rem; }
</style>
</head>
<body>
<div id="app" class="card">Cargando…</div>
<script>
// Paso 3: el motor JS toca el DOM construido en el paso 2
document.getElementById("app").textContent =
"El navegador construyó el DOM y JS lo modificó";
</script>
</body>
</html>Qué estás viendo: el navegador parseó el HTML a un árbol (paso 2), ejecutó el script que modificó ese árbol (paso 3) y pintó el resultado con el CSS (paso 4). El paso 1 fue traer index.html desde tu disco o servidor.
Explícame el ciclo de vida completo de una página web cuando escribo una
URL y presiono Enter: qué archivos pide el navegador, en qué orden, qué es
el DOM y cuándo se ejecuta el JavaScript. Usa este HTML de ejemplo:
[pegar tu index.html]. Quiero una explicación paso a paso, no una
definición de Wikipedia — y dime qué puedo ver en DevTools para
comprobar cada etapa.
1.6 ¿Por qué importa esto para backend?
Lo único que necesitas llevarte: el navegador es un cliente HTTP con pantalla. Cuando en la Sección II construyas el servidor, tu única misión será responder bien al paso 1 — el navegador hace el resto.
El motor JS de Chrome es V8 — el mismo que corre Node.js. Por eso JavaScript “saltó” del navegador al servidor: Node es V8 + APIs de sistema (archivos, red, procesos) en vez de APIs de navegador (DOM, eventos, canvas). Mismo lenguaje, distintas herramientas alrededor — esa es toda la diferencia frontend/backend a nivel runtime.
1.7 Errores comunes
- Confundir el archivo con lo que se ve: el HTML que escribiste no es lo que se pinta — es lo que el DOM tiene después de que JS lo tocó. Mira Elements, no el archivo.
- Script antes del DOM: si tu script corre antes de que exista el elemento,
getElementByIddevuelvenull. Por eso los scripts van al final del<body>o condefer.
null (TS), None (Py), nil (Go) = “aquí no hay valor”. Es la respuesta a “¿qué devuelvo cuando no hay nada?” — y la fuente del bug más famoso de la historia (su inventor lo llamó “el error del billón de dólares”). Por eso el código revisa if x is not None.
return hace dos cosas a la vez: devuelve el resultado Y termina la función — lo que esté debajo nunca corre. return task = “aquí está el plato, salgo de la cocina”.
- Debuggear a ciegas: editar HTML sin mirar Network/Console es apagar fuegos con los ojos cerrados.
1.8 Buenas prácticas
- DevTools abiertas siempre mientras desarrollas — son tu debugger, no un accesorio.
type="module"ydeferpara scripts modernos — respetan el orden y no bloquean el parse.
Serializar es convertir un objeto en memoria a texto viajero (JSON.stringify); parsear/deserializar es el viaje de vuelta (JSON.parse). Todo lo que cruza la red o la BD pasa por este par.
- Pregunta “¿en qué etapa estoy?” ante cualquier bug: ¿llegó el archivo? ¿está en el DOM? ¿corrió el JS? ¿se pintó?
1.9 Ejercicio
- Crea el
index.htmlde arriba, ábrelo y cambia el texto del div desde la consola de DevTools (document.getElementById("app").textContent = "otro"). ¿Qué pasó — el archivo cambió o el DOM? - En Network, recarga y encuentra el request de
index.html: mira su status, su tamaño y su tiempo.
Un request (petición) es el mensaje que un cliente le manda al servidor: “quiero X”. Tiene una dirección (URL), un verbo (GET, POST…), headers (metadatos) y a veces un body (los datos). La respuesta es el response.
La terminal (consola, línea de comandos) es la interfaz de texto con el sistema operativo: escribes comandos, lees resultados. Es como hablarle a la computadora por cartas en vez de señalar con el mouse.
1.10 Mini reto
Abre una web real (cualquiera) y responde solo con DevTools: ¿cuántos requests hizo al cargar? ¿cuál fue el más lento? ¿hay algún error en Console? Esas tres respuestas son el 80% del diagnóstico frontend.
Ejercicio 1. Cambió el DOM en memoria, no el archivo — si recargas, vuelve el texto original. Esa es la lección del capítulo: el navegador pinta el DOM (árbol vivo), no tu archivo.
Ejercicio 2. En Network verás index.html con status 200, tipo document, y su tiempo de descarga — el paso 1 del diagrama.
Mini reto. Respuesta modelo: una página típica hace 20–80 requests (HTML + JS + CSS + imágenes + APIs). El más lento suele ser un bundle JS grande o una API — ordena por columna “Time” en Network. Errores rojos en Console = JS que falló en el paso 3.
1.11 Vocabulario técnico del capítulo
Un objeto es una colección de datos con nombre: {name: "Ana", age: 30} — cada dato es una propiedad (clave → valor). Python los llama dict, Go los arma con struct, TS con objetos/interface.
Una clase es el molde de un objeto: define qué datos y qué métodos tiene. class Task es el molde; new Task() es una instancia concreta. Go no tiene clases — usa struct + métodos sueltos.
Los tipos (int, string, boolean, Task) son el contrato de cada dato. Tipado estático (TypeScript, Go, Python con hints) = los tipos se revisan al escribir, no cuando explota en producción.
El cliente es quien pide: el navegador, una app móvil, otro servidor. El servidor es quien atiende y responde. La misma computadora puede ser cliente de una cosa y servidor de otra.
Un proceso es un programa en ejecución: el sistema operativo le da memoria propia y un lugar en la fila del CPU. Tu API es un proceso; Postgres es otro; el navegador es varios. Que “se caiga el proceso” = el programa murió.
La memoria RAM es el escritorio de trabajo del programa: rápida, pero se borra al apagar. Los datos que deben sobrevivir van a disco o a la base de datos. Por eso let tasks = [] pierde todo al reiniciar.
Un evento es “algo que pasó” convertido en dato: el click del usuario, el payment.succeeded del webhook, el mensaje del socket. La programación moderna es reaccionar a eventos más que seguir un guion.
Una traza sigue un request a través de todo el sistema: entró por el gateway → llamó auth → consultó la BD → tardó 340ms en la query. Cuando algo anda lento, la traza dice exactamente dónde.
Una API (Application Programming Interface) es el menú de un programa: la lista de operaciones que otros programas pueden pedirle. Tu frontend no habla con la base de datos — le pide cosas a la API, y la API decide.