Блог

Статические сайты теперь работают во время повторной публикации

Повторная публикация статического сайта в Mythex раньше сначала удаляла живые файлы, а потом загружала новую сборку. Поэтому на время загрузки часть посетителей получала страницу 404 или страницу, у которой не загружались скрипты. Неудачная загрузка могла оставить сайт пустым или наполовину новым. Теперь новая сборка записывается поверх старой, страницы — последними, а ненужные файлы удаляются через несколько минут. Второе исправление делает так, что повторная публикация появляется за секунды, а не за минуту, или, для файлов вроде логотипа, через сутки.

Как отдаётся статический сайт

Статический сайт — это набор файлов: HTML-страницы, JavaScript, CSS, изображения. Когда вы публикуете его в Mythex, мы собираем его, загружаем результат в объектное хранилище в папку вашего сайта и отдаём через edge-сеть — серверы рядом с посетителями, которые берут файлы из хранилища и некоторое время хранят их копии. (Если вы только знакомитесь с этим, наше руководство что такое CDN объясняет идею.)

Неправильно было две вещи: порядок, в котором повторная публикация меняла файлы, и то, как долго хранились старые копии.

Проблема 1: загрузка сначала очищала сайт

Повторная публикация удаляла всё в папке сайта, а потом загружала новую сборку. Всё время загрузки — 12 секунд для сайта из 250 файлов в нашем локальном тесте — посетитель, чей запрос не был уже закэширован на edge, получал 404 или HTML-страницу, скрипты которой возвращали 404.

Неудачная загрузка была хуже. Папка уже была пустой, а на одном из двух путей загрузки новый index.html мог появиться раньше файла, который не загрузился. Публикация, сообщённая как неудачная, могла оставить живым наполовину новый сайт.

Исправление: запись поверх, страницы последними, очистка позже

  1. Не удаляйте сначала. Новая сборка загружается поверх старой.
  2. Ресурсы раньше страниц. Страница называет скрипты и стили, которые ей нужны, поэтому страницы загружаются последними. Пока новые страницы не появились, посетители получают старую страницу, которая называет старые ресурсы, а они ещё на месте. Когда страницы появляются, новые ресурсы, которые они называют, уже на месте.
  3. Удаляйте лишнее позже. Перед загрузкой мы составляем список того, из чего состоит сайт. Через три минуты после успешной загрузки всё из этого списка, что новая сборка не перезаписала, удаляется. Три минуты дольше, чем 60 секунд, которые страница может храниться в кэше edge и в браузере, поэтому посетитель, который ещё держит старую страницу, сможет найти ресурсы, которые она называет.
  4. При сомнении ничего не удаляйте. Если список до загрузки не удалось получить, очистки не будет. Лишние файлы безвредны, и следующая публикация их уберёт. Удалять, не зная, что там было, — именно так сайт и остаётся пустым.

Неудачная загрузка теперь оставляет предыдущий сайт в точности таким, каким он был.

Мы проверили это сквозным тестом локально, используя настоящий скрипт загрузки, настоящий маршрут загрузки и отдачу из хранилища, а посетители приходили с холодным кэшем edge. На старом коде 55 из 91 визитов были сломаны во время повторной публикации, а 61 из 92 — во время неудачной. На новом коде сломано было 0 из примерно 3 500 визитов, охватывающих оба пути загрузки, неудачную загрузку и последующую публикацию, а удалялись ровно лишние файлы.

Проблема 2: повторная публикация слишком долго проявлялась

Даже когда загрузка проходила нормально, изменения появлялись медленно. Edge хранил копию страницы 60 секунд, а всех остальных файлов — сутки, и велел браузерам делать то же самое. Файлы с фиксированным именем — logo.png, шрифт, всё из папки public/ — могли показывать старую версию до суток после повторной публикации.

Исправление: копии файлов привязаны к сборке

Когда edge спрашивает наш API, где находится сайт, ответ теперь содержит маркер сборки, который меняется каждый раз, когда публикация проходит. Edge сохраняет свои копии под этим маркером. Поэтому публикация становится совершенно новым набором ключей кэша, как только истекает 30-секундный поиск на edge. Старые копии просто больше не находятся, и edge может хранить копии сутки, никогда не отдавая устаревшую версию после публикации, которая её заменила.

Для браузеров действуют два разных правила:

  • Хешированный результат сборки — файлы вроде assets/index-CzLcxDO8.js, имя которых меняется вместе с содержимым, — кэшируется на год и помечается как immutable. Под этим именем он не может устареть.
  • Всё остальное — страницы и файлы с фиксированным именем, например логотип, — помечается как no-cache, то есть «проверь перед использованием». Если ничего не изменилось, ответом будет крошечный 304 Not Modified без тела, поскольку теперь мы учитываем проверку If-None-Match браузера.

Различать их нужно аккуратно: файл, скопированный из public/assets/, сохраняет своё имя, а кэширование assets/logo.png на год закрепило бы старый логотип на год. Поэтому файл считается хешированным, только если он лежит в папке результатов сборки и в его имени есть сегмент, похожий на хеш, а не обычное слово.

Локально новая страница и логотип стали видны через 6 секунд после выхода публикации. Раньше на страницу уходило 60 секунд, а на логотип — сутки.

Два менее значимых исправления

  • Пустые страницы из HEAD-запросов. Запрос HEAD запрашивает заголовки страницы без тела. Мы кэшировали эти пустые ответы, и следующий посетитель той страницы получал пустую страницу. Ответы на HEAD больше не кэшируются.
  • Настоящая страница для «здесь ничего нет». Адрес без приложения раньше возвращал простой текст «This published app is offline or the link was not found» с кодом ошибки 502. Теперь он получает нормальную страницу «Здесь нет приложения» со статусом 404 и ссылкой обратно в Mythex для владельца. Неизвестные собственные домены получают ту же страницу.

Что мы из этого вынесли

  • Порядок — часть корректности. Одни и те же файлы, загруженные в другом порядке, — это разница между сломанным и работающим сайтом.
  • Удаляйте поздно и только то, что знаете. Очистка по списку, снятому до загрузки, безопасна; опустошать папку и надеяться, что загрузка успеет, — нет.
  • Кэшируйте по версии, а не по времени. Время истечения — это догадка о том, когда меняется содержимое. Ключ, который меняется вместе со сборкой, — это факт.

Смежное: ваше опубликованное приложение теперь остаётся работающим во время повторной публикации. Больше о публикации — в документации.

Mythex · Pricing · Создавайте что угодно с ИИ · Шаблоны сайтов и приложений · Сравнения Mythex · Глоссарий по созданию приложений с ИИ · Бесплатные инструменты для создания приложений с ИИ · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)