Добро пожаловать в первую из серии статей об общих знаниях о масштабном запуске одностраничного приложения в производственной среде!

В этом выпуске мы обсуждаем лучшие практики кэширования ресурсов в одностраничном приложении - Angular / AngularJs / React / Vue или аналогичных - для достижения баланса между производительностью, гибкостью и защитой от удара в ногу.

Сначала предположим, что ваше приложение имеет процесс сборки (веб-пакет или другой) для создания типичных ресурсов *.js, *.css, *.html.

Как только процесс сборки будет завершен, вы получите 2 класса ресурсов:

  • «Неизменяемые ресурсы» с именем файла, уникальным для этой сборки, например main.8d7a94ef1418343a7897.js,
  • «Mutable Resources» с постоянным именем файла во всех сборках, например index.html

TL; DR;

  • Для неизменяемых ресурсов убедитесь, что ваш сервер отвечает следующими заголовками HTTP:

Cache-Control: public, max-age=31536000

  • Это инструктирует браузеры (и все прокси-серверы, которые играли роль в доставке этого контента в браузер) использовать кэшированную копию, где это возможно, в течение следующего 1 года. Это идеально, так как имя этого файла было сгенерировано с хешем содержимого файла, и мы знаем, что имя файла для этой копии файла никогда не изменится.

  • Для изменяемых ресурсов убедитесь, что ваш сервер отвечает следующими заголовками HTTP:
Cache-Control: max-age=30
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
  • Обеспечивая возврат ETag, это означает, что браузер может выдавать условный GET запрос в последующих запросах на получение новой копии файла, только если файл был обновлен на вашем сервере.
  • Обратите внимание, что мы также указываем браузеру кэшировать на 30 секунд. В случае, если мы введем ошибку, из-за которой страница постоянно обновляется, мы избегаем перегружать наши серверы тоннами запросов.

Детали

А как насчет использования Cache-Control : immutable?

Это новое значение расширения управления кешем может показаться соблазнительным, но предпочтительнее использовать более традиционные значения для достижения более ожидаемого поведения в браузерах. Некоторые браузеры либо не понимают, либо игнорируют директиву immutable - https://stackoverflow.com/questions/41936772/which-browsers-support-cache-control-immutable - https://stackoverflow.com/questions / 52762478 / причина-почему-google-chrome-ignoring-cache-control-header

Почему бы не использовать Cache-Control: no-store, must-revalidate?

Использование no-store, must-revalidate может быть полезно в сценариях, когда мы хотим строго не кэшировать какой-либо контент, особенно конфиденциальный.

Однако, поскольку наше приложение представляет собой SPA, состоящий из ресурсов *.js, *.css, *.html, которые по определению не могут быть чувствительными, мы предпочитаем, чтобы кеш браузера, где это возможно, оптимизировался для более быстрой загрузки

Почему Cache-Control: max-age=30?

На случай, если мы случайно введем ошибку, которая приведет к постоянному обновлению нашего приложения, мы защищаем наши серверы от перегрузки, сообщая браузеру о необходимости кэширования ресурсов на срок до 30 секунд.

После нескольких циклов обновления большинство браузеров должны обнаружить неисправность и предотвратить бесконечное продолжение цикла.

Примечание. Мнения принадлежат мне и не отражают точку зрения или положение моего работодателя.