Топ-50 вопросов для Faq веб-разработчика: что такое Cors и как работает cookie

Этот топ-50 - компактный FAQ веб-разработчика, который закрывает базовые и собеседовательные темы: сеть и браузерные политики (включая что такое CORS), управление доступом (как работают cookie, сессии, JWT), хранение и кеширование, API-дизайн, производительность и деплой. В каждом блоке - короткие ответы и быстрые альтернативы для ограниченных ресурсов.

Краткие практические выводы по 50 вопросам веб-разработчика

  • CORS - это не "фича сервера", а политика браузера: сервер лишь сообщает, кому разрешено читать ответ, через заголовки.
  • Cookie ≠ LocalStorage: cookie ездят в каждом запросе (в пределах правил), а Web Storage - нет; значит, и угрозы/стоимость разные.
  • JWT удобен для масштабирования, но не отменяет сессии: отзыв токена и ротация ключей - ваши обязанности.
  • Кеширование - это слои: HTTP-кеш, CDN, Service Worker, app-кеш; начинайте с корректных заголовков.
  • REST и GraphQL решают разные проблемы: выбирайте по профилю данных, кэшируемости и сложности клиента.
  • Перфоманс чаще ломают мелочи: блокирующие ресурсы, лишний JS, некорректные приоритеты загрузки.
  • Для малых команд важнее наблюдаемость, чем "идеальный CI/CD": логи+метрики+алерты дают больше эффекта, чем редкие релизы.

Сетевые механики и CORS: принцип, отладка и распространённые ошибки

Что такое CORS: это механизм, при котором браузер ограничивает доступ JS-кода страницы к ответам с другого origin (схема+хост+порт). Сервер может разрешить доступ, возвращая заголовки Access-Control-*. Если CORS не настроен, запрос может "уйти", но чтение ответа скриптом будет заблокировано.

CORS не является защитой сервера от запросов как таковых: любой клиент (curl, сервер-сервер, Postman) может обратиться к API. CORS защищает пользователя в браузере от нежелательного чтения ответов чужой страницей.

Preflight (OPTIONS) возникает, когда запрос "непростой" (например, нестандартные заголовки, методы, JSON с Content-Type: application/json). Браузер сначала проверяет, разрешён ли такой запрос, и только потом делает основной.

Практические вопросы (1-10): короткие ответы

  1. Что считается разным origin? Любое отличие в схеме, домене или порту: https://a.com и http://a.com - разные origin.
  2. Почему "CORS error" может быть из-за 500/502? Если сервер упал/прокси вернул ошибку без CORS-заголовков, браузер покажет CORS, потому что не может "прочитать" тело ошибки.
  3. Как быстро проверить CORS без браузера? Через curl увидеть заголовки: curl -i https://api.example.com. Но помните: curl не применяет CORS-политику, он лишь показывает заголовки.
  4. Какие заголовки минимально нужны? Обычно: Access-Control-Allow-Origin. Для cookie/авторизации ещё Access-Control-Allow-Credentials: true и конкретный origin вместо *.
  5. Почему нельзя Allow-Origin: * вместе с credentials? Браузер запрещает: при credentials origin должен быть конкретным, иначе это слишком широкий доступ.
  6. Откуда берётся preflight? Из комбинации метода/заголовков/типа контента. Например, Authorization: Bearer ... почти всегда вызывает preflight.
  7. Как "починить" preflight на бэкенде? Отвечать на OPTIONS быстро и корректно: статус 204/200 + Access-Control-Allow-Methods, -Headers, -Origin.
  8. Почему запрос работает в Postman, но не в браузере? Потому что Postman не ограничен CORS; это типичный сигнал, что проблема в политике браузера.
  9. Можно ли обойти CORS на фронтенде? В проде - нет "честного" обхода. Используют прокси (BFF/реверс-прокси) или переносят запрос на сервер.
  10. Дешёвая альтернатива при ограниченных ресурсах? Поставить один общий домен и проксировать API через Nginx/Caddy, чтобы все запросы стали same-origin.

Чек-лист диагностики CORS (быстро)

