Заставить браузер перезагрузить css после его обновления

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

После поиска по многим постам и объединения разных идей я пришел к тому, что кажется самым простым и дешевым подходом.

Если какой-либо файл CSS связан, добавьте href с отметкой о дате последнего изменения файла, например:

<link rel="stylesheet" type="text/css" href="main.css?t=<?=filemtime('main.css')?>" />

Я использую CakePHP, так что я делаю в файле макета это:

  <? $t = filemtime(CSS . 'main.css'); ?>
  <?=$html->css("schedule.css?t={$t}") ?>

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

Тем не менее, при использовании этого метода человек чувствует себя немного грязным из-за того, что использует то, для чего он не предназначен. Отправляемое "сообщение" не имеет смысла в том смысле, что содержание сообщения имеет значение, кроме идентификации его существования.

Вот мои вопросы:

  1. Можно ли признать, что существует риск того, что клиент увидит исправленный HTML с устаревшими таблицами стилей (или, если на то пошло, JavaScript) из кэша браузера?
  2. Это взлом или законное решение?
  3. Есть ли лучшее решение?

2 ответа

Решение

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

Тем не менее, потому что вы используете URL-адрес, такой как: http://site.com/assets/mystyle.css?29320202020, могут быть проблемы с CDN. CDN увидит этот параметр GET и сочтет, что это динамический запрос, поэтому он запросит у вашего сервера файл, который лишает цели наличия кэшированной копии в CDN.

Почему я делаю, что я включаю параметр очистки кэша в мое имя файла: http://site.com/assets/mystyle.2390202202.css, Я использую отличную библиотеку Assetic для этого и только что написал простой код, чтобы мои шаблоны знали, что это требует mystyle.css а также mystyle.2390202202.css генерируется Assetic на лету и вставляется в шаблон.

Этот подход должен обеспечить вам функциональность кэширования, а также хорошо работать с CDN.


Другие возможные решения:

  • ETag: браузер отправит запрос на сервер с ETag (может рассматриваться как хеш файла), и сервер ответит неизмененным ответом заголовка, если файл не изменился. Недостаток: HTTP-запрос все еще должен быть сделан.

  • Установите заголовок expires: сервер сообщит браузеру, что срок действия файла истекает к определенной дате, и, если это еще не та дата, браузер не будет запрашивать копию с сервера и использовать свою локальную кэшированную копию. Недостаток: если файл на сервере изменяется до даты, пользователю браузера потребуется вручную выполнить жесткое обновление.

Вот почему я предпочитаю просто использовать параметр очистки кэша: я могу установить заголовок expires для файла, срок действия которого истекает через 5 лет. И браузер никогда не должен делать http-запрос для этого файла, если я не обновлю файл и не изменю параметр очистки кэша.

CakePHP имеет очень простое в использовании решение для этого. Просто раскомментируйте эту строку:

//Configure::write('Asset.timestamp', true);

от core.php

Согласно этому файлу, это будет

Примените временные метки с последним измененным временем к статическим ресурсам (js, css, images). Добавит параметр строки запроса, содержащий время изменения файла. Это полезно для аннулирования кэшей браузера.

Это чрезвычайно просто сделать и будет работать большую часть времени, однако не является надежным. Большинство прокси не кэшируют ресурсы с "?" в URL, поэтому, если вы хотите исправить эти случаи, вы должны реализовать более сложное решение, подобное предложенному phpdev.

Другие вопросы по тегам