단일 페이지 앱에서 브라우저 캐시 처리


27

단일 페이지 앱의 웹 브라우저 캐시를 올바르게 처리하는 방법을 찾으려고합니다.

SPA를 구현하는 여러 HTML, JS 및 CSS 파일과 SPA가 소비하는 JSON 데이터가 상당히 일반적인 디자인입니다. 업데이트를 푸시 할 때 문제가 발생합니다. 사이트의 정적 부분과 JSON을 동시에 생성하는 코드를 업데이트하지만 클라이언트 브라우저에는 종종 정적 부분이 캐시되어 있으므로 오래된 코드는 새 데이터를 처리하려고 시도합니다. (변경 사항에 따라) 문제가 발생할 수 있습니다. (특히 IE는 다시 확인하지 않고 캐시 된 JS를 사용하는 데 Chrome 또는 Firefox보다 더 공격적인 것으로 보입니다.)

이것을 처리하는 가장 좋은 방법은 무엇입니까?

  1. 내 JSON 변경 사항이 이전 버전과 호환되는지 확인하고 브라우저 캐시가 적절한 시간 내에 만료된다고 가정하십시오.
  2. 정적 JS와 JSON 모두에 일종의 버전 번호를 포함시킨 다음 window.location.reload(true);일치하지 않으면 실행 합니다.
  3. 브라우저가 사이트를로드하기 위해 몇 번의 추가 왕복 여행을 의미하더라도 브라우저가 항상 모든로드에서 모든 리소스를 다시 확인하도록하기 위해 적절한 헤더 조합 ( must-revalidate또는 no-cache기타 : 소스 가이 방법에 따라 다름 )을 파악하십시오.
  4. 캐시 제어를 마이크로 관리하고 헤더를 만료하여 업데이트를 푸시 할 때 정적 컨텐츠가 만료되도록합니다.
  5. 다른 것?

1
동료 가 환경이 좋지 않은 경우 ( iOS 기침 ) 내장 웹 브라우저 컨트롤에서 # 3 및 # 4가 예기치 않게 실패한다고 들었습니다 . # 1과 # 2는 앱 수준의 선택이 될 수 있지만 여전히 다른 리소스 또는 부분 리소스로드에 대해 캐시 문제를 일으킬 수 있습니다 (?). 프로덕션 용 코드에서 안정적으로 작동하는 것으로 확인 된 유일한 것은 yoururl.html? <SomeTimeStamp>를 가져 오는 것입니다. 보너스 : 전체 웹 앱을 파일로 롤링하여로드가 원자 적으로 성공하거나 실패하도록합니다. 단점 : 로컬 링크에서 가장 잘 작동합니다. 귀하의 마일리지가 다를 수 있습니다. 행운을 빕니다!
J Trana

2
버전 번호 또는 타임 스탬프를 리소스의 URL 매개 변수로 사용하려면 +1하십시오.
9000

답변:


14

캐시 버스 팅 솔루션 이 필요합니다 . 캐시 무효화의 역할은 다음과 같습니다.

  1. 내용에 따라 리소스의 이름을 고유 한 이름으로 바꿉니다.
  2. 해당 자원에 대한 모든 참조를 업데이트하십시오.

Grunt 기반 프로젝트에서는 grunt-rev 를 사용하여 새로 고쳐야하는 모든 파일에 내용에 따라 고유 한 이름을 부여하는 것이 일반적입니다.

JSON 파일이 Javascript에서 해당 파일에 대한 참조와 함께 캐시 버스트 파일 이름을 갖도록하려면 클라이언트는 항상 Javascript에 필요한 JSON 파일을로드합니다.

해시 기반 파일 이름 지정의 이점은 변경되지 않은 파일은 캐시 버스 팅 후에 동일한 파일 이름을 가져 와서 브라우저가 변경되지 않은 경우에도 캐시 된 컨텐츠를 안전하게 사용할 수 있다는 것입니다.

분명히 이것은 프로젝트 프로덕션 빌드의 일부로 자동화하려는 종류이므로 파일 이름 및 참조 변경을 수동으로 추적 할 필요가 없습니다.


2
이탤릭체로 된 "캐시 버스 팅 (cache busting)"비트에 대해 +1. 실제로이 항목을 생산적으로 구글로 검색 할 수있는 문을 엽니 다.
Zak Kus 12'12

@ 테드 Percival-yeoman 프레임 워크가 이것을 사용하지만 문제가 있습니다. 새 빌드를 릴리스하면 브라우저에 이전 파일에 대한 참조로 캐시 된 index.html이있을 수 있으며 브라우저에 오류가 발생합니다. 이 문제를 어떻게 해결해야합니까? (A.) 모든 이전 파일 이름을 새 파일 이름으로 심볼릭 링크하십시오 (이 작동합니다) (B.) index.html에 캐시 없음 헤더를 추가하십시오 (그러나 항상 존중됩니다). 기본 항목을 검색하십시오 (예 : 12345.main.js-> main.js)
timh

5

당신은 사용할 수 있습니다 if-modified-since + last-modified또는 if-none-match + etag적절한과 함께 헤더 cache-control헤더입니다. ( 브라우저 버그 가있을 수 있지만 최근 브라우저에서 관리 할 수있는 것은 없습니다.)

파일이 정적 인 if-modified-since경우 잘 구성된 HTTP 서버로 자동으로 수행 할 수 있으므로을 사용하는 것이 좋습니다 . 파일이 마지막 다운로드 이후 수정되지 않은 경우 304를 다시 보내야합니다.

나는 당신의 # 1과 # 2가 장기적으로 작동하지 않을 것이라고 생각합니다. # 3 또는 # 4가 작동 할 수 있습니다. # 3은 더 간단하지만이 문제를 한 번만 처리하는 방법을 배워야합니다. 따라서 내가 당신이라면 # 4를 시도하지만 솔루션은 고객이 사용하는 브라우저에 따라 다를 수 있습니다 ... 예를 들어 IE8에는 ajax 캐시 등을 업데이트하여 문제가 있습니다 ...


2

SPA에 Java Servlet Filter를 포함 할 수있는 경우 다음과 같이 작동합니다. CorrectBrowserCacheHandlerFilter.java

기본적으로 브라우저가 정적 파일을 요청하면 서버는 모든 요청을 동일한 요청으로 리디렉션하지만 해시 쿼리 매개 변수 ( ?v=azErT예 : 대상 정적 파일의 내용에 따라 다름)를 사용합니다.

이렇게하면 브라우저는 index.html예를 들어 선언 된 정적 파일을 캐시하지 않지만 (항상을 수신하기 때문에 302 Moved Temporarily) 해시 버전 (서버가 응답 200)으로 캐시 된 파일 만 캐시합니다 . 따라서 브라우저 캐시는 해시 버전의 정적 파일에 효율적으로 사용됩니다.

면책 조항 : 나는의 저자입니다 CorrectBrowserCacheHandlerFilter.java.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.