Топ-50 вопросов для FAQ веб-разработчика: от
  • Проверьте, есть ли Access-Control-Allow-Origin на реальном ответе и на ответе preflight (OPTIONS).
  • Сверьте origin запроса в DevTools → Network → Request Headers: схема/домен/порт.
  • Если используются cookie/авторизация: включены ли credentials на клиенте и Allow-Credentials на сервере.
  • Убедитесь, что прокси/балансер не "съедает" CORS-заголовки на ошибках.

Управление состоянием доступа: куки, сессии, JWT и безопасные практики

Состояние доступа - это способ связать запрос с пользователем: через cookie+сессию на сервере, через токены (JWT/opaque) на клиенте, или гибридно. Ключевая разница - где хранится "истина" (на сервере или в токене) и как выполняется отзыв.

  • Cookie + серверная сессия: браузер хранит идентификатор, сервер хранит состояние (в памяти/Redis/БД). Плюс - простой отзыв; минус - хранение состояния и масштабирование.
  • JWT: токен несёт данные и подпись. Плюс - меньше серверного состояния; минус - отзыв сложнее (нужны списки блокировки/короткие TTL/ротация).
  • Opaque token: "непрозрачный" токен, проверяется сервером. Часто удобен как компромисс для контроля и аналитики.
  • Refresh/Access токены: короткоживущий access + более долгий refresh снижает ущерб при утечке access.
  • CSRF: актуален, когда авторизация автоматом едет в cookie. Для токенов в заголовке риск обычно иной (часто ближе к XSS/утечкам).
  • XSS: угроза для всего, что читает JS. Поэтому секреты в LocalStorage - сомнительная идея для браузерных приложений с риском XSS.

Практические вопросы (11-20): короткие ответы

  1. Как работают cookie? Сервер ставит Set-Cookie, браузер хранит и автоматически отправляет cookie обратно по правилам домена/пути/срока и атрибутов.
  2. Когда cookie не поедут в запросе? Если домен/путь не совпали, истёк срок, запрещено по SameSite, или кросс-доменный запрос без credentials.
  3. Что выбрать для SPA: cookie-сессия или JWT? Если нужен простой отзыв и контроль - cookie+сессия. Если много сервисов и нужен статлес - JWT/opaque + продуманная ротация.
  4. Зачем HttpOnly? Чтобы JS не мог прочитать cookie (снижает ущерб от XSS для cookie).
  5. Зачем Secure? Чтобы cookie отправлялась только по HTTPS.
  6. Что делает SameSite? Ограничивает отправку cookie в кросс-сайтовых контекстах (важно для CSRF и сторонних встраиваний).
  7. Почему "вышли из аккаунта", но JWT ещё работает? Потому что токен валиден до истечения. Нужен отзыв: короткий TTL, blacklist, смена ключа подписи или серверная проверка состояния.
  8. Дешёвый минимум безопасности при малых ресурсах? Cookie-сессия + HttpOnly/Secure/SameSite, CSRF-токен для небезопасных методов, строгая CSP по возможности.
  9. Можно ли хранить JWT в LocalStorage? Можно технически, но это делает токен доступным JS и уязвимым при XSS; предпочтительнее HttpOnly cookie или opaque token с серверной проверкой.
  10. Нужны ли подписи/шифрование в JWT? Подпись - да (JWS) для целостности. Шифрование (JWE) - только если действительно нужно скрывать содержимое и вы готовы к усложнению.

Чек-лист безопасной авторизации

  • Для cookie включены HttpOnly, Secure, корректный SameSite, минимальный Path/Domain.
  • Определён механизм отзыва (сессии/blacklist/короткий TTL + refresh).
  • CSRF закрыт там, где cookie отправляются автоматически.
  • XSS-риски снижены (экранирование, CSP, запрет inline где возможно).

Хранение и кеширование: LocalStorage, IndexedDB, HTTP-кеш и CDN

