Запуск кешу через парами


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/…
lao

25
Зараз повідомлення в блозі наближається до десятиліття. Як ви вважаєте, що постачальники кеш-пам'яті та CDN ще не вмістили його? Кальмар , здається , щоб мати можливість кешувати документи рядки запиту в даний час .
jeteon

1
Можливо, це комусь допомагає: Особисто я використовую часову позначку модифікації файлів як параметр версії "автоматична", наприклад. <link rel="stylesheet" href="style.css?v=1487935578" />
oelna

Я особисто не розумію, чому, але Лара Хоган (Swanson) (менеджер з інженерії Etsy) не рекомендує використовувати параметри запитів для кешування-кешування. Я думаю, що це стосується проксі-серверів кешу між користувачем та сервером.
Сем Рюбі

36

Два питання: Чи ефективно це порушить кеш?

Так. Навіть переповнення стека використовують цей метод, хоча я пам’ятаю, що у них (зі своїми мільйонами відвідувачів на день та мільйонами різних клієнтських та проксі-версій та конфігурацій) були випадки, коли навіть цього було недостатньо, щоб зламати кеш. Але загальне припущення полягає в тому, що це спрацює, і це підходящий метод для порушення кешування клієнтів.

Чи змусить параметр браузер ніколи не кешувати відповідь з цього URL-адреси, оскільки парам вказує, що це динамічний контент?

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


1
@spender Я не можу зараз знайти посилання. Боюся, з’явилась тривала стаття в блозі або ТАК відповідь, де Джефф Етвуд розповідає про це (IIRC)
Pekka,

2
@spender Я читав, що деякі проксі-сервери (або старі, або їх можна налаштувати) ігнорують рядок запиту під час кешування.
MrWhite

2
@spender - я чув те саме, і я думаю, що зміна назви файла чи шлях є найкращим варіантом. Можливо, найпростіше просто дозволити переміщати всі статичні файли під перейменованим іменем папки, наприклад, /static/v22/file.cssяк ви могли зробити декілька файлів з однією перейменовуванням папки, наприклад, /static/v23/file.cssі/static/v23/mystuff.js
Brad Parks

22

Безпечніше вводити номер версії в фактичне ім’я файлу. Це дозволяє одночасно існувати декілька версій, щоб ви могли розгорнути нову версію, і якщо ще зберігаються кешовані HTML-сторінки, які вимагають старішої версії, вони отримають версію, яка працює з їх HTML.

Зауважте, що в одному з найбільших розгорнутих версій в Інтернеті jQuery використовує номери версій у фактичному імені файлу, і це безпечно дозволяє спільно існувати декілька версій без будь-якої спеціальної логіки на стороні сервера (кожна версія - це лише інший файл).

Це перетворює кеш один раз, коли ви розгортаєте нові сторінки та нові пов'язані файли (що саме ви хочете), а з тих пір ці версії можуть бути ефективно кешовані (чого ви також хочете).


Я погоджуюся з цим, але набагато простіше просто додавати Sinatra до всіх запитів css і js? V = <% = VERSION%> порівняно з необхідністю контролювати кожен файл окремо. Врешті-решт ми перейдемо на sinatra-панель активів, яка попередньо обробить і стисне всі файли і фактично додасть до імені файлу версію #, що дозволить нам контролювати їх окремо набагато простіше.
Бред Герман

1
Я погоджуюся, що номер версії у назві файлу - це найкраще безпечне рішення, якщо ви хочете зробити 10000% впевненим, але я не дотримуюся аргументу "декілька версій, які існують одразу". URL-адреса з параметром запиту відрізняється від тієї ж URL-адреси з іншим параметром запиту. Клієнт повинен розглядати їх як два різних ресурси; якщо їх немає, клієнт зламається.
Pekka

2
@Pekka - річ з номером версії може дозволити існувати декілька версій одночасно, але для цього потрібна співпраця сервера для відображення параметра запиту у правильному фактичному файлі. Я не думаю, що саме це робить тут ОП, і мало підстав вимагати, щоб це ускладнення при зміні імені файлів було набагато простіше і не потребує співпраці з сервером. Очевидно, що обидва можуть працювати.
jfriend00

11

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

Однак, з тих рекомендацій, які я бачив, які цитували джерело, всі, здається, беруть свою мудрість із статті 2008 року Стіва Суудерса. Його висновки ґрунтуються на поведінці довірених осіб у той час, і вони можуть бути або не бути актуальними в наші дні. Однак, за відсутності більш актуальної інформації, зміна імені файлу є безпечним варіантом.


9

Він завантажує кеш-пам'ять один раз, після того як клієнт завантажив ресурс, кожен інший відповідь буде поданий з кеш-пам'яті клієнта, якщо:

  1. параметр v оновлюється.
  2. клієнт очищає кеш

6

Загалом це повинно бути добре, але можливо, що це не працює, якщо є проміжний кеш (проксі), який налаштований ігнорувати параметри запиту.

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


5

Це дуже залежить від того, наскільки надійним ви хочете кешувати. Наприклад, проксі-сервер squid (і, можливо, інші) за замовчуванням не кешує URL-адреси, що подаються з рядком запитів - принаймні, це робилося під час написання цієї статті. Якщо ви не заперечуєте проти певних випадків використання, які спричиняють непотрібні пропуски кешу, тоді продовжуйте користуватися парамами запитів. Але дуже легко створити схему перебору кешу на основі імені файлів, що дозволяє уникнути цієї проблеми.


5
Проксі-провайдер кальмарів, зазначений у статті Steve Souders, змінив їх політику кешування за замовчуванням. З версії 2.7 (травень 2008 р.) Та версії 3.1 (березень 2010 р.) Поведінка за замовчуванням полягає в кешуванні динамічного вмісту.
Josh Rack

5

Знайдено порівняння 2 методів (рядки запиту проти імені файлу) тут :

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

По-перше, це не завжди може бути браузер, який реалізує кешування, через яке нам потрібно перейти. Кажуть, що деякі (можливо, старші) проксі-сервери ігнорують рядок запитів щодо кешування.

По-друге, у певних складніших сценаріях розгортання, де у вас є декілька серверів інтерфейсу та / або декілька резервних серверів, оновлення - це все, але не миттєве. Потрібно мати можливість одночасно обслуговувати і стару, і нову версію своїх активів. Дивіться, наприклад, як це впливає на вас під час використання Google App Engine.


4

Інший подібний підхід полягає у використанні htaccess mod_rewrite для ігнорування частини шляху при обслуговуванні файлів. Ваша ніколи не кешована сторінка індексу посилається на останній шлях до файлів.

З точки зору розвитку, це так просто, як використовувати парами для номера версії, але це так само надійно, як і підхід до назви файлів.

Використовуйте ігноровану частину шляху для номера версії, а сервер просто ігнорує його і подає файл без кешування.

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 для оновлення.


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 telco (якщо ви робите мобільне розгортання) кешуватимуть статичний вміст (наприклад, JS, CSS, HTML, img). Ви можете подолати це, додавши номер URL-адреси, випадкове число або часову позначку до URL, наприклад: JSP: <script src = "js / excel.js? Time = <% = new java.util.Date ()%>"> </ скрипт> Якщо ви використовуєте чистий HTML (замість серверних сторінок JSP, ASP, PHP), сервер вам не допоможе. У браузері посилання завантажуються до запуску JS, тому вам потрібно видалити посилання та завантажити їх з JS
Conete Cristian

Я не думаю, що це завантажить файли JS по порядку, синхронно.
Стелс-раббі

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>

Джерело - код кешбюстера в JavaScript

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.