Jak zapobiec buforowaniu przeglądarki dla strony php

121

Mam witrynę php uruchomioną na serwerze w chmurze, a kiedy dodam nowe pliki css, js lub obrazy, przeglądarka ładuje te same stare pliki js, css i obrazy przechowywane w pamięci podręcznej.

Moja witryna ma typ dokumentu i metatag, jak poniżej

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

Ze względu na powyższy doctype i meta kod ładuję te same pliki buforowane w przeglądarce zamiast nowego

ArrayOutOfBound
źródło
No Cache in all Browsers. Możesz również wykonać? RandomGeneratedNumber na plikach, których nie chcesz buforować.
Kodemon
2
Prawdopodobnie nie chcesz całkowicie wyłączać pamięci podręcznej dla obrazów / js / css: stackoverflow.com/questions/4206224/ ...
FoolishSeth
Oparł się pokusie nekro, ale proszę, każdy rozważający to: przestań. Naucz się kontrolować i używać buforowania, nie wyłączaj go na ślepo z powodu jednego niewygodnego epizodu. Przeczytaj rozdział o buforowaniu z HTTP The Definitive Guide - ta książka (i RFC) powinna być lekturą obowiązkową, z testem. Dowiedz się, jak określić Last-Modified, odpowiedzieć na If-Modified-Since i korzystać z identyfikacji ETag. Następnie, gdy zasób zostanie zaktualizowany, przeglądarki zostaną poinformowane, kiedy 304 zmieni się ponownie w 200.
amcgregor

Odpowiedzi:

283

Spróbuj tego

<?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");
?>
Codesen
źródło
6
Z wyjątkiem "max-age = 0", są to nagłówki wysłane przez PHP bez określenia powyższego w mojej instalacji. Wygląda na to, że PHP domyślnie próbuje zapobiec buforowaniu przeglądarki ...
szybkie refleksy
1
Mam wtyczkę WordPress, która wysyła alternatywny motyw do starszych wersji Internet Explorera i bardzo się uruchamiała w niektórych systemach pamięci podręcznej. Ten post pojawił się podczas mojego pierwszego wyszukiwania w Google. Dobrze rozegrane.
Tryb konieczny
3
Pamiętaj, że nie można tego osadzić w html; powinien znajdować się na samej górze strony.
Hunter S
9
Uwaga: jeśli użyjesz session_start()później, nadpisze twój nagłówek, Cache-Control: private, max-age=10800, pre-check=10800ponieważ 180 minut jest domyślną wartością session.cache_expire. Jeśli nie możesz uniknąć rozpoczęcia sesji, ale musisz wyłączyć użycie pamięci podręcznej session_cache_limiter('private');session_cache_expire(0);.
mgutt
2
@thdoan Drugi parametr headerfunkcji jest logiczna dla zastąpienia . Opcjonalny parametr replace wskazuje, czy nagłówek powinien zastąpić poprzedni podobny nagłówek, czy dodać drugi nagłówek tego samego typu.
mrReiha
36

Tutaj, jeśli chcesz kontrolować to za pomocą HTML: zrób jak poniżej Opcja 1:

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

A jeśli chcesz kontrolować to przez PHP: zrób to jak poniżej Opcja 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');

ORAZ Opcja 2 JEST ZAWSZE LEPSZA, aby uniknąć problemu z buforowaniem proxy.

Ritesh Aryal
źródło
10

Możesz spróbować tego:

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

Miejmy nadzieję, że pomoże to zapobiec Cache, jeśli takie istnieją!

Aakanksha
źródło
Dotyczy to tylko buforowania plików HTML, prawda? I nie ma to nic wspólnego z eTag? Dzięki!
Sam Levin
4
tylko pierwsza linia powinna wystarczyć. Piąty wiersz jest w rzeczywistości błędny i nie ma nic wspólnego z odpowiedzią serwera (jest to nagłówek żądania). szósta linia nie odniesie żadnego skutku. Mógłbym kontynuować ...
The Surrican
Podejście ze strzelby: rzuć wszystkim w ścianę, miej nadzieję, że coś utknie. Zgodnie z moim komentarzem do samego pytania, gorąco polecam pobranie kopii HTTP: The Definitive Guide i przeczytanie rozdziału o buforowaniu. Również specyfikacje RFC, ale ich czytanie to osobna umiejętność. („Połączenie: zamknij” to zabawny strzał z nogi na nogę, który włącza, wyłącza wydajne potokowanie żądań lub nic nie robi, ale podejrzewam, że PHP może to przepuścić.)
amcgregor
7