Хранение в браузере решает офлайн/ускорение/снижение нагрузки на сеть, но требует дисциплины: что именно кешировать, как инвалидировать и что делать при рассинхронизации. Начинайте с HTTP-кеша и правильных заголовков, а более сложные слои добавляйте по необходимости.

Типичные сценарии применения (21-30)

  1. Где уместен LocalStorage? Для несекретных небольших настроек (тема, флаги UI), где не критична транзакционность.
  2. Где лучше IndexedDB? Для структурированных данных, офлайн-очередей, кеша API-ответов, когда нужен объём и запросы по ключам.
  3. Что кешировать через HTTP-заголовки? Статику (JS/CSS/изображения) и ответы, которые можно валидировать ETag/Last-Modified.
  4. Как быстро снизить трафик без сложного фронта? Включить CDN для статики и выставить долгий кеш для файлов с хешами в имени.
  5. Как отличить memory cache / disk cache / CDN? В DevTools видно, откуда пришёл ресурс; CDN - по заголовкам/домену, браузерный кеш - по статусу/пометкам о кешировании.
  6. Что делать при ограниченных ресурсах команды? Не писать Service Worker "ради галочки"; сначала настроить Cache-Control, хеширование ассетов и CDN.
  7. Можно ли кешировать API-ответы? Да, если данные публичные или корректно разделены по пользователям; используйте Vary, учитывайте авторизацию и приватность.
  8. Как инвалидировать кеш правильно? Для статики - контент-хеш в имени файла; для данных - ETag/версионирование/TTL.
  9. Что хранить нельзя/опасно? Секреты (токены, пароли), персональные данные без необходимости, всё, что критично при XSS/компрометации устройства.
  10. Как понять, что кеш "сломался"? Симптомы: пользователи видят старый UI, 404 на ассеты, несовместимость API/фронта после релиза; лечится стратегией версионирования и хешами.

Чек-лист кеширования без лишней сложности

  • Статика отдаётся с долгим Cache-Control и именами файлов с хешем.
  • API-ответы помечены как private/public осознанно; нет утечек через общий кеш.
  • Включена валидация (ETag/Last-Modified) там, где это уместно.
  • Отдельно продуманы "обновления" клиента (версия приложения, миграции IndexedDB).

API и интеграции: REST vs GraphQL, обработка ошибок и версионирование

API-дизайн - это предсказуемость для клиента и управляемость для команды. Выбор REST или GraphQL влияет на кэш, дебаг и контракт. Для ограниченных ресурсов часто выигрывает простой REST с аккуратными ошибками и версионированием.

Плюсы, когда подход обычно выигрывает

  • REST: проще проксировать и кэшировать на уровне HTTP/CDN; проще логировать; проще поддерживать без специализированного гейтвея.
  • GraphQL: удобен при разнообразных клиентах и сложных графах данных, когда важно уменьшать overfetch/underfetch (но цена - сложнее сервер, кеш и безопасность запросов).
  • Webhook: полезен для интеграций "событиями", снижает опрос; требует ретраев, подписи и идемпотентности.
  • BFF (Backend For Frontend): часто самый прагматичный способ скрыть микросервисы и CORS, особенно если команда небольшая.

Ограничения и типовые ловушки

  • REST: без дисциплины легко получить "RPC в REST-обёртке" и хаотичные эндпоинты; решается единым стилем ресурсов и кодов ошибок.
  • GraphQL: риск дорогих запросов, N+1, необходимость лимитов сложности/глубины, сложнее кэш "из коробки".
  • Ошибки: смешивание 200 + ошибка в теле ломает инструменты и ретраи; лучше согласовать статус-коды и формат тела.
  • Версионирование: ломающее изменение без версии ведёт к авариям; при малых ресурсах проще всего версионировать путь (/v1) и держать короткий период совместимости.

