\n\n\n

Hello

\n \n \n\n\n\"\"\"\n\n# Процесс рендеринга:\n# 1. Parse HTML → DOM Tree\n# 2. Fetch CSS → CSS Object Model (CSSOM)\n# 3. Combine DOM + CSSOM → Render Tree\n# 4. Layout (вычислить размер и позицию)\n# 5. Paint (покрасить пиксели)\n# 6. Composite (объединить слои)\n\n# Параллельно:\n# - Fetch CSS файлы (блокирует рендеринг)\n# - Fetch JS файлы (блокирует HTML парсинг)\n# - Fetch images (не блокирует, загружаются асинхронно)\n```\n\n### 10. Fetch ресурсов\n\n```\nБраузер видит в HTML:\n- \n-
← Назад к вопросам

Что происходит после вбивания в адресную строку браузера?

2.0 Middle🔥 201 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что происходит после вбивания URL в адресную строку браузера

Этот вопрос проверяет системное мышление и понимание web стека. Расскажу подробно от нажатия клавиши до отображения страницы.

1. Ввод и парсинг URL

Момент: пользователь вводит "https://example.com/page"

# Браузер парсит URL:
from urllib.parse import urlparse

url = "https://example.com:443/page?id=123#top"
parsed = urlparse(url)

print(f"Scheme: {parsed.scheme}")      # https
print(f"Netloc: {parsed.netloc}")      # example.com:443
print(f"Hostname: {parsed.hostname}")  # example.com
print(f"Port: {parsed.port}")          # 443
print(f"Path: {parsed.path}")          # /page
print(f"Query: {parsed.query}")        # id=123
print(f"Fragment: {parsed.fragment}")  # top

# Внимание:
# - Fragment (#top) НЕ отправляется на сервер
# - Это используется только браузером для скролла
# - Запрос идёт на: example.com/page?id=123

2. Проверка кеша и истории

# Браузер проверяет:

# 1. Кеш браузера
# Если есть в кеше и не истёк:
#   → Вернуть из кеша (супер быстро)
#   → HTTP headers определяют валидность:
#      - Cache-Control: max-age=3600 (кеш 1 час)
#      - ETag: "abc123" (проверить изменения)
#      - Last-Modified: 2024-01-01 (проверить дату)

# 2. Проверить HSTS (HTTP Strict Transport Security)
if url.startswith("http://"):
    # Если домен в HSTS list → автоматически перевести на https
    url = url.replace("http://", "https://")

# 3. Redirect'ы
# Если было 301/302 ранее → использовать сохранённый redirect

3. DNS Lookup

┌─────────────────────────────────────────┐
│ Браузер: Какой IP адрес у example.com? │
└─────────────────────────────────────────┘
     ↓
┌─────────────────────────────────────────┐
│ Кеш браузера (локально)                 │
│ Есть ли уже результат? (~1 час)        │
└─────────────────────────────────────────┘
     ↓ (если не в кеше)
┌─────────────────────────────────────────┐
│ Кеш ОС                                  │
│ Windows: ipconfig /displaydns           │
│ Linux: systemctl status systemd-resolved│
└─────────────────────────────────────────┘
     ↓ (если не в кеше ОС)
┌─────────────────────────────────────────┐
│ Рекурсивный resolver (обычно ISP)       │
│ 8.8.8.8, 1.1.1.1                       │
└─────────────────────────────────────────┘
     ↓
┌─────────────────────────────────────────┐
│ Root nameserver (.com)                  │
└─────────────────────────────────────────┘
     ↓
┌─────────────────────────────────────────┐
│ TLD nameserver (example.com registry)   │
└─────────────────────────────────────────┘
     ↓
┌─────────────────────────────────────────┐
│ Authoritative nameserver (owner)        │
│ "A example.com. 93.184.216.34"         │
└─────────────────────────────────────────┘
     ↓
┌─────────────────────────────────────────┐
│ Браузер: 93.184.216.34 это example.com │
└─────────────────────────────────────────┘

Практический пример:

import socket
import time

start = time.time()
# Это делает браузер
ip = socket.gethostbyname("example.com")
print(f"example.com → {ip}")
print(f"DNS lookup took: {time.time() - start:.2f}s")
# Output:
# example.com → 93.184.216.34
# DNS lookup took: 0.05s  (if cached)
# DNS lookup took: 1.50s  (if not cached, typical)

4. Установка TCP соединения (Three-Way Handshake)

Томография TCP соединения:

браузер (93.184.216.34:443) ← ← ← пример.com

Шаг 1: SYN (браузер)
  браузер: "Привет, я хочу соединиться, мой номер последовательности = 1000"
  ↓ (отправляет пакет)

