Принудительное обновление кэшированных данных CSS - PullRequest
37 голосов
/ 06 октября 2010

Можно ли заставить браузер обновить кэшированный CSS?

Это не так просто, как каждый запрос. У нас есть сайт, на котором уже давно есть стабильный CSS.

Теперь нам нужно сделать несколько важных обновлений CSS; однако браузеры, которые кэшировали CSS, не получат новый CSS в течение нескольких дней, что вызывает проблемы с отображением.

Есть ли способ принудительного обновления CSS или нам лучше выбрать CSS-адреса для конкретных версий?

Ответы [ 4 ]

53 голосов
/ 06 октября 2010

Есть несколько вещей, которые нужно учитывать, и множество способов подойти к этому. Во-первых, спецификация

Чего мы пытаемся достичь?

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

Наблюдаемое поведение кэширования

Отслеживание различных перестановок может быть немного запутанным, поэтому я создал следующую таблицу. Эти наблюдения были получены путем выполнения запросов от 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-заголовки, чтобы максимизировать преимущества кэширования
7 голосов
/ 19 октября 2012

Я думаю, что переименование файла CSS - гораздо лучшая идея.Это может не подходить для всех приложений, но гарантирует, что пользователь должен загрузить файл CSS только один раз.Добавление случайной строки в конец гарантирует, что они должны будут загружать ее каждый раз.То же самое касается метода javascript и методов apache, описанных выше.Иногда простой ответ может быть наиболее эффективным.

Другое решение:

<FilesMatch "\.(js|css)$">
    Header set Cache-Control "max-age=86400, public"
</FilesMatch>

Это ограничивает максимальный срок хранения кэша 1 днем ​​или 86400 секундами.

0 голосов
/ 21 марта 2019

Пожалуйста, сначала прочитайте ответ Тима Медоры, так как это действительно знающий и полезный пост.

Теперь я расскажу вам, как я это делаю в PHP. Я не хочу беспокоиться о традиционном управлении версиями или попытке поддерживать более 1000 страниц, но я хочу, чтобы пользователь всегда получал последнюю версию моего CSS и кэшировал ее.

Поэтому я использую технику строки запроса и PHP filemtime () , которая будет возвращать последнюю измененную метку времени.

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

В своих веб-приложениях я использую файл config.php для хранения своих настроек, поэтому здесь я сделаю переменную, подобную этой:

$siteCSS = "/css/standard.css?" .filemtime($_SERVER['DOCUMENT_ROOT']. "/css/standard.css");

и затем на всех своих страницах я буду ссылаться на свой CSS следующим образом:

<link rel="stylesheet" type="text/css" media="all" href="<?php echo $siteCSS?>" />

До сих пор это прекрасно работало для меня на PHP / IIS.

0 голосов
/ 06 октября 2010

Ю может сделать это в apache ...

<FilesMatch "\.(html|htm|js|css)$">
FileETag None
<IfModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</IfModule>
</FilesMatch>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...