Практические вопросы (31-40): короткие ответы

  1. REST или GraphQL для небольшого продукта? Часто REST: дешевле в поддержке, проще кешировать, проще дебажить. GraphQL берите, когда реально болит агрегирование и вариативность запросов клиентов.
  2. Как оформлять ошибки? Единый формат: код/сообщение/детали, плюс корректный HTTP-статус (4xx/5xx). Сообщения для пользователя отделяйте от технических.
  3. Какие статусы важнее всего согласовать? 200/201/204, 400, 401, 403, 404, 409, 422 (если используете), 429, 500.
  4. Как делать идемпотентность? Для операций создания - ключ идемпотентности (заголовок/поле) и хранение результата на сервере.
  5. Как версионировать API без боли? Не ломать контракт; при необходимости - /v2 и параллельная поддержка. Для малой команды лучше реже и крупнее версии.
  6. Как бороться с N+1? Батчинг/даталоадеры, правильные JOIN/агрегации, кеширование на уровне резолверов.
  7. Альтернатива GraphQL при ограниченных ресурсах? REST + эндпоинты-агрегаторы (BFF), или параметризованные include/expand, чтобы уменьшать число запросов.
  8. Что логировать на интеграциях? Корреляционный ID, статус, время, ретраи, внешний request-id, но без утечки секретов/PII.
  9. Как тестировать контракт? Контрактные тесты, схемы (OpenAPI), мок-сервер для клиента.
  10. Где уместны ретраи? На сетевых/временных сбоях и 429/503 с backoff; не ретраить 4xx (кроме случаев с обновлением токена).

Чек-лист надёжного API "без лишнего"

  • Единый формат ошибок и понятные статусы.
  • Версионирование и политика совместимости описаны и соблюдаются.
  • Идемпотентность для критичных операций (платежи/создание заказов).
  • Ограничения (rate limit) и наблюдаемость (корреляционные ID) включены.

Производительность фронтенда: загрузка ресурсов, рендеринг и оптимизация времени первой отрисовки

Оптимизация фронтенда - это управление критическим путём: что блокирует рендер, что занимает main thread, и что можно отложить. Часто лучший результат дают не сложные техники, а дисциплина сборки, корректные приоритеты загрузки и снижение объёма JS.

Типичные ошибки и мифы (41-47)

  1. Миф: "нужен SSR всегда". SSR помогает TTFB/первой отрисовке и SEO, но усложняет инфраструктуру. Для ограниченных ресурсов иногда достаточно пререндеринга статических страниц.
  2. Ошибка: один огромный bundle. Решение: code splitting по маршрутам/фичам и загрузка по требованию.
  3. Ошибка: блокирующие CSS/JS без приоритетов. Решение: минимальный критический CSS, defer/async где уместно, предзагрузка ключевых ресурсов.
  4. Миф: "картинки не важны, всё решит CDN". Без правильных форматов/размеров CDN не спасёт. Делайте responsive images и оптимизацию формата.
  5. Ошибка: слишком много runtime-полифилов. Решение: таргетировать браузеры, отдавать дифференцированные бандлы, не тянуть лишнее.
  6. Ошибка: тяжёлые вычисления на main thread. Решение: Web Worker/разбиение задач, виртуализация списков.
  7. Миф: "оптимизируем только Lighthouse". Нужны реальные метрики (RUM) и профилирование под вашу аудиторию и устройства.

Практические вопросы (48-50): короткие ответы

  1. Что оптимизировать в первую очередь? Объём JS и блокировки рендера: меньше кода, меньше синхронных зависимостей, меньше работы на main thread.
  2. Какая дешёвая альтернатива сложному SSR? SSG/пререндер (например, сборка статических страниц) + CDN: проще и часто достаточно.
  3. Как быстро найти "тормоз"? DevTools Performance + Coverage, смотреть долгие tasks и неиспользуемый JS/CSS, затем резать по маршрутам.

Чек-лист быстрого фронта для небольшой команды

  • Настроены code splitting и загрузка по требованию; нет "всего в одном бандле".
  • Критические ресурсы имеют приоритет, блокирующие скрипты минимизированы.
  • Изображения отдаются в подходящих размерах/форматах.
  • Есть базовые RUM-метрики и регулярное профилирование.

Инфраструктура и деплой: CI/CD, контейнеризация, логирование и мониторинг приложений