Шаг 2: SYN-ACK (сервер)
  сервер: "Хорошо, я получил 1000. Мой номер последовательности = 5000"
  ↓ (отправляет пакет)

Шаг 3: ACK (браузер)
  браузер: "Спасибо, я подтверждаю 5000. Теперь отправляй данные"
  ↓ (отправляет пакет)

Соединение установлено! (обычно 50-300ms)

Код (как это выглядит в Python):

import socket
import time

socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_obj.settimeout(10)  # 10 сек таймаут

start = time.time()
try:
    # Три пакета выше отправляются автоматически
    socket_obj.connect(("93.184.216.34", 443))
    print(f"TCP connection established in {time.time() - start:.2f}s")
except socket.timeout:
    print("Connection timeout")

5. TLS Handshake (для HTTPS)

Если HTTPS (443 порт), нужен TLS handshake:

┌─────────────────────────────────────────────────┐
│ 1. Client Hello                                 │
│    Браузер отправляет:                          │
│    - Поддерживаемые версии TLS (1.2, 1.3)      │
│    - Cipher suites (методы шифрования)         │
│    - Random number (nonce)                      │
│    - Extensions (SNI, ALPN, и т.д.)            │
└─────────────────────────────────────────────────┘
     ↓ (100+ bytes)
┌─────────────────────────────────────────────────┐
│ 2. Server Hello                                 │
│    Сервер отправляет:                          │
│    - Выбранная версия TLS                      │
│    - Выбранный cipher suite                    │
│    - Сертификат (public key)                   │
│    - Random number (nonce)                      │
└─────────────────────────────────────────────────┘
     ↓ (1-2 KB)
┌─────────────────────────────────────────────────┐
│ 3. Key Exchange                                 │
│    Браузер вычисляет:                          │
│    - Session key (shared secret)               │
│    - Шифрует его public key'ем сервера         │
└─────────────────────────────────────────────────┘
     ↓ (128 bytes)
┌─────────────────────────────────────────────────┐
│ 4. Finished                                     │
│    Обе стороны подтверждают готовность         │
└─────────────────────────────────────────────────┘
     ↓
Теперь всё шифруется!

Время: 100-200ms (network RTT зависит)

6. HTTP Request

Браузер отправляет:

request = """
GET /page?id=123 HTTP/1.1
Host: example.com
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Cookie: session_id=abc123def456
If-None-Match: "abc123"  # Если в кеше
"""

# Что браузер отправляет:
# 1. Method (GET, POST, PUT, DELETE)
# 2. Path + Query (/page?id=123)
# 3. HTTP version (1.1 или 2.0 или 3.0)
# 4. Headers (Host, User-Agent, Accept, и т.д.)
# 5. Body (если POST/PUT)

7. Серверная обработка

# На сервере (FastAPI example):

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get("/page")
async def get_page(id: int = None, request: Request):
    # 1. Парсинг query параметров
    print(f"Query: {request.query_params}")  # id=123
    
    # 2. Парсинг headers
    print(f"User-Agent: {request.headers.get('user-agent')}")
    
    # 3. Парсинг cookies
    print(f"Session: {request.cookies.get('session_id')}")
    
    # 4. Проверка кеша (If-None-Match)
    if request.headers.get('if-none-match') == '"abc123"':
        return Response(status_code=304)  # Not Modified
    
    # 5. Обработка запроса (database queries, etc.)
    page_content = fetch_page_from_database(id)
    
    # 6. Отправка ответа
    return HTMLResponse(
        content=page_content,
        headers={
            'ETag': '"abc123"',
            'Cache-Control': 'max-age=3600',
            'Content-Type': 'text/html; charset=utf-8'
        }
    )

8. HTTP Response

Сервер отправляет:

HTTP/1.1 200 OK
Date: Mon, 23 Mar 2026 12:00:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 45670
ETag: "abc123"
Cache-Control: max-age=3600
Set-Cookie: session_id=xyz789; Path=/; HttpOnly; Secure
Content-Encoding: gzip
Vary: Accept-Encoding

[45670 bytes of HTML content]

9. Парсинг и рендеринг HTML

# Браузер парсит HTML:

html_content = """
<!DOCTYPE html>
<html>
<head>
    <title>Example</title>
    <link rel="stylesheet" href="/static/style.css">
    <script src="/static/jquery.js"></script>
</head>
<body>
    <h1>Hello</h1>
    <img src="/image.jpg">
    <script src="/static/app.js"></script>
</body>
</html>
"""

# Процесс рендеринга:
# 1. Parse HTML → DOM Tree
# 2. Fetch CSS → CSS Object Model (CSSOM)
# 3. Combine DOM + CSSOM → Render Tree
# 4. Layout (вычислить размер и позицию)
# 5. Paint (покрасить пиксели)
# 6. Composite (объединить слои)

