일부 브라우저(특히 Firefox 및 Opera)에서는 브라우저 세션 간에도 .css 및 .js 파일의 캐시된 복사본을 매우 많이 사용하고 있습니다.이러한 파일 중 하나를 업데이트할 때 문제가 발생하지만 사용자의 브라우저는 캐시된 복사본을 계속 사용합니다.
파일이 변경되었을 때 사용자의 브라우저를 강제로 다시 로드하는 가장 우아한 방법은 무엇입니까?
이 솔루션에서는 페이지를 방문할 때마다 브라우저가 파일을 강제로 새로고침하지 않는 것이 이상적입니다.
나는 존 밀리킨과 da5id의 제안이 유용하다는 것을 알았다.이 용어에는 자동 버전이라는 용어가 있습니다.
아래에 저의 원래 해결책과 존의 제안을 조합한 새로운 답변을 올렸습니다.
SCdF가 제안한 또 다른 아이디어는 파일에 가짜 쿼리 문자열을 추가하는 것입니다.(타임스탬프를 자동으로 가짜 쿼리 문자열로 사용하기 위한 일부 Python 코드는 pi에 의해 제출되었습니다.)
단, 브라우저가 쿼리 문자열로 파일을 캐시할지 여부에 대해서는 논의 중입니다.(브라우저가 파일을 캐시하여 향후 방문 시 사용하는 것을 잊지 마십시오.파일이 변경되었을 때만 파일을 다시 가져오기를 원합니다.
질문에 대한 답변
이 솔루션은 PHP로 작성되어 있지만 다른 언어에 쉽게 적응할 수 있습니다.
오리지널.htaccess
regex는 다음과 같은 파일에 문제를 일으킬 수 있습니다.json-1.3.js
해결 방법은 끝에 정확히 10자리가 있는 경우에만 다시 쓰는 것입니다.(10자리는 2001년 9월 9일부터 2286년 11월 20일까지의 모든 타임스탬프를 커버하기 때문입니다.)
먼저 .htaccess에서는 다음 개서 규칙을 사용합니다.
RewriteEngine on RewriteRule ^(.*).[d]{10}.(css js)$ $1.$2 [L]
이제 다음 PHP 함수를 작성합니다.
/**
*
Given a file, i.e. /css/base.css, replaces it with a string containing the
*
file's mtime, i.e. /css/base.1221534296.css.
*
*
@param $file
The file to be loaded.
Must be an absolute path (i.e.
*
starting with slash).
*/ function auto_version($file) {
if(strpos($file, '/') !== 0
!file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
return $file;
$mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
return preg_replace('{\.([^./]+)$}', ".$mtime.$1", $file); }
여기서 CSS를 포함하면 다음과 같이 변경합니다.
<link rel="stylesheet" href="/css/base.css" type="text/css" />
이를 위해:
<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />
이렇게 하면 링크태그를 다시 변경할 필요가 없어지고 사용자는 항상 최신 CSS를 볼 수 있습니다.브라우저는 CSS 파일을 캐시할 수 있지만 CSS를 변경하면 새로운 URL로 인식되므로 캐시된 복사본은 사용되지 않습니다.
이미지, favicon 및 JavaScript에서도 사용할 수 있습니다.기본적으로 동적으로 생성되지 않은 모든 것.
단순한 클라이언트 측 기술
일반적으로 캐싱은 양호합니다.따라서 웹 사이트를 개발할 때 문제를 직접 해결하는지, 실제 환경에서 캐시를 제어하는지 여부에 따라 몇 가지 방법이 있습니다.
웹 사이트의 일반 방문자는 사이트를 개발할 때와 같은 경험을 하지 못합니다.일반 방문자는 사이트를 방문하는 횟수가 적기 때문에(Google 또는 hi5 Networks가 아닌 한 한 한 달에 몇 번 정도만 방문), 파일을 캐시에 저장할 가능성이 적기 때문에 이 정도면 충분할 수 있습니다.
브라우저에 새 버전을 강제로 삽입할 경우 언제든지 요청에 쿼리 문자열을 추가하고 주요 변경 시 버전 번호를 업로드할 수 있습니다.
<script src="/myJavascript.js?version=4"></script>
그러면 모든 사용자가 새 파일을 받을 수 있습니다.브라우저가 파일의 URL을 보고 캐시에 복사본이 있는지 여부를 판단하기 때문에 작동합니다.서버가 쿼리 문자열로 작업을 수행하도록 설정되어 있지 않으면 무시되지만 브라우저에는 이름이 새 파일처럼 표시됩니다.
한편, 웹 사이트를 개발하는 경우, 개발 버전에 대한 변경 내용을 저장할 때마다 버전 번호를 변경할 필요가 없습니다.그것은 지루할 것이다.
따라서 사이트를 개발하는 동안 쿼리 문자열 매개 변수를 자동으로 생성하는 것이 좋습니다.
<!-- Development version: --> <script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"></script>');</script>
요청에 쿼리 문자열을 추가하는 것은 리소스를 버전화하는 데 좋은 방법이지만 단순한 웹 사이트에서는 이 작업이 필요하지 않을 수 있습니다.캐싱은 좋은 것입니다.
또한 브라우저가 파일을 캐시에 보관하는 데 반드시 인색한 것은 아닙니다.브라우저에는 이러한 종류의 정책이 있으며 보통 HTTP 사양에 명시된 규칙에 따라 작동합니다.브라우저가 서버에 요청을 할 때 응답의 일부는 Expires 헤더입니다. 이 날짜는 브라우저가 캐시에 보관해야 하는 기간을 알려줍니다.다음 번에 같은 파일에 대한 요청을 발견하면 브라우저는 해당 파일의 복사본이 캐시에 있는 것을 확인하고 만료 날짜를 참조하여 해당 파일의 사용 여부를 결정합니다.
믿거나 말거나 브라우저 캐시를 영속적으로 만드는 것은 서버입니다.서버 설정을 조정하거나 Expires 헤더를 변경할 수 있지만, 위에서 설명한 작은 기술을 사용하는 것이 훨씬 더 간단한 방법일 수 있습니다.캐싱이 좋기 때문에 일반적으로 해당 날짜를 먼 미래로 설정하고(‘Far-future Expires Header’) 위에서 설명한 기술을 사용하여 변경을 강제할 수 있습니다.
HTTP에 대한 자세한 정보나 이러한 요청이 이루어지는 방법에 관심이 있는 경우 Steve Souders의 “고성능 웹 사이트”가 좋은 책입니다.그것은 그 주제에 대한 아주 좋은 입문이다.
Google의 Apache용 mod_pagespeed 플러그인은 자동 버전을 수행합니다.정말 매끄럽다.
웹 서버(PHP, Ruby on Rails, Python, 정적 HTML 등)에서 HTML을 해석하고 CSS, JavaScript, 이미지 파일에 대한 링크를 ID 코드를 포함하도록 다시 씁니다.수정된 URL에 있는 파일을 매우 긴 캐시 제어로 제공합니다.파일이 변경되면 자동으로 URL이 변경되므로 브라우저는 파일을 다시 가져와야 합니다.기본적으로 코드를 변경하지 않고 작동합니다.나가는 길에도 암호를 최소화할 수 있습니다.
버전을 수동으로 변경하는 것이 아니라 실제 CSS 파일의 MD5 해시를 사용하는 것이 좋습니다.
그래서 당신의 URL은 다음과 같습니다.
http://mysite.com/css/[md5_hash_here]/style.css
개서 규칙을 사용하여 해시를 제거할 수도 있지만 URL이 같으면 파일이 변경되지 않으므로 캐시 정책을 “영원히 캐시”로 설정할 수 있다는 장점이 있습니다.
그런 다음 파일의 해시를 계산하고 태그를 업데이트하는 간단한 셸 스크립트를 작성할 수 있습니다(포함하기 위해 다른 파일로 이동하는 것이 좋습니다).
CSS가 변경될 때마다 이 스크립트를 실행하기만 하면 됩니다.브라우저는 파일이 변경되었을 때만 파일을 새로고침합니다.편집 후 실행 취소하면 방문자가 다시 다운로드하지 않기 위해 어떤 버전으로 돌아가야 하는지 쉽게 알 수 있습니다.
이 솔루션을 구현하기 위해 애쓰는 이유를 잘 모르겠습니다.
파일의 수정된 타임스탬프를 가져와 쿼리 문자열로 파일에 추가할 경우 필요한 작업만 하면 됩니다.
PHP에서는 다음과 같이 합니다.
<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">
filemtime()은 파일 수정 타임스탬프를 반환하는 PHP 함수입니다.