Инфраструктура должна уменьшать риск релиза и ускорять обратную связь. Для ограниченных ресурсов важнее воспроизводимость (одинаковая сборка), быстрый откат и минимальная наблюдаемость, чем "идеальная" платформа. Начните с простого пайплайна, контейнера и стандартных логов.

Мини-кейс: деплой с минимальными затратами

Сценарий: один фронтенд и один API. Цель - каждый merge в main собирает образ, прогоняет тесты и выкатывает на сервер; откат - смена тега образа.

# Псевдопайплайн (смысл, не привязка к конкретному CI)
steps:
  - checkout
  - install && test
  - build
  - docker build -t registry/app:${GIT_SHA} .
  - docker push registry/app:${GIT_SHA}
  - ssh deploy@server "docker pull registry/app:${GIT_SHA} && docker compose up -d"

# Минимум для логов/трейсинга
# - писать логи в stdout/stderr (JSON по возможности)
# - прокидывать X-Request-Id и логировать его на всех сервисах

Практические вопросы: что сделать "сегодня"

  1. Нужны ли контейнеры? Почти всегда да: Docker упрощает воспроизводимость. Если ресурсов мало - начните хотя бы с одного Dockerfile.
  2. Что важнее: CD или CI? CI (тесты/сборка) обязателен; CD можно начать с полуавтомата (ручное подтверждение на прод).
  3. Что логировать в первую очередь? Ошибки, латентность, идентификатор запроса, пользователя (если допустимо), версию приложения, внешние вызовы.
  4. Дешёвая альтернатива сложному мониторингу? Централизованные логи + несколько ключевых метрик (ошибки, время ответа) + алерты по порогам.
  5. Как пережить "плохой релиз" с малыми ресурсами? Canary/blue-green - хорошо, но минимум: быстрый откат на предыдущий образ/артефакт и миграции БД с обратимостью.

Чек-лист самопроверки по всей странице (быстрый)

  • Понимаете, почему CORS проявляется только в браузере и как читать preflight в Network.
  • Для авторизации выбран один основной сценарий (cookie-сессия или токены) и определён отзыв/ротация.
  • Кеширование начинается с HTTP/CDN и хеширования ассетов, а не с преждевременного Service Worker.
  • Контракт API стабилен: ошибки, версии, идемпотентность и лимиты согласованы.
  • Деплой воспроизводим, есть быстрый откат и минимальная наблюдаемость.

Разъяснения по 50 распространённым техническим вопросам

Почему CORS "ломается", хотя сервер отвечает 200?

Браузер может заблокировать доступ к ответу, если нет нужных Access-Control-* заголовков или не пройден preflight. В Network часто видно 200, но JS не получает данные.

Как понять, что проблема в SameSite у cookie?

Если кросс-сайтовый запрос перестал быть авторизованным, проверьте атрибут SameSite и режим запроса (credentials). Часто причина - смена схемы/домена или переход на встраивание в iframe.

Что выбрать для хранения токена, если боюсь XSS?

Обычно безопаснее HttpOnly cookie, потому что JS не читает её напрямую. При этом всё равно нужно снижать XSS-риски и продумать CSRF.

Почему REST "легче кешировать", чем GraphQL?

REST-ресурсы естественно мапятся на URL, и стандартный HTTP-кеш/CDN работает предсказуемо. В GraphQL часто всё идёт через один endpoint, и кэширование требует дополнительных слоёв/ключей.

Как отвечать на ошибки в API, чтобы клиент не гадал?

Топ-50 вопросов для FAQ веб-разработчика: от

Возвращайте корректный HTTP-статус и стабильный формат тела ошибки (код, сообщение, детали). Не прячьте ошибки под 200, иначе ломаются ретраи и аналитика.

Какие "вопросы по JavaScript для собеседования" чаще всего упираются в браузерные механики?

Топ-50 вопросов для FAQ веб-разработчика: от

Про event loop, микротаски/макротаски, замыкания и область видимости, прототипы, а также взаимодействие JS с сетью (fetch, CORS) и хранением (cookie, storage). Это часто проверяют через практические кейсы.

Прокрутить вверх