Как заставить браузер перезагружать кэшированные файлы CSS / JS? - PullRequest
933 голосов
/ 23 сентября 2008

Я заметил, что некоторые браузеры (в частности, Firefox и Opera) очень усердно используют кэшированные копии файлов .css и .js , даже между сеансами браузера. Это приводит к проблеме при обновлении одного из этих файлов, но браузер пользователя продолжает использовать кэшированную копию.

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

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

Обновление:

После некоторого обсуждения здесь я нашел предложение Джона Милликина и da5id полезным. Оказывается, есть термин для этого: автоматическое управление версиями .

Я разместил новый ответ ниже, который представляет собой сочетание моего первоначального решения и предложения Джона.

Другая идея, предложенная SCdF , заключается в добавлении в файл фиктивной строки запроса. (Некоторый код Python для автоматического использования метки времени в качестве фиктивной строки запроса был передан pi .). Тем не менее, существует некоторое обсуждение относительно того, будет ли браузер кэшировать файл со строкой запроса. (Помните, мы хотим, чтобы браузер кэшировал файл и использовал его при будущих посещениях. Мы хотим, чтобы он снова извлекал файл только после его изменения.)

Поскольку неясно, что происходит с фиктивной строкой запроса, я не принимаю этот ответ.

Ответы [ 48 ]

4 голосов
/ 23 сентября 2008

Я недавно решил это с помощью Python. Вот код (должен быть легко адаптирован к другим языкам):

def import_tag(pattern, name, **kw):
    if name[0] == "/":
        name = name[1:]
    # Additional HTML attributes
    attrs = ' '.join(['%s="%s"' % item for item in kw.items()])
    try:
        # Get the files modification time
        mtime = os.stat(os.path.join('/documentroot', name)).st_mtime
        include = "%s?%d" % (name, mtime)
        # this is the same as sprintf(pattern, attrs, include) in other
        # languages
        return pattern % (attrs, include)
    except:
        # In case of error return the include without the added query
        # parameter.
        return pattern % (attrs, name)

def script(name, **kw):
    return import_tag("""<script type="text/javascript" """ +\
        """ %s src="/%s"></script>""", name, **kw)

def stylesheet(name, **kw):
    return import_tag('<link rel="stylesheet" type="text/css" ' +\
        """%s href="/%s">', name, **kw) 

Этот код добавляет метку времени файлов в качестве параметра запроса к URL-адресу. Вызов следующей функции

script("/main.css")

приведет к

<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">

Преимущество, конечно, в том, что вам больше никогда не придется менять html, прикосновение к файлу CSS автоматически вызовет аннулирование кэша. Работает очень хорошо и накладные расходы не заметны.

4 голосов
/ 27 октября 2017

В Google Chrome есть Жесткая перезагрузка , а также Очистить кэш и Жесткая перезагрузка . Вы можете нажать и удерживать кнопку перезагрузки (в режиме проверки), чтобы выбрать одну.

4 голосов
/ 24 июля 2015

Для моего развития я считаю, что у Chrome есть отличное решение.

https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload

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

Это мой лучший друг, и это супер легкий способ получить то, что вы хотите!

2 голосов
/ 22 июня 2011

Я поместил хеш MD5 содержимого файла в его URL. Таким образом, я могу установить очень длинную дату истечения срока действия, и мне не придется беспокоиться о пользователях, имеющих старый JS или CSS.

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

Если вы используете ASP.NET MVC, вы можете проверить код в моем другом ответе здесь .

2 голосов
/ 11 июня 2013

Для среды сервлетов Java вы можете обратиться к библиотеке Jawr . Страница функций объясняет, как она обрабатывает кэширование:

Jawr сделает все возможное, чтобы заставить ваших клиентов кешировать ресурсы. Если браузер спрашивает, изменился ли файл, заголовок 304 (не измененный) отправляется обратно без содержимого. С другой стороны, с Jawr вы будете на 100% уверены, что новые версии ваших пакетов загружаются всеми клиентами. Каждый URL-адрес ваших ресурсов будет содержать автоматически сгенерированный, основанный на контенте префикс, который изменяется автоматически при каждом обновлении ресурса. После развертывания новой версии URL-адрес пакета также изменится, поэтому клиент не сможет использовать более старую кэшированную версию.

Библиотека также выполняет минификацию js / css, но вы можете отключить ее, если не хотите.

2 голосов
/ 06 июля 2012

Извините за возвращение мертвой нити.

@ ТомА прав.

Использование метода querystring не будет кэшироваться, как указано Steve Souders ниже:

... что Squid, популярный прокси, не кэширует ресурсы с помощью Строка запроса.

@ TomA предложение использовать style.TIMESTAMP.css - это хорошо, но MD5 будет гораздо лучше, поскольку только когда содержимое действительно изменилось, MD5 также изменится.

2 голосов
/ 12 сентября 2017

Просто добавьте этот код, где вы хотите выполнить полную перезагрузку (заставить браузер перезагружать кэшированные файлы CSS / JS) Сделайте это внутри .load, чтобы он не обновлялся как цикл

 $( window ).load(function() {
   location.reload(true);
});
2 голосов
/ 23 декабря 2016

Если вы используете git + PHP, вы можете перезагружать скрипт из кэша каждый раз, когда происходит изменение в git repo, используя следующий код:

exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;
2 голосов
/ 24 сентября 2008

Я предлагаю реализовать следующий процесс:

  • версия ваших файлов CSS / JS при каждом развертывании, например: screen.1233.css (номер может быть вашей версией SVN, если вы используете систему управления версиями)

  • уменьшите их, чтобы оптимизировать время загрузки

2 голосов
/ 20 июля 2015

Я добавляю этот ответ как SilverStripe http://www.silverstripe.org конкретный ответ, который я искал и не нашел, но сработал из чтения: http://api.silverstripe.org/3.0/source-class-SS_Datetime.html#98-110

Надеюсь, это поможет кому-то использовать шаблон SilverStripe и пытаться принудительно перезагрузить кэшированное изображение при каждом посещении / обновлении страницы. В моем случае это gif-анимация, которая воспроизводится только один раз и поэтому не воспроизводится после ее кэширования. В свой шаблон я просто добавил:

?$Now.Format(dmYHis)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...