# Параллельно:
# - Fetch CSS файлы (блокирует рендеринг)
# - Fetch JS файлы (блокирует HTML парсинг)
# - Fetch images (не блокирует, загружаются асинхронно)

10. Fetch ресурсов

Браузер видит в HTML:
- <link href="/style.css">
- <script src="/app.js">
- <img src="/image.jpg">

И одновременно запрашивает:

├─ style.css (CSS)
│  └─ Блокирует рендеринг (CSSOM нужен)
│  └─ Загружается за ~50ms
│  └─ Парсится в CSSOM
│  └─ Рендеринг может продолжаться
│
├─ app.js (JavaScript)
│  └─ Блокирует HTML парсинг!
│  └─ Загружается за ~100ms
│  └─ Парсится и выполняется
│  └─ Может модифицировать DOM
│
└─ image.jpg (Image)
   └─ Не блокирует рендеринг
   └─ Загружается асинхронно
   └─ Отображается когда готово

11. Выполнение JavaScript

# JavaScript engine (V8 в Chrome, SpiderMonkey в Firefox)

# Фазы:
# 1. Parsing → AST (Abstract Syntax Tree)
# 2. Compilation → Machine code (JIT)
# 3. Execution → Run code
# 4. Garbage collection → Clean memory

# Когда JS изменяет DOM:
javascript_code = """
const heading = document.getElementById('title');
heading.textContent = 'Updated!';
heading.style.color = 'red';
"""

# Браузер:
# 1. Обновляет DOM
# 2. Пересчитывает CSSOM (если стили изменились)
# 3. Перестраивает Render Tree
# 4. Перепчитывает Layout (переflow)
# 5. Перепарсит Paint
# 6. Recomposite

# Это называется "Reflow" и "Repaint" — дорого!

12. Определение готовности страницы

# DOMContentLoaded
event_name = "DOMContentLoaded"
event_when = "HTML парсен и DOM построен, но изображения могут загружаться"
event_time = "~500-2000ms"

# load
event_name = "load"
event_when = "Все ресурсы загружены (изображения, стили, скрипты)"
event_time = "~2000-5000ms"

# Lighthouse metrics (Core Web Vitals):
metrics = {
    "FCP": "First Contentful Paint (первый контент)",
    "LCP": "Largest Contentful Paint (самый большой контент)",
    "CLS": "Cumulative Layout Shift (прыганье элементов)",
    "FID": "First Input Delay (задержка взаимодействия)",
    "TTFB": "Time to First Byte (до первого байта ответа)"
}

13. Полная временная шкала (типично)

  0 ms   │ Пользователь вводит URL и нажимает Enter
      ↓
 50 ms   │ DNS Lookup (может быть из кеша)
      ↓
100 ms   │ TCP Connection (three-way handshake)
      ↓
200 ms   │ TLS Handshake (для HTTPS)
      ↓
250 ms   │ HTTP Request отправлен
      ↓
300 ms   │ Сервер обрабатывает запрос (database queries, etc.)
      ↓
350 ms   │ HTTP Response приходит (TTFB - Time To First Byte)
      ↓
400 ms   │ Браузер начинает парсить HTML
      ↓
600 ms   │ DOMContentLoaded событие (dom готов)
      ↓
700 ms   │ CSS загружен и применён
      ↓
800 ms   │ JS загружен, выполнен, DOM обновлён
      ↓
2000ms   │ Все изображения загружены
      ↓
2100ms   │ load событие (всё готово)

Вывод: полная цепочка

┌────────────────────────────────────────────────┐
│ 1. URL парсинг, кеш проверка                 │
├────────────────────────────────────────────────┤
│ 2. DNS Lookup → IP адрес                      │
├────────────────────────────────────────────────┤
│ 3. TCP Connection (SYN-ACK-ACK)              │
├────────────────────────────────────────────────┤
│ 4. TLS Handshake (для HTTPS)                 │
├────────────────────────────────────────────────┤
│ 5. HTTP Request отправлен                    │
├────────────────────────────────────────────────┤
│ 6. Server обрабатывает (database, etc.)      │
├────────────────────────────────────────────────┤
│ 7. HTTP Response получена                    │
├────────────────────────────────────────────────┤
│ 8. HTML парсинг, DOM построение              │
├────────────────────────────────────────────────┤
│ 9. CSS загружен и применён                   │
├────────────────────────────────────────────────┤
│ 10. JS загружен и выполнен                   │
├────────────────────────────────────────────────┤
│ 11. Изображения загружены                    │
├────────────────────────────────────────────────┤
│ 12. Страница интерактивна (ready)            │
└────────────────────────────────────────────────┘

Общее время: 1-5 секунд (зависит от сети, сервера, сложности страницы)