Есть несколько вещей, которые нужно учитывать, и множество способов подойти к этому. Во-первых, спецификация
Чего мы пытаемся достичь?
В идеале, модифицированный ресурс будет безоговорочно выбираться при первом запросе, а затем извлекаться из локального кэша до истечения срока его действия без последующего взаимодействия с сервером.
Наблюдаемое поведение кэширования
Отслеживание различных перестановок может быть немного запутанным, поэтому я создал следующую таблицу. Эти наблюдения были получены путем выполнения запросов от Chrome к IIS и наблюдения за реакцией / поведением в консоли разработчика.
Во всех случаях новый URL приводит к HTTP 200. Важно то, что происходит с последующими запросами.
+---------------------+--------------------+-------------------------+
| Type | Cache Headers | Observed Result |
+---------------------+--------------------+-------------------------+
| Static filename | Expiration +1 Year | Taken from cache |
| Static filename | Expire immediately | Never caches |
| Static filename | None | HTTP 304 (not modified) |
| | | |
| Static query string | Expiration +1 Year | HTTP 304 (not modified) |
| Static query string | Expire immediately | HTTP 304 (not modified) |
| Static query string | None | HTTP 304 (not modified) |
| | | |
| Random query string | Expiration +1 Year | Never caches |
| Random query string | Expire immediately | Never caches |
| Random query string | None | Never caches |
+---------------------+--------------------+-------------------------+
Однако , помните, что браузеры и веб-серверы не всегда ведут себя так, как мы ожидаем. Известный пример: в 2012 году мобильный Safari начал кэшировать POST-запросы . Разработчики не были довольны.
Строка запроса
Примеры в синтаксисе ASP.Net MVC Razor, но применимы практически к любому языку обработки сервера.
... так как некоторые приложения традиционно используют GET и HEAD с
URL запросов (те, которые содержат «?» в части rel_path) для выполнения
операции со значительными побочными эффектами, кеши НЕ ДОЛЖНЫ лечить
ответы на такие URI как свежие, если сервер не предоставит явный
Время истечения. Это конкретно означает, что ответы от HTTP / 1.0
серверы для таких URI НЕ ДОЛЖНЫ быть взяты из кэша.
Добавление случайного параметра в конец CSS-URL, включенного в ваш HTML, заставит новый запрос, и сервер должен ответить HTTP 200 (не 304, даже если это не было
модифицированный).
<link href="normalfile.css?random=@Environment.TickCount" />
Конечно, если мы рандомизируем строку запроса с каждым запросом, это полностью победит кэширование. Это редко / никогда не желательно для производственного применения.
Если вы поддерживаете только несколько URL-адресов, вы можете вручную изменить их, чтобы они содержали номер сборки или дату:
@{
var assembly = Assembly.GetEntryAssembly();
var name = assembly.GetName();
var version = name.Version;
}
<link href="normalfile.css?build=@version.MinorRevision" />
Это вызовет новый запрос в первый раз, когда пользовательский агент встретит URL, но последующие запросы в основном будут возвращать 304. Это по-прежнему вызывает запрос, но, по крайней мере, весь файл не обслуживается.
Модификация пути
Лучшее решение - создать новый путь. С небольшими усилиями этот процесс можно автоматизировать, чтобы переписать путь с номером версии (или каким-либо другим непротиворечивым идентификатором).
В этом ответе показано несколько простых и элегантных опций для платформ, не принадлежащих Microsoft.
Разработчики Microsoft могут использовать модуль HTTP, который перехватывает все запросы для данного типа файлов, или, возможно, использовать комбинацию маршрута / контроллера MVC для предоставления правильного файла (я не видел, чтобы это было сделано, но я считаю, это возможно).
Конечно, самый простой (не обязательно самый быстрый или лучший) метод - просто переименовывать файлы в каждом выпуске и ссылаться на обновленные пути в тегах link
.
TLDR
- Изменить имя файла или строку запроса
- Использовать изменения, которые происходят только один раз в каждом выпуске
- Переименование файла предпочтительнее, чем изменение строки запроса
- Всегда устанавливайте HTTP-заголовки, чтобы максимизировать преимущества кэширования