Очистка кеша через параметры

123

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

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

Два вопроса: эффективно ли это сломает кеш? Будет ли параметр заставлять браузер никогда не кэшировать ответ с этого URL-адреса, поскольку параметр указывает, что это динамический контент?

Брэд Херман
источник

Ответы:

115

Параметр ?v=1.123указывает строку запроса, и поэтому браузер будет думать, что это новый путь, скажем, от ?v=1.0. Таким образом, он загружается из файла, а не из кеша. Как ты хочешь.

И браузер будет предполагать, что источник останется прежним при следующем вызове, ?v=1.123и должен кэшировать его с этой строкой. Таким образом, он будет оставаться в кеше, независимо от настройки вашего сервера, до тех пор, пока вы не перейдете к нему ?v=1.124или так далее.

Маршалл
источник
4
Цитата Стива Содерса: «Чтобы воспользоваться преимуществами кеширования с помощью популярных прокси-серверов, избегайте повторения с помощью строки запроса и вместо этого изменяйте само имя файла». Полное объяснение можно найти здесь: stevesouders.com/blog/2008/08/23/...
лао
25
Этому сообщению в блоге уже почти десять лет. Считаете ли вы, что провайдеры кеша и CDN еще не приняли это? Squid, похоже, теперь может кэшировать документы со строками запроса .
jeteon
1
Может быть, это кому-то поможет: Лично я использую метку времени модификации файла как «автоматический» параметр версии, например. <link rel="stylesheet" href="style.css?v=1487935578" />
oelna
Я лично не понимаю, почему, но Лара Хоган (Свансон) (технический менеджер Etsy) не рекомендует использовать параметры запроса для очистки кеша. Я думаю, это связано с прокси-серверами кеша между пользователем и сервером.
Sam Rueby
36

Два вопроса: эффективно ли это сломает кеш?

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

Будет ли параметр заставлять браузер никогда не кэшировать ответ с этого URL-адреса, поскольку параметр указывает, что это динамический контент?

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

Пекка
источник
1
@spender Я не могу найти ссылку прямо сейчас, боюсь, там была длинная статья в блоге или ТАК-ответ, где об этом говорит Джефф Этвуд (IIRC)
Пекка
2
@spender Я читал, что некоторые прокси-серверы (старые или могут быть настроены на) игнорируют строку запроса при кэшировании.
MrWhite
2
@spender - я слышал то же самое, и я думаю, что изменение имени файла или пути - лучший вариант. Может быть проще всего просто позволить перемещать все ваши статические файлы под именем версированной папки, например, /static/v22/file.cssкак вы могли бы сделать несколько файлов с одним переименованием папки, например /static/v23/file.cssи/static/v23/mystuff.js
Брэд Паркс
22

Безопаснее указывать номер версии в фактическом имени файла. Это позволяет одновременно существовать нескольким версиям, поэтому вы можете развернуть новую версию, и если какие-либо кешированные HTML-страницы все еще существуют, запрашивая старую версию, они получат версию, которая работает с их HTML.

Обратите внимание, что в одном из крупнейших развертываний с поддержкой версий где-либо в Интернете, jQuery использует номера версий в фактическом имени файла и безопасно позволяет нескольким версиям сосуществовать без какой-либо специальной логики на стороне сервера (каждая версия - это просто отдельный файл).

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

jfriend00
источник
Я согласен с этим, но гораздо проще, чтобы Sinatra добавляла? V = <% = VERSION%> ко всем запросам css и js, вместо того, чтобы контролировать каждый файл индивидуально. В конце концов мы переключимся на sinatra-assetpack, который будет предварительно обрабатывать и сжимать все файлы и фактически добавлять номер версии к имени файла, что затем позволит нам управлять ими по отдельности намного проще.
Брэд Херман,
1
Я согласен, что указание номера версии в имени файла является самым безопасным решением, если вы хотите быть уверены на 10000%, но я не следую аргументу «несколько версий существуют одновременно». URL-адрес с параметром запроса отличается от того же URL-адреса с другим параметром запроса. Клиент должен рассматривать их как два разных ресурса; в противном случае клиент сломан.
Pekka
2
@Pekka - номер версии может допускать одновременное существование нескольких версий, но для этого требуется взаимодействие с сервером, чтобы сопоставить параметр запроса с правильным фактическим файлом. Я не думаю, что это то, что здесь делает OP, и нет особых причин требовать этого усложнения, когда изменение имени файла намного проще и не требует взаимодействия с сервером. Очевидно, оба могут работать.
jfriend00
11

