PHP 사이트의 브라우저 캐시를 방지하는 방법


120

클라우드 서버에서 실행되는 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)">

위의 doctype 및 메타 코드로 인해 새 파일 대신 브라우저에 캐시 된 동일한 파일을로드하고 있습니까?


No Cache in all Browsers. 캐시하지 않으려는 파일에 대해? randomGeneratedNumber를 수행 할 수도 있습니다.
Kodemon


네크로에 대한 유혹에 저항했지만 이것을 고려하는 사람은 누구든지 중지하십시오. 캐싱을 제어하고 사용하는 방법을 배우십시오. 한 번의 불편한 에피소드 때문에 맹목적으로 비활성화하지 마십시오. HTTP 에서 캐싱에 대한 장 읽기 The Definitive Guide —이 책 (및 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가 기본적으로 브라우저 캐싱을 방지하려고 시도하는 것 같습니다 ...
fast-reflexes

1
이전 버전의 Internet Explorer에 대체 테마를 보내는 WordPress 플러그인이 있는데 일부 캐싱 시스템에서 심하게 작동하지 않습니다. 이 게시물은 내 첫 Google 검색에서 나왔습니다. 잘했다.
명령

3
이것은 html 안에 포함될 수 없다는 것을 명심하십시오. 페이지 맨 위에 있어야합니다.
Hunter S

9
참고 : session_start()나중에 사용하는 경우 Cache-Control: private, max-age=10800, pre-check=10800180 분이 기본값이므로 헤더를 덮어 씁니다 session.cache_expire. 세션 시작을 피할 수 없지만 캐시 사용을 비활성화해야하는 경우 session_cache_limiter('private');session_cache_expire(0);.
mgutt

2
@thdoan function의 두 번째 매개 변수는 replace에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와 관련이 없습니까? 감사!
Sam Levin

4
첫 번째 줄만 완벽하게 충분합니다. 다섯 번째 줄은 실제로 잘못되었으며 서버 응답 (요청 헤더)에서 할 일이 없습니다. 여섯 번째 줄은 아무 효과가 없습니다. 나는 계속할 수 있습니다 ...
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(); ?>">

임의의 버전, 현재 타임 스탬프 (캐싱을 완전히 무력화)… 그러나 "디버깅"플래그 여부에 관계없이 실제로 의미가 있고 작동하는 것은 아닙니다. 파일의 실제 mtime을 사용하지 않는 이유는 무엇입니까? 그러면 말 그대로 PHP를 업데이트 할 필요가 없으며 캐시가 완전하고 환상적으로 쓸모 없게되지 않을 것입니다. 또는 적절한 Last-Modified 및 ETag를 설정하는 Nginx 또는 Apache와 같이 적절하게 구성된 HTTP 서버로 통계를 전달하십시오. 마찬가지로 이러한 유형의 "디버깅"플래그가 이미 브라우저에 있습니다. (캐시 비활성화, 캐시없이 새로 고침, 빈 캐시 등)
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

@Dalin Gentoo ricer (소스에서 과도하게 컴파일되고 아키텍처를 조정하여 "빠르게"되는 것으로 알려진 Linux 배포판)의 눈물을 울리기 전에 stat전화를 걸었습니다. 파일 시스템 캐시가 없으면 16ns, 최고? 캐시를 사용하면 안정적으로 8ns 미만입니다. 나노초. 그리고 내 시스템에서 MD5는 깜박임없이 754 MiB / s를 처리 할 수 ​​있습니다. ( openssl speed md5) 결합하면 100KB CSS 파일은 129µs (마이크로 초, 0.1295ms) + 8ns (최종 수치에 의미있게 기여하지 않음) = 129µs의 추가 오버 헤드를 갖게됩니다.
amcgregor

더 고려해 보면, 유일하게 "정확한"답변 (유지 보수 부담이 가장 낮고 가장 정확하고 신뢰할 수있는 행동)이 그러한 어리 석고 비현실적인 근거에 대한 단일 의견에서 가장 적게 득표하고 기각한다는 사실에 충격을 받았습니다.
amcgregor

당신과 나는 아마도 다른 웹 사이트에서 일할 것입니다. 그러나 나는 내 의견을지지합니다. 어느 시점에서든 웹 페이지를 제공하는 동시 스레드가 수십 개라면 확장 가능한지 여부에 대해 질문 할 필요가없는 더 나은 옵션이 있다고 생각합니다. hash_file('md5', $deployment_counter)또는 hash_file('md5', $cache_clear_counter)가장 먼저 떠오르는 것입니다.
Dalin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.