Заставить браузер перезагрузить 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 имеет дополнительный тег в конце, но он остается тем же самым, пока файл не был изменен. Это означает, что браузер сможет кешировать его как обычно. Однако, как только файл будет изменен, ссылка изменится, и браузер не пропустит ритм.
Тем не менее, при использовании этого метода человек чувствует себя немного грязным из-за того, что использует то, для чего он не предназначен. Отправляемое "сообщение" не имеет смысла в том смысле, что содержание сообщения имеет значение, кроме идентификации его существования.
Вот мои вопросы:
- Можно ли признать, что существует риск того, что клиент увидит исправленный HTML с устаревшими таблицами стилей (или, если на то пошло, JavaScript) из кэша браузера?
- Это взлом или законное решение?
- Есть ли лучшее решение?
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.