← Назад к вопросам

Кэшируется ли GET-запрос

2.0 Middle🔥 133 комментариев
#Браузер и сетевые технологии

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

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

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

Кэширование GET-запроса: подробный разбор

Да, GET-запросы по умолчанию кэшируются браузерами и промежуточными прокси-серверами. Это фундаментальное свойство HTTP, основанное на принципе идемпотентности метода GET (многократное выполнение одного запроса должно давать одинаковый результат). Однако важно понимать, что кэширование — это не абсолютное правило, а гибкий механизм, управляемый HTTP-заголовками.

Как работает кэширование GET-запросов

Кэширование контролируется в первую очередь сервером через следующие ключевые заголовки:

  • Cache-Control (современный стандарт, заменяющий Expires):
    Cache-Control: max-age=3600, public
    
    Этот заголовок — основной инструмент. Значение `max-age=3600` говорит браузеру: «храни ответ в кэше 3600 секунд (1 час)». Параметр `public` разрешает кэширование публичными прокси. `private` — только браузером пользователя. `no-store` — полностью запрещает кэширование (ни браузером, ни прокси). `no-cache` — не означает «не кэшировать», а «перед использованием кэша необходимо проверить актуальность на сервере».

  • Expires (устаревший, но поддерживаемый):
    Expires: Wed, 21 Oct 2024 07:28:00 GMT
    
    Указывает абсолютную дату истечения срока действия кэшированной версии.

  • ETag (Entity Tag) и Last-Modified — для условных запросов (Conditional Requests):
    *   Сервер отправляет ответ с `ETag` (хеш-идентификатор версии контента) или `Last-Modified` (дата изменения).
    *   При повторном запросе браузер отправляет `If-None-Match` (значение предыдущего `ETag`) или `If-Modified-Since`.
    *   Если контент не изменился, сервер возвращает статус **`304 Not Modified`** (без тела ответа), и браузер использует локальную кэшированную копию. Это экономит трафик и ускоряет загрузку.

Пример жизненного цикла кэшированного GET-запроса

  1. Первый запрос:
    GET /api/products/123 HTTP/1.1
    Host: example.com
    
    **Ответ сервера:**
```http
HTTP/1.1 200 OK
Cache-Control: max-age=300, public
ETag: "xyz123"
Content-Type: application/json

{"id": 123, "name": "Телефон", "price": 999}
```
    Браузер сохраняет ответ в кэше вместе с метаданными (`ETag`, `max-age`).

  1. Повторный запрос (до истечения max-age):
    Браузер **вообще не отправляет сетевой запрос**. Данные мгновенно извлекаются из **кеша памяти (memory cache)** или **дискового кэша (disk cache)**.

  1. Запрос после истечения max-age (или при принудительном обновлении Ctrl+F5):
    Браузер отправляет **условный запрос**:
```http
GET /api/products/123 HTTP/1.1
Host: example.com
If-None-Match: "xyz123"
```
    Если ресурс не менялся, сервер отвечает `304 Not Modified`, и браузер обновляет срок жизни кэшированной копии.

Особенности и управление кэшированием на клиенте (в JavaScript)

  • Fetch API: По умолчанию ведет себя аналогично браузеру, учитывая заголовки. Но вы можете управлять кэшем через опцию cache:

    // Разные стратегии кэширования в fetch
    fetch('/api/data', { cache: 'default' }); // следует HTTP-заголовкам (поведение по умолчанию)
    fetch('/api/data', { cache: 'no-store' }); // полностью игнорирует кэш браузера и HTTP-кэш
    fetch('/api/data', { cache: 'reload' }); // обходит кэш, но сохраняет ответ (как Ctrl+F5)
    fetch('/api/data', { cache: 'force-cache' }); // использует кэш, даже если он устарел
    fetch('/api/data', { cache: 'only-if-cached' }); // использует только кэш, сетевой запрос не отправляется
    
  • XMLHttpRequest: Также обычно следует HTTP-заголовкам, но тонкое управление сложнее.

  • Библиотеки (Axios): Работают поверх XHR/fetch, поэтому наследуют их поведение. Для принудительного обхода кэша часто используют параметр-метку времени (timestamp) или отключение кэша в заголовках:

    // Способ 1: Добавление уникального query-параметра
    axios.get('/api/data', { params: { _t: Date.now() } });
    
    // Способ 2: Установка заголовков запроса
    axios.get('/api/data', {
      headers: { 'Cache-Control': 'no-cache' }
    });
    

Практические выводы для Frontend-разработчика

  1. Сервер определяет политику. Ваш бэкенд или CDN должен правильно настраивать Cache-Control, ETag для статики (CSS, JS, изображения) и динамических API.
  2. Статика: Устанавливайте длительный max-age (например, max-age=31536000 — год) и используйте хеширование имен файлов (например, app.a1b2c3.js). Это позволяет кэшировать надолго, а при обновлении новое имя файла заставит браузер загрузить свежую версию.
  3. Динамические данные (API): Используйте max-age=0 или no-cache вместе с ETag/Last-Modified для баланса между актуальностью и производительностью. Для абсолютно свежих данных — no-store.
  4. Отладка: В DevTools на вкладке Network следите за столбцами Size (значения memory cache, disk cache указывают на загрузку из кэша) и статусами 304. Вкладка Application > Cache Storage показывает содержимое Cache API.

Итог: GET-запросы кэшируются, но это контролируемый процесс. Понимание механизмов Cache-Control, ETag и условных запросов критически важно для создания быстрых и эффективных веб-приложений, минимизирующих нагрузку на сервер и трафик пользователя.