П’ять сценаріїв, яких аудит не перевіряв
Аудит PWA 26 вересня позначив п’ять сценаріїв як неперевірені. Тепер кожен має тест. Два знайшли справжні вади: 501-ша зірочка мовчки знімала першу, а сторінка першого візиту офлайн не відкривалася. Третій виявив вибір, і «6 в 1» його зробив: якщо мережа зависла, а копія є, через 10 секунд читач бачить копію.
Що лишив аудит
Звіт аудиту PWA від 26 вересня, крім вад R1–R5, мав і список того, чого не перевіряв зовсім. П’ять пунктів із нього можна закрити без людини, автоматичними тестами. «6 в 1» зібрав їх в ішью #31 і поставив першим кроком плану відкриття сайту для пошуковиків: перед тим як сайт почнуть знаходити, офлайн має поводитися так, як обіцяє сторінка «Про атлас».
Правило було те саме, що й для R1: спершу тест за контрактом, і лише якщо він падає на поточному коді, виправлення. З п’яти тестів два впали на справжніх вадах, один виявив вибір поведінки, два пройшли одразу.
Заголовки на проді
Живий запит до https://www.aitimeline.dev 27 вересня. Файли /_astro/ приходять із public, max-age=31536000, immutable і правильним типом (application/javascript, text/css). Кадри /media/ — з max-age=604800 і image/jpeg. Обидва класи несуть усі заголовки безпеки: CSP, nosniff, Referrer-Policy, COOP, Permissions-Policy і HSTS. Тест правил vercel.json тепер перевіряє кожен клас файлів тим самим зіставленням, яким відповідає локальний Preview, тож правило, що зникло або почало ловити зайве, зупинить збірку.
Одну річ живий запит показав поза контрактом. Відповідь 404 під /_astro/ теж отримує immutable на рік. Vercel не вміє обмежити правило статусом відповіді. Ризик вузький: браузер, що колись побачив файл відсутнім, не повірить, якщо пізніша збірка поверне файл із тим самим іменем. Я записав це як залишковий ризик і нічого не змінював.
Межі кешу
Нещодавно відкритих сторінок воркер тримає 60. Тест заповнює кеш до межі прямо зі сторінки, а не відкриває 60 сторінок. Перевідкрита сторінка стає найновішою, наступна витісняє найстарішу, а відкритий онлайн відкладений запис оновлює свою копію й до шістдесяти не лічиться. Усе це працювало й до тесту.
Зірочок натомість не вистачало. Межа була 500, і коментар біля неї обіцяв, що вона «далеко вище за розмір колекції». Колекція тим часом виросла до 885 записів. Читач, що відклав би 501-й, мовчки втратив би перший разом з його офлайн-копією. Тепер межа 10 000, і тест тримає її щонайменше вдвічі вищою за кількість опублікованих записів, тож наступного разу її піднімуть задовго до того, як хтось до неї дійде.
Аварійний вимикач
Досі тест вимикача підміняв лише dist/sw.js, в одній вкладці. Тепер тест сам збирає весь сайт із вимкненим воркером у тимчасову теку. Прапорець перемикає Vite-плагін, а файл switch.ts лишається як був, тож перерваний прогін нічого не зламає. Далі тест подає на тому самому origin спершу звичайну збірку, потім вимкнену, двом відкритим вкладкам. Обидві звільняються, кеші atlas-* зникають, реєстрацій нуль. Після перевідкриття сторінки воркера не реєструють, а вісь читається з мережі. Відкладені зірочки в localStorage лишаються, бо це не кеш.
Перехопити запит через Playwright тут не вийшло: браузер перевіряє оновлення /sw.js повз перехоплення. Тому тест піднімає власний сервер і на тому самому порту міняє одну збірку на іншу, як це робить розгортання. dist/ він не змінює, і чат, що паралельно перезбирає сайт, його не зламає. Вимикач пройшов одразу.
Перший візит одразу на запис
Аудит перевіряв офлайн лише після старту з осі. Тест приходить першим візитом просто на сторінку запису, чекає воркера й вимикає мережу. На старому коді вісь офлайн відкривалася, а сам запис показував «Ця сторінка недоступна офлайн». Сторінка «Про атлас» обіцяє інше: без мережі відкриваються сторінки, які ви нещодавно відкривали. Це вада. Сторінка першого візиту завантажується раніше, ніж з’являється воркер, тож він її просто не бачив.
Тепер така сторінка сама називає воркеру свою адресу в тому ж повідомленні, де передає мову й відкладені записи. Воркер зберігає її разом з її файлами. Файли тест спершу пропускав: їх віддавав HTTP-кеш браузера, який може звільнитися будь-коли. Тож тест чистить HTTP-кеш перед офлайном, і тоді два скрипти сторінки впали. Воркер тепер зберігає й їх.
Мережа, що зависає
Тест тримає запит воркера без відповіді, не обриваючи його. На старому коді сторінка чекала понад 150 секунд, хоча датована копія лежала в кеші. Картка осі чекала 20 секунд, повторювала запит ще на 20 і лише потім казала, що текст не завантажився. Копії читач не бачив.
Скільки чекати — це вибір, а не вада, тож я спитав. «6 в 1» вибрав так: якщо за 10 секунд мережа не відповіла, а копія є, воркер віддає копію. На сторінці з’являється рядок «Мережа не відповідає: це копія, збережена …», а не «Ви офлайн», бо читач може бути в мережі. Картка осі показує свій наявний рядок про копію тексту. Запит не скасовується: відповідь, що прийде пізніше, замінить копію для наступного відкриття. Якщо копії немає, воркер чекає мережу, скільки знадобиться, і заглушку не показує. 10 секунд менше за 20, які вісь чекає сама, тож картка встигає заповнитися з копії.
Що не перевірено
Усе перевірено в Chromium через Playwright: pwa.spec.ts тричі поспіль і verify:code. Хвилини GitHub Actions вичерпано до 1 жовтня, тож CI цей прохід не бачив. Не перевірено справжній Android та iOS, Safari й Firefox. Випадок «мережа зависла, а копії немає» перевірено лише за кодом: тест мусив би чекати фіксовані 10 секунд, а таких очікувань у тестах PWA немає за правилом.
Запис зроблено 27 вересня 2026 р.
Коміти, про які цей запис
a63850f