Приятно иметь небольшой проект, на котором можно потренировать разные скиллы.
ТЛДР:
https://pickyouragent.dev - оптимизированная версия
https://pickyouragent-dev.pages.dev - неоптимизированная.
Желательно проверять в хромиуме.
Так же можете глянуть как работает
https://v1000.reatom.dev. Супер стейт менеджер, всем рекомендую, но документация не оптимизирована на кеши(это важно будет ниже).
В этот раз мне захотелось разобраться как сделать максимально эффективную работу с кешами в браузере, чтобы пользователь получал данные максимально быстро.
Дано: статический сайт. В идеале - всё должно кешироваться максимально. В идеале: браузер загрузил должен грузить каждый ресурс максимум 1 раз и больше на сервер не ходить.
Что же получилось:
Слой нулевой.
Сборка. Всё кроме .html переименовываем по шаблону
<name>_<hash>.js. Это позволит нам очень эффективно инвалидировать файлы. Если контент файла изменился, то мы просто ссылаемся на другой файл(потому что хеш нового контента будет другим), которого уже нет в кеше.
Слой первый.
CDN.
Тут всё просто:
- Говорим Clodflare(далее CF) что надо кешировать все файлы на 1 год на своём уровне(так называемый Edge level) и игнорировать GET параметры в урле(/a?a=1 и /a?b=2 считаются одним и тем же адресом). А так же генерировать для каждого файла свой Etag(об этом чуть позже).
В итоге первый запрос на CDN будет создавать кеш, а уже следующие запросы будут не ходить к вам на сервер, а браться напрямую с CDN. И это позволит человеку из Австралии тратить не 2 секунды на установку соединения, а за 200-500мс брать файл с ближайшего CDN
Слой второй.
Браузер. HTTP-кеш- Для всех файлов кроме .html ставим
max-age в 1 год. Этот заголовок говорит браузеру, что можно безопасно читать файл с дискового кеша вместо похода на сервер. А если страницы сайта реюзают разные файлы, то переходы по страницам будут куда быстрее.
Так же не забываем о значении
must-revalidate. Это позволит браузеру включать ранее полученный
ETag в запросы, а серверу смотреть поменялся ли
Etag и отвечать 200, если контента файла нет у клиента, или же 304, если контент уже есть.
Ещё небольшая экономия на пересылке контента.
- Кешировать .html на 1 год мы не можем, так как, вспоминаем шаг 0, имена .html в браузерном кеше всегда одинаковые. Но если мы хотим обновлять содержимое сайта, то надо заставить клиент перекачивать .html. Поэтому мы не можем ставить большой
max-ageИ тут возникает проблема: пользователь готов ждать первую загрузку и это незаметно для него. Но лаги во время переходов между страницами будут бесить.
Для сокращения лагов во время переходов придумали отдельный механизм: префетчинг. Но, увы, он не работает везде. В хромиумах лучше всего. В FF только если
max-age != 0. А в сафари вообще надо костылить через fetch. Больше инфы тут:
https://github.com/withastro/astro/issues/10464#issuecomment-2104238799Поэтому, для .html ставим
max-age=1. Если честно, то нет разницы какой мы ставим
max-age, потому что CF так же посылает заголовок
Age. Он означает сколько секунд файл валяется на конкретной ноде CDN. И,
max-age работает, учитывая
Age. Можете поразмыслить почему кеш или всегда будет протухшим, или же мешать нам запрашивать новые данные.