Как уже говорили другие, перебор кеша с помощью параметра запроса обычно считается плохой идеей (tm), и это было уже давно. Лучше отражать версию в названии файла. Html5 Boilerplate , среди прочего, не рекомендует использовать строку запроса.

Тем не менее, все рекомендации, которые я видел и цитирующие источник, похоже, основаны на своей мудрости из статьи Стива Содерса 2008 года. Его выводы основаны на поведении доверенных лиц в то время, и они могут быть актуальны или не актуальны в наши дни. Тем не менее, в отсутствие более свежей информации изменение имени файла является безопасным вариантом.

hashchange
источник
9

Он будет очищать кеш один раз, после того как клиент загрузит ресурс, каждый второй ответ будет обслуживаться из кеша клиента, если:

  1. параметр v обновлен.
  2. клиент очищает кеш
ncremins
источник
6

В общем, это должно быть хорошо, но это может не работать, если есть промежуточный кеш (прокси), который настроен на игнорирование параметров запроса.

Например, если вы обслуживаете статический контент через Akamai CDN, его можно настроить на игнорирование параметров запроса, чтобы предотвратить перебор кеша с помощью этого метода.

Кен Лю
источник
5

Это очень сильно зависит от того, насколько надежным должно быть ваше кеширование. Например, прокси-сервер squid (и, возможно, другие) по умолчанию не кэширует URL-адреса, обслуживаемые строкой запроса - по крайней мере, так было, когда была написана эта статья. Если вы не возражаете против определенных вариантов использования, вызывающих ненужные пропуски кеша, продолжайте работу с параметрами запроса. Но очень легко настроить схему очистки кеша на основе имени файла, которая позволяет избежать этой проблемы.

Бобби Джек
источник
5
Прокси-сервер squid, процитированный в статье Стива Содерса, изменил свою политику кэширования по умолчанию. Начиная с версии 2.7 (май 2008 г.) и версии 3.1 (март 2010 г.) по умолчанию выполняется кэширование динамического содержимого.
Джош Рэк,
5

Найдено сравнение 2 методов (строки запроса против имени файла) здесь :

Версия как строка запроса имеет две проблемы.

Во-первых, это может быть не всегда браузер, который реализует кеширование, через которое нам нужно обойтись. Говорят, что некоторые (возможно, более старые) прокси игнорируют строку запроса в отношении своего поведения кэширования.

Во-вторых, в некоторых более сложных сценариях развертывания, когда у вас есть несколько внешних и / или несколько внутренних серверов, обновление происходит не мгновенно. Вы должны иметь возможность одновременно обслуживать как старую, так и новую версию своих ресурсов. Посмотрите, например, как это влияет на вас при использовании Google App Engine.

пользователь
источник
4

Другой подобный подход - использовать htaccess mod_rewrite для игнорирования части пути при обслуживании файлов. Ваша индексная страница, которая никогда не кэшируется, ссылается на последний путь к файлам.

С точки зрения разработки это так же просто, как использование params для номера версии, но столь же надежно, как и подход к имени файла.

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

1.2.3/css/styles.cssобслуживает тот же файл, что css/styles.cssи первый каталог, который удаляется и игнорируется файлом htaccess

Включение версионных файлов

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

Обратите внимание, что этот подход означает, что вам нужно отключить кеширование вашей индексной страницы - Использование тегов <meta> для отключения кеширования во всех браузерах?

файл .htaccess

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

Вы можете использовать тот же подход на любой серверной платформе, которая позволяет переписывать URL

(условие перезаписи адаптировано из mod_rewrite - перезаписать каталог в строку запроса, кроме / #! / )

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

alexanderbird
источник
2
<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 
Конете Кристиан
источник
Во время разработки / тестирования новых выпусков кеш может быть проблемой, потому что браузер, сервер и даже иногда телефонная компания 3G (если вы выполняете мобильное развертывание) будут кэшировать статический контент (например, JS, CSS, HTML, img). Вы можете преодолеть это, добавив к URL-адресу номер версии, случайное число или временную метку, например: JSP: <script src = "js / excel.js? Time = <% = new java.util.Date ()%>"> </ script> Если вы используете чистый HTML (вместо серверных страниц JSP, ASP, PHP), сервер вам не поможет. В браузере ссылки загружаются до
запуска
Я не думаю, что это синхронно загрузит файлы JS по порядку.
Stealth Rabbi
0
 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###
Тея
источник
0

Надеюсь, это поможет вам ввести внешний JS файл.

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

Источник - код Cachebuster на JavaScript

Винит Кадколь
источник