Miałem problem z buforowaniem moich plików css. Ustawianie nagłówków w PHP nie pomogło mi (być może dlatego, że nagłówki musiałyby być ustawione w pliku arkusza stylów zamiast strony, która do niego prowadzi?).

Rozwiązanie znalazłem na tej stronie: https://css-tricks.com/can-we-prevent-css-caching/

Rozwiązanie:

Dołącz znacznik czasu jako część zapytania identyfikatora URI dla połączonego pliku.
(Może być używany do css, js, obrazów itp.)

Dla rozwoju:

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

W przypadku produkcji (gdzie buforowanie jest głównie dobrą rzeczą):

<link rel="stylesheet" type="text/css" href="style.css?version=3.2">
(i przepisz ręcznie, gdy jest to wymagane)

Lub połączenie tych dwóch:

<?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') : ""; ?>">

EDYTOWAĆ:

Albo ładniejsze połączenie tych dwóch:

<?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(); ?>">
Lukas
źródło
Dowolne wersje, aktualne sygnatury czasowe (całkowite pokonanie buforowania)… ale nie jedyna rzecz, która ma sens i działa, niezależnie od flagi „debugowania” czy nie. Dlaczego nie używasz rzeczywistego czasu mtime pliku? Wtedy dosłownie nigdy nie musiałbyś aktualizować PHP, a pamięci podręczne nie stałyby się całkowicie i fantastycznie bezużyteczne. Lub po prostu dostarcz swoje statystyki za pomocą odpowiednio skonfigurowanego serwera HTTP, takiego jak Nginx lub Apache, który ustawia właściwe Last-Modified i ETag. Podobnie, ten typ flagi „debugowania” już istnieje… w przeglądarce. (Wyłącz pamięci podręczne, odświeżaj bez pamięci podręcznej, opróżnij pamięci podręczne,…)
amcgregor
5

W zależności od przypadku blokowanie pamięci podręcznej przeglądarki nie jest dobrym pomysłem. Szukając rozwiązania znalazłem takie rozwiązania:

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

Problem polega na tym, że jeśli plik zostanie nadpisany podczas aktualizacji na serwerze, co jest moim scenariuszem, pamięć podręczna jest ignorowana, ponieważ sygnatura czasowa jest modyfikowana, nawet zawartość pliku jest taka sama.

Używam tego rozwiązania, aby zmusić przeglądarkę do pobierania zasobów tylko wtedy, gdy ich zawartość jest zmodyfikowana:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=hash_file('md5', $file);?>">
ismavolk
źródło
Yikes! Byłoby okropne dla wydajności i skalowalności, gdyby zawsze ładował wszystkie pliki CSS / JS w głównym wątku, aby sprawdzić ich rozmiar / hash.
Dalin
@Dalin Zanim zaczniesz płakać łzami Gentoo ricera (dystrybucja Linuksa znana z „szybkiej pracy” poprzez nadmierną kompilację ze źródeł i dostrojenie architektury), statzadzwoniłbym. Bez pamięci podręcznej systemu plików, 16ns, topów? Z pamięcią podręczną, niezawodnie <8ns. Nanosekundy. A w moim systemie MD5 może przetwarzać 754 MiB / s bez mrugnięcia. ( openssl speed md5) Łącznie, plik CSS o rozmiarze 100 KB miałby łączny dodatkowy narzut… 129 µs (mikrosekund, 0,1295 ms) + 8ns (co nie wpływa znacząco na ostateczną liczbę) = 129 µs.
amcgregor
Po dalszych rozważaniach zdumiewa mnie, że jedyna „poprawna” odpowiedź (przy najniższym obciążeniu konserwacyjnym, najbardziej dokładnym / niezawodnym zachowaniu) jest zarówno najmniej głosowana, jak i odrzucona w jednym komentarzu z tak wątłych i nierealistycznych powodów.
amcgregor
Ty i ja prawdopodobnie pracujemy na różnych stronach internetowych. Ale podtrzymuję swój komentarz. Jeśli w dowolnym momencie istnieją dziesiątki współbieżnych wątków dostarczających strony internetowe, myślę, że istnieją lepsze opcje, których nie musisz nawet kwestionować, czy są skalowalne. hash_file('md5', $deployment_counter)lub hash_file('md5', $cache_clear_counter)są pierwszymi, które przychodzą na myśl.
Dalin