Як запобігти кеш-пам’яті браузера для php-сайту


120

У мене php-сайт працює на хмарному сервері. Коли я додаю нові файли css, js або зображення, браузер завантажує ті самі старі файли js, css та зображення, які зберігаються в кеші.

На моєму веб-сайті є доктіп та метатег, як показано нижче

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta http-equiv="Page-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Page-Exit" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Exit" content="blendTrans(Duration=1.0)">

Через вищевказаний doctype та мета-код я завантажую ті самі файли, кешовані в браузері замість нових


No Cache in all Browsers. Ви також можете зробити? RandomGeneratedNumber у файлах, які ви не хочете кешувати.
Кодемон

2
Ви , ймовірно , не хочете , щоб відключити кеш повністю для зображень / JS / CSS: stackoverflow.com/questions/4206224 / ...
FoolishSeth

Протистояли спокусі некроїти, але будь-хто, хто вважає це: зупиніться. Навчіться керувати та використовувати кешування, не просто сліпо відключайте його через один незручний епізод. Прочитайте розділ "Кешування з HTTP" Остаточний посібник - ця книга (і RFC) повинна бути обов'язковою для читання з тестом. Дізнайтеся, як вказати Last-Modified, відповісти на If-Modified-Since і використовувати ідентифікацію ETag. Потім, коли об’єкт оновлюється, браузери будуть повідомлені, коли цей 304 знову стане 200.
amcgregor

Відповіді:


282

спробуйте це

<?php

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

6
За винятком "max-age = 0", це заголовки, надіслані PHP, не вказуючи вказане вище в моїй установці. Здається, PHP намагається запобігти кешування браузера за замовчуванням ...
швидкі рефлекси

1
У мене є плагін WordPress, який надсилає альтернативну тему до старих версій Internet Explorer, і вона погано спрацьовує на деяких системах кешування. Ця публікація з’явилася під час мого першого пошуку в Google. Гарно зіграно.
імператив

3
Майте на увазі, що це не може бути вбудовано всередині html; це має бути в самому верху сторінки.
Мисливець S

9
Примітка. Якщо ви користуєтесь session_start()згодом, він замінить ваш заголовок, Cache-Control: private, max-age=10800, pre-check=10800оскільки 180 хвилин - це значення за замовчуванням session.cache_expire. Якщо ви не можете уникнути запуску сеансу, але вам потрібно відключити використання кешу session_cache_limiter('private');session_cache_expire(0);.
mgutt

2
@thdoan Другий параметр headerфункції є логічне для заміни . Необов'язковий параметр заміни вказує, чи повинен заголовок замінювати попередній аналогічний заголовок або додати другий заголовок того ж типу.
mrReiha

36

Тут, якщо ви хочете керувати ним за допомогою HTML: зробіть, як описано нижче Варіант 1:

<meta http-equiv="expires" content="Sun, 01 Jan 2014 00:00:00 GMT"/>
<meta http-equiv="pragma" content="no-cache" />

А якщо ви хочете керувати ним через PHP: зробіть це так, як наведено нижче Варіант 2:

header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');

І Варіант 2 ЗАВЖДИ ПОСЛУГІший, щоб уникнути проблеми кешування на основі проксі.


10

Ви можете спробувати це:

    header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
    header("Cache-Control: post-check=0, pre-check=0", false);
    header("Pragma: no-cache");
    header("Connection: close");

Сподіваємось, це допоможе запобігти кеш, якщо такий є!


Це стосується лише кешування файлів HTML? І нічого спільного з eTag не має? Дякую!
Сем Левін

4
просто першого рядка повинно вистачити ідеально. 5-й рядок насправді неправильний і не має нічого спільного у відповіді сервера (це заголовок запиту). шостий рядок не матиме жодного ефекту. я міг би продовжуватись ...
The Surrican

Підхід рушниці: киньте все на стіну, сподівайтеся, що щось прилипає. Відповідно до мого коментаря до самого запитання, я настійно рекомендую захопити копію HTTP: Посібник з остаточним підсумком та прочитати розділ Кешування. Також RFC, але їх читання - це виразний навик. ("З'єднання: тісно" - це веселий знімок, включений, вимкнення ефективного конвеєрного запиту або нічого не зробить, але я підозрюю, що PHP може насправді пропустити це.)
amcgregor

7

У мене виникли проблеми з кешуванням файлів css. Налаштування заголовків у PHP не допомогло мені (можливо, тому, що заголовки потрібно було б встановити у файлі таблиць стилів замість сторінки, що посилається на нього?).

Я знайшов рішення на цій сторінці: https://css-tricks.com/can-we-prevent-css-caching/

Рішення:

Додайте часову позначку як частину запиту URI для пов'язаного файлу.
(Можна використовувати для css, js, зображень тощо)

Для розвитку:

<link rel="stylesheet" href="style.css?<?php echo date('Y-m-d_H:i:s'); ?>">

Для виробництва (де кешування в основному є хорошою справою):

<link rel="stylesheet" type="text/css" href="style.css?version=3.2">
(і перепишіть вручну, коли це потрібно)

Або поєднання цих двох:

<?php
    define( "DEBUGGING", true ); // or false in production enviroment
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo (DEBUGGING) ? date('_Y-m-d_H:i:s') : ""; ?>">

Редагувати:

Або гарне поєднання цих двох:

<?php
    // Init
    define( "DEBUGGING", true ); // or false in production enviroment
    // Functions
    function get_cache_prevent_string( $always = false ) {
        return (DEBUGGING || $always) ? date('_Y-m-d_H:i:s') : "";
    }
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo get_cache_prevent_string(); ?>">

Довільні версії, поточні часові позначки (цілком перемігши кешування)… але не одне, що насправді має сенс і працює, незалежно від того, прапор «налагодження» чи ні. Чому ви не використовуєте фактичний mtime файлу? Тоді вам буквально ніколи не потрібно оновлювати PHP, і кеші не стануть повністю і фантастично марними. Або просто доставити вашу статику за допомогою правильно налаштованого HTTP-сервера, наприклад Nginx або Apache, який встановлює належні Last-Modified та ETag. Аналогічно, такий тип прапора "налагодження" вже існує ... у браузері. (Вимкнути кеші, оновити без кешу, порожні кеші,…)
amcgregor

5

Запобігання кеш-пам’яті браузера не є хорошою ідеєю залежно від конкретного випадку. Шукаючи рішення, я знайшов такі рішення:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=filemtime($file);?>">

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

Я використовую це рішення, щоб змусити браузер завантажувати активи, лише якщо зміст його змінено:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=hash_file('md5', $file);?>">

Yikes! Це було б страшно для продуктивності та масштабованості, щоб завжди завантажувати всі ваші CSS / JS файли в основний потік, щоб перевірити їх розмір / хеш.
Далін

@Dalin Перш ніж плакати сльози Gentoo ricer (дистрибутив Linux, відомий тим, що "йде швидко" завдяки надмірному компіляції з джерела та налаштованої архітектури), я б почав statдзвінок. Без кеш-файлів, 16ns, вершини? З кешем надійно <8ns. Наносекунди. І в моїй системі MD5 може обробляти 754 МіБ / с, не моргаючи. ( openssl speed md5) У поєднанні CSS-файл розміром 100 КБ повинен мати комбіновані додаткові накладні витрати… 129 мкс (мікросекунди, 0.1295 мс) + 8 сек (що не має значення для остаточного числа) = 129 мкс.
amcgregor

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

Ми з вами, ймовірно, працюємо на різних веб-сайтах. Але я стою біля свого коментаря. Якщо в будь-який момент часу є десятки паралельних потоків, які доставляють веб-сторінки, то я думаю, що є кращі варіанти, які вам навіть не знадобляться, чи можна це масштабувати. hash_file('md5', $deployment_counter)або hash_file('md5', $cache_clear_counter)є першими, які приходять у голову.
Далін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.