Как предотвратить кеширование браузера для php-сайта


121

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

На моем сайте есть doctype и метатег, как показано ниже.

<!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)">

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


No Cache in all Browsers, Вы также можете сделать? RandomGeneratedNumber для файлов, которые не хотите кэшировать.
Kodemon

2
Вероятно, вы не хотите полностью отключать кеш для изображений / js / css: stackoverflow.com/questions/4206224/…
FoolishSeth

Сопротивлялся искушению некро, но, пожалуйста, всем, кто задумывается над этим: остановитесь. Научитесь контролировать и использовать кеширование, а не просто отключать его вслепую из-за одного неудобного эпизода. Прочтите главу о кэшировании из HTTP The Definitive Guide - эту книгу (и RFC) следует прочитать в обязательном порядке с тестом. Узнайте, как указать Last-Modified, ответить на If-Modified-Since и использовать идентификацию ETag. Затем, когда актив будет обновлен, браузеры будут проинформированы, когда 304 снова станет 200.
amcgregor

Ответы:


283

попробуй это

<?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 пытается предотвратить кеширование браузера по умолчанию ...
fast-reflexes

1
У меня есть плагин WordPress, который отправляет альтернативную тему в старые версии Internet Explorer, и он сильно зависал в некоторых системах кеширования. Это сообщение появилось при моем первом поиске в Google. Отлично сработано.
Императив

3
Имейте в виду, что это не может быть встроено в html; это должно быть в самом верху страницы.
Hunter 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функции - это логическое значение для замены . Необязательный параметр replace указывает, должен ли заголовок заменить предыдущий аналогичный заголовок или добавить второй заголовок того же типа.
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
просто первой строки должно хватить. Пятая строка на самом деле неверна и не имеет ничего общего с ответом сервера (это заголовок запроса). шестая строка не будет иметь никакого эффекта. я мог бы продолжить ...
The Surrican

Подход с дробовиком: бросьте все в стену, надеюсь, что что-то прилипнет. Согласно моему комментарию по самому вопросу, я настоятельно рекомендую взять копию HTTP: The Definitive Guide и прочитать главу о кэшировании. Также RFC, но их чтение - это особый навык. («Connection: close» - это забавный шаг, который нужно включить, отключив эффективную конвейерную обработку запросов, или он ничего не сделает, но я подозреваю, что 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(); ?>">

Произвольные версии, текущие отметки времени (полностью исключающие кеширование)… но не единственное, что действительно имеет смысл и работает, независимо от флага «отладки» или нет. Почему вы не используете фактическое время файла? Тогда вам буквально никогда не понадобится обновлять 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);?>">

Хлоп! Было бы ужасно для производительности и масштабируемости всегда загружать все ваши файлы CSS / JS в основном потоке, чтобы проверить их размер / хэш.
Далин

@Dalin Прежде, чем вы заплачете в слезы Gentoo ricer (дистрибутив Linux, известный тем, что он «быстро работает» из-за чрезмерной компиляции из исходных текстов и настройки архитектуры), я бы засек statзвонок. Без кеша файловой системы, 16нс, вершины? С кешем надежно <8 нс. Наносекунд. А в моей системе 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.