Хранилища браузера
Вы открываете ту же страницу, но тема уже выбрана иначе, чем у коллеги. На сервере исходники совпадают, а результат отличается. Причина может находиться в состоянии браузера: сохранённой настройке, cookie или кеше. Важно определить конкретный механизм, а не сразу удалять все данные всех сайтов.
В lesson-21 архива используется прежняя отдельная лаборатория на http://127.0.0.1:4310/. Она не содержит аккаунтов и секретов. Сервер, хранилища и команды консоли не запускались; перечисленные результаты являются ожидаемыми для будущего ручного упражнения.
Настройка принадлежит origin
После успешной загрузки выбранной темы приложение пытается сохранить catalog-topic в localStorage. При следующем открытии читает значение и принимает его только из набора all, frontend, publishing. Если значение отсутствует или неизвестно, исходная тема остаётся all.
const saved = localStorage.getItem("catalog-topic");
if (allowedTopics.has(saved)) select.value = saved;
Это чтение меняет выбранный пункт, но не загружает API автоматически. Начальные две карточки по-прежнему приходят в HTML. Поэтому после открытия с сохранённым publishing вы сначала увидите выбранную тему «Публикация» и старый начальный список; пустой список появится только после нажатия загрузки.
Такое поведение задано намеренно и помогает разделить состояние формы и состояние данных. Если требуется автоматическая загрузка сохранённой темы, это отдельное изменение приложения. Нельзя считать два начальных курса признаком того, что сохранение вообще не сработало, не прочитав выбранное значение.
Откройте Application и localStorage нужного origin. Найдите ключ и его значение. Инструкция Chrome по localStorage описывает просмотр и изменение записей. В нашем примере удаляется только учебный catalog-topic, чтобы вернуть исходную тему при следующем открытии.
Cookie с отдельным назначением
При GET главной страницы сервер устанавливает lab_view=cards с Path=/ и SameSite=Lax. Это несекретный учебный маркер, не идентификатор сессии и не авторизация. Он нужен лишь для сравнения механизмов; приложение не выбирает по нему тему и не проверяет доступ к API.
В Application прочитайте Cookies для лаборатории и сравните имя, путь и значение. Руководство Chrome по cookie показывает соответствующие поля. Для нашего HTTP-примера нет Secure и HttpOnly; это не образец настройки производственной авторизации.
Cookie относится к правилам домена и пути и может участвовать в HTTP-запросах. LocalStorage читается кодом страницы и не добавляется автоматически в заголовок Cookie. Поэтому сохранённый catalog-topic=frontend не появляется сам собой в запросе сервера: приложение отдельно строит параметр topic из формы.
Если удалить lab_view и обновить главную страницу, сервер установит его снова. Это ожидаемое следствие нашего обработчика, а не признак того, что кнопка удаления в панели не работает. При чтении состояния важно учитывать не только момент удаления, но и последующее действие, которое может восстановить данные.
Cache Storage отдельно от HTTP-кеша
В учебном приложении нет Service Worker и код не читает Cache Storage. Тем не менее для сравнения можно вручную создать одну демонстрационную запись через консоль лаборатории:
const cache = await caches.open("catalog-lab-demo");
await cache.put("/demo-marker.txt", new Response("учебный маркер"));
После этого в Application должна появиться именованная запись Cache Storage. Она не начинает автоматически подменять сетевой ответ /api/courses. Для такого поведения приложению нужен код, который действительно читает кеш и использует сохранённый ответ. Документация Chrome Cache Storage описывает просмотр этого хранилища.
В отличие от него обычный HTTP-кеш браузера может учитывать заголовок Cache-Control CSS. Наш сервер разрешает кешировать theme.css на 120 секунд. Наличие именованного catalog-lab-demo и возможное чтение CSS из HTTP-кеша относятся к разным механизмам. Удаление одного не обязательно меняет состояние другого.
Для уборки демонстрации используется точное имя:
await caches.delete("catalog-lab-demo");
localStorage.removeItem("catalog-topic");
Это команды будущего ручного упражнения только в отдельной лаборатории. Они не очищают произвольные данные других сайтов. После удаления темы следующий старт вновь выберет all; после удаления именованного кеша его учебная запись исчезнет. Cookie имеет отдельное управление и при чтении главной страницы создаётся снова.
Для минимального сброса сначала определите, какое наблюдение меняется. Если интересует выбранная тема, удаляется только catalog-topic, а не весь профиль. Если интересует учебная запись Cache Storage, удаляется только catalog-lab-demo. Если нужно увидеть повторное получение CSS, используются отдельные сетевые условия. Это три разных эксперимента. Выполнение всех очисток сразу могло бы скрыть причину: результат изменился, но осталось непонятно, какое состояние влияло на него. В нашем каталоге настройка формы и кеш оформления независимы. Такое разделение полезно и при передаче ошибки коллеге: сначала воспроизведите один известный фактор, затем добавляйте следующий. Не нужно требовать от другого автора уничтожить настройки всех сайтов, чтобы исследовать несекретное значение одной учебной формы. Точный набор условий делает сравнение обозримым и сохраняет остальные рабочие данные.
Состояние и воспроизводимость
При передаче ошибки коллеге укажите точный origin. http://127.0.0.1:4310 и http://localhost:4310 не являются одним origin для localStorage. Разный порт также меняет его. Cookie имеет другую область: порт не является самостоятельной границей cookie. Поэтому удобнее использовать выделенный учебный профиль и один неизменный адрес.
Перед наблюдением запишите состояние catalog-topic, наличие cookie и состояние настроек Network. Это позволит понять, почему два одинаковых исходника дали разные первые экраны. Не нужно экспортировать целиком содержимое профиля: для заданной формы достаточно одного ключа и описания действий.
Есть и случай недоступного localStorage. Приложение оборачивает чтение и запись в обработку исключения. При недоступности настройки оно сохраняет исходную тему и может показать пояснение. Такой отказ не должен мешать самому чтению каталога. Состояние браузера считается удобством интерфейса, а не единственным источником бизнес-данных.
Не храните в localStorage секрет только потому, что панель Application удобно его показывает. Наш ключ содержит название темы, которое уже публично присутствует в форме. Для авторизации нужны другой договор и отдельные меры; этот урок не предлагает переносить учебный маркер в сессионную схему.
Конечный результат — понимание трёх разных механизмов и минимального способа вернуть исходные условия конкретной страницы. Файлы приложения в этом уроке не меняются. В следующем уроке сохраним минимальные условия запроса с ошибкой параметра и отделим их от лишнего состояния браузера.