AngularJS는 dev 컴퓨터에서 부분 캐싱을 비활성화합니다.


210

AngularJS에서 부분을 캐싱하는 데 문제가 있습니다.

내 HTML 페이지에는 다음이 있습니다.

<body>
 <div ng-view></div>
<body>

내 부분이로드되는 곳.

부분적으로 HTML 코드를 변경해도 브라우저는 여전히 오래된 데이터를로드합니다.

해결 방법이 있습니까?


4
간단한 참고 사항 : Flask 응용 프로그램이 다시 보내는 캐시 제어 헤더와 관련이있는 문제가 있습니다. 나는 추가하여 문제를 주위에있어 app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)내에 flask_app.py. (다른 웹 서버에도 비슷한 것이 있다고 생각합니다).
gatoatigrado

4
크롬을 사용하는 경우 Ctrl+Shift+R(즉, 하드 리로드) 어떤 캐싱 메커니즘을 사용하더라도 크롬은이를 무시하고 모든 스크립트, 스타일 시트 등을 다시 가져옵니다.
snajahi

4
ctrl + shift + R은 Chrome에서 작동하지 않지만 개발자 도구의 "네트워크"탭에서 "캐시 비활성화"를 클릭하면 완벽하게 작동합니다. 나에게 이것은 클라이언트 측 문제이며 아래의 많은 제안과 같이 서버에서 해킹을 사용하여 해결해서는 안됩니다. "문제"가있는 클라이언트에서 수정해야합니다. 서버에서 수정하고 수정하지 않는 경우 프로덕션에 부정적인 영향을 줄 수 있습니다.
Ant Kutschera

8
ctrl + shift + R은 일반 요청에 대해 캐시를 무시합니다. 각도에서 만든 아약스 요청 ng-include| ng-view| templateUrl이 바로 가기로 처리되지 않습니다
André Werlang

2
사이트를 방문 할 때 모든 최종 사용자에게 Ctrl + Shift + R을 요청할 수는 없습니다. 따라서 비 개발 사례의 경우이 질문에 대한 답변은 무엇입니까? "나에게 이것은 아래의 많은 제안과 같이 서버에서 해킹을 사용하여 해결해서는 안되는 클라이언트 측 문제입니다."-동의하지 않습니다. 웹 환경에서 클라이언트를 제어 할 수 없으므로 프로덕션에 대한 해결책입니다. 응용 프로그램 중심이어야합니다. 이런 이유로 나는 $ rootScope. $ on ( '$ viewContentLoaded', function () {$ templateCache.removeAll ();});
Robert Christian

답변:


200

개발을 위해 브라우저 캐시를 비활성화 할 수도 있습니다-오른쪽 하단의 Chrome 개발자 도구에서 톱니 바퀴를 클릭하고 옵션을 선택하십시오

캐시 비활성화 (DevTools가 열려있는 동안)

업데이트 : Firefox의 디버거-> 설정-> 고급 섹션에 동일한 옵션이 있습니다 (버전 33 확인)

업데이트 2 :이 옵션은 Firefox에 표시되지만 일부 보고서에서는 작동하지 않습니다. 방화범을 사용하고 hadaytullah 답변을 따르는 것이 좋습니다.


7
이것은 코드 변경이 필요하지 않으며 OP 요청의 요점에 가깝기 때문에 허용되는 답변이어야합니다. 물론 프로덕션 앱이 요청을 캐시하기를 원하므로 위의 사람들이 제안한 것을 수행하는 것은 의미가 있지만 프로덕션 앱에 코드가 남아 있으면 문제가 될 수 있습니다.
Aaron Wagner

Firefox와 같은 다른 브라우저에 대한 제안 사항이 있습니까?
Lereveme

Firefox : 디버거> 설정 (기어)에는 동일한 옵션이 있습니다.
LukeSolar

5
Firefox에서는 작동하지 않습니다. 캐시가 비활성화되어 있고 도구 상자가 열려 있어도 템플릿은 여전히 ​​캐시됩니다.
Patrick J Collins

4
캐싱도 생산에 영향을 미칩니 까? 새 웹 파일을 서버로 푸시하면 프로덕션 클라이언트의 후속 요청이 사전 게시 된 캐시 된 버전을로드하지 못하게하는 이유는 무엇입니까?
22:39에

111

@Valentyn의 대답을 약간 바탕으로 ng-view 컨텐츠가 변경 될 때마다 항상 캐시를 자동으로 지우는 한 가지 방법이 있습니다.

myApp.run(function($rootScope, $templateCache) {
   $rootScope.$on('$viewContentLoaded', function() {
      $templateCache.removeAll();
   });
});

@ user252690 html 템플릿이 캐시 헤더와 함께 전송되지 않았는지 확인해야 할 수도 있습니다. 참조 여기여기에 가능한 수정을 위해
크리스 포스터에게

30
약간의 경고 : $ templateCache를 비우면 실제로 의도하지 않은 결과가 발생할 수 있습니다. 예를 들어, UI Bootstrap 은 초기화 중에 기본 부분을 $ templateCache에 직접 추가하고 나중에 기본 부분을 기대합니다.
Strille

@Strille 나는 angular-ui-bootstrap Modal을 사용하려고했습니다. 팝업이 보이지 않았습니다. 왜냐하면 $ templateCache.removeAll (); 그것에 대한 어떤 수정?
Mukun

4
@ 무쿤 : removeAll ()을 사용하지 않는 것 외에는 내가 보는 방식을 쉽게 고칠 수는 없지만 remove ()를 사용하여 지우는 키를 삭제하십시오. 어떤 키를 삭제할지 알기 위해서는 일종의 부기가 필요합니다.
Strille

특정 UI보기 캐시에 대해서만 캐시를 지우는 방법이 있습니까?
Gayan

37

다른 답변 herehere 에서 언급했듯이 캐시는 다음을 사용하여 지울 수 있습니다.

$templateCache.removeAll();

그러나 주석 에서 gatoatigrado 가 제안한 것처럼 html 템플릿이 캐시 헤더없이 제공 된 경우에만 작동하는 것으로 보입니다.

그래서 이것은 나를 위해 작동합니다 :

각도로 :

app.run(['$templateCache', function ( $templateCache ) {
    $templateCache.removeAll(); }]);

다양한 방법으로 캐시 헤더를 추가 할 수 있지만 여기에 도움이되는 몇 가지 솔루션이 있습니다.

를 사용하는 경우 IIS이것을 web.config에 추가하십시오.

<location path="scripts/app/views">
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="DisableCache" />
    </staticContent>
  </system.webServer>
</location>

Nginx를 사용하는 경우 이것을 구성에 추가 할 수 있습니다 :

location ^~ /scripts/app/views/ {
    expires -1;   
}

편집하다

방금 질문에 dev기계가 언급되었다는 것을 깨달았 지만 이것이 여전히 누군가를 도울 수 있기를 바랍니다 ...


2
예, 이것이 원래의 질문에 직접 대답하지는 않지만 실제로 이것은 실제 웹 사이트에서 캐싱 문제를 해결하는 데 도움이되었습니다.
Andre

31

전체 페이지를 다시로드하지 않고 템플릿 캐싱에 사용 된 캐시에 대해 이야기하는 경우 다음과 같은 방법으로 캐시를 비울 수 있습니다.

.controller('mainCtrl', function($scope, $templateCache) {
  $scope.clearCache = function() { 
    $templateCache.removeAll();
  }
});

그리고 마크 업에서 :

<button ng-click='clearCache()'>Clear cache</button>

이 버튼을 누르면 캐시가 지워집니다.


22

Firebug (22.0.6)를 사용하는 Firefox (33.1.1) 용 솔루션

  1. 도구> 웹 도구> Firebug> Open Firebug.
  2. Firebug보기에서 "Net"보기로 이동하십시오.
  3. 드롭 다운 메뉴 기호가 "Net"(보기 제목) 옆에 나타납니다.
  4. 드롭 다운 메뉴에서 "브라우저 캐시 비활성화"를 선택하십시오.

Mac의 Firebug (2.0.11) 및 Firefox (38.0.1)에서 시도했지만 작동하지 않았습니다.
paullb

19

이 스 니펫은 템플릿 캐싱을 제거하는 데 도움이되었습니다.

app.run(function($rootScope, $templateCache) {
    $rootScope.$on('$routeChangeStart', function(event, next, current) {
        if (typeof(current) !== 'undefined'){
            $templateCache.remove(current.templateUrl);
        }
    });
});

다음 스 니펫의 세부 사항은이 링크에서 찾을 수 있습니다. http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/


nitpick 그러나 현재는 언제 객체가 아닌가? 그것이 어디에도 있는지 확실하지는 않지만if (!current) { return; }
Nate-Wilkins

이것은 Angular의 라우트 기반 템플릿 캐싱을 무효화하지만 포함되지 않은 부분은 캐싱하지 않습니다.
bradw2k

16

다른 솔루션 중 어느 것도 나를 위해 일하지 않았기 때문에 모든 가능성을 다루기 위해 이것을 게시하고 있습니다 (각도 부트 스트랩 템플릿 종속성으로 인해 오류가 발생했습니다).

특정 템플릿을 개발 / 디버깅하는 동안 다음과 같이 경로에 타임 스탬프를 포함시켜 항상 새로 고칠 수 있습니다.

       $modal.open({
          // TODO: Only while dev/debug. Remove later.
          templateUrl: 'core/admin/organizations/modal-selector/modal-selector.html?nd=' + Date.now(),
          controller : function ($scope, $modalInstance) {
            $scope.ok = function () {
              $modalInstance.close();
            };
          }
        });

변수 의 마지막 ?nd=' + Date.now()에 유의하십시오 templateUrl.


1
나중에 .value('DEBUG', true)해당 회선을 사용하도록 설정하거나 해제 할 수 있습니다 .
diosney

1
내 솔루션은 내 메인 모듈의 초기화 단계 .run(function($rootScope) { $rootScope.DEBUG = true; ...내에서 다음 지시문 내에서 다음을 사용하여 지시문 내에서 $ rootScope를 .directive('filter', ['$rootScope', function($rootScope)...반환하고 객체 속성을 반환했습니다 templateUrl: '/app/components/filter/filter-template.html' + ($rootScope.DEBUG ? '?n=' + Date.now() : ''). .value ( 'DEBUG', true) 접근법을 정교하게 만들 수 있습니까? 공감!
JackLeEmmerdeur

의 사용법은 .value('DEBUG', true당신이했던 것과 동일 $rootScope하지만 혼란스럽지 않습니다 :) 나중에 DEBUG컨트롤러에 주입 하고 정상적인 서비스로 쿼리 할 수 ​​있습니다.
diosney

소스 코드가 .value(...)너무 복잡하지 않은 경우 소스 코드를 확장하여 답을 포함시킬 수 있습니까? 나는 뒤에있는 개념이 나에게 알려진 각도 모범 사례라고 생각합니다.
JackLeEmmerdeur

1
이 솔루션은 Ionic으로 작업 할 때 매우 유용합니다. livereload를 다시 유용하게 사용하면 시간이 많이 절약됩니다. 정말 감사합니다!
ajuser

11

다른 사람들이 말했듯이, 브라우저 설정이나 플러그인을 사용하면 코드를 변경하지 않고도 개발 목적으로 캐싱을 완전히 물리 칠 수 있습니다. 개발자 외부에서 경로 기반 템플릿의 Angular 템플릿 캐싱을 막으려면 Shayan이 보여준 것처럼 $ routeChangeStart (또는 UI 라우터의 경우 $ stateChangeStart) 동안 캐시에서 템플릿 URL을 제거하십시오. 그러나 ng-include가로드 한 템플릿의 캐싱에는 영향을 미치지 않습니다. 이러한 템플릿은 라우터를 통해로드되지 않기 때문입니다.

프로덕션에서 ng-include로로드 된 템플릿을 포함하여 모든 템플릿에 핫픽스를 적용하고 사용자가 전체 페이지를 다시로드하지 않고도 브라우저에서 핫픽스를 빠르게받을 수 있기를 원했습니다. 또한 템플릿에 대한 HTTP 캐싱을 물리 치는 것에 대해 걱정하지 않습니다. 해결책은 앱이 만드는 모든 HTTP 요청을 가로 채고 내 앱의 .html 템플릿이 아닌 요청을 무시한 다음 매 분마다 변경되는 템플릿 URL에 매개 변수를 추가하는 것입니다. 경로 확인은 앱 템플릿 경로에 따라 다릅니다. 다른 간격을 얻으려면 매개 변수에 대한 수학을 변경하거나 캐싱하지 않도록 %를 완전히 제거하십시오.

// this defeats Angular's $templateCache on a 1-minute interval
// as a side-effect it also defeats HTTP (browser) caching
angular.module('myApp').config(function($httpProvider, ...) {
    $httpProvider.interceptors.push(function() {
        return {
            'request': function(config) {
                config.url = getTimeVersionedUrl(config.url);
                return config;
            }
        };
    });

    function getTimeVersionedUrl(url) {
        // only do for html templates of this app
        // NOTE: the path to test for is app dependent!
        if (!url || url.indexOf('a/app/') < 0 || url.indexOf('.html') < 0) return url;
        // create a URL param that changes every minute
        // and add it intelligently to the template's previous url
        var param = 'v=' + ~~(Date.now() / 60000) % 10000; // 4 unique digits every minute
        if (url.indexOf('?') > 0) {
            if (url.indexOf('v=') > 0) return url.replace(/v=[0-9](4)/, param);
            return url + '&' + param;
        }
        return url + '?' + param;
    }

귀하의 솔루션에 관심이 있습니다.이 코드를 양호하게 유지 하시겠습니까? 또는 변경 후 일정 기간 동안 유지 하시겠습니까? 이유-성능에 관심이 있습니다. 또한 부작용으로 인해 HTTP가 실패한다고 언급했습니다. 당신은 그것이 올바른 부작용이라는 것을 의미합니다. 즉, '핫픽스'를 가지기 위해 의도 한 것입니까? Thx
jamie

1
캐시 버스 팅의 길이를 10 분으로 되돌 렸지만이 코드는 그대로 두었습니다. 따라서 10 분마다 사용자는 새로운 HTML 템플릿을 다시로드하게됩니다. 내 biz 앱의 경우 템플릿을 핫 패치하는 기능을 얻는 데 드는 비용이지만, 일부 앱의 경우 성능이 너무 나빠질 수 있습니다. ... HTTP 캐싱도 패배하지만 불행히도 etag 등을 물리 치지 않고 Angular 템플릿 캐싱을 지능적으로 물리 칠 수있는 방법은 없습니다. IMO Angular 템플릿 캐싱은 충분히 구성 할 수 없습니다.
bradw2k

1
+1 나는 같은 생각을 가지고 있었지만 localhost 만 차단했습니다. 여기 인터셉터의 내 구현을 확인할 수 있습니다 overengineer.net/...
joshcomley

@joshcomley localhost에서 캐싱을 해제해야하는 경우 모든 캐싱을 해제하는 브라우저 플러그인을 사용하지 않겠습니까?
bradw2k

@ bradw2k이 방법으로 나는 캐시되고 캐시되지 않은 것을 완전히 제어 할 수있어 개발에 유용 할 수 있습니다. 또한 모든 브라우저에서 테스트하지만 모든 브라우저에 필요한 작업을 수행하는 확장 기능이있는 것은 아닙니다. 캐싱이 비활성화되어 있는지 여부를 알려주는 개발 사이트의 지표도 있습니다. 때로는 브라우저에서 잠시 동안 비활성화하고 테스트하기를 원하기 때문입니다.
joshcomley

8

UI 라우터를 사용하는 경우 데코레이터를 사용하고 $ templateFactory 서비스를 업데이트하고 쿼리 문자열 매개 변수를 templateUrl에 추가하면 브라우저는 항상 서버에서 새 템플리트를로드합니다.

function configureTemplateFactory($provide) {
    // Set a suffix outside the decorator function 
    var cacheBust = Date.now().toString();

    function templateFactoryDecorator($delegate) {
        var fromUrl = angular.bind($delegate, $delegate.fromUrl);
        $delegate.fromUrl = function (url, params) {
            if (url !== null && angular.isDefined(url) && angular.isString(url)) {
                url += (url.indexOf("?") === -1 ? "?" : "&");
                url += "v=" + cacheBust;
            }

            return fromUrl(url, params);
        };

        return $delegate;
    }

    $provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}

app.config(['$provide', configureTemplateFactory]);

$ routeProvider에서 "when"메소드를 장식하여 동일한 결과를 얻을 수 있다고 확신합니다.


훨씬 더 좋은 대안은 gulp-angular-templatecache와 같은 플러그인을 사용하여 $ templateCache에 각도 js 템플릿을 등록하는 것입니다. gulp-rev와 함께 사용해야합니다. 템플릿이 변경 될 때마다 개정 번호가 다른 새 JavaScript 파일이 작성되며 캐싱은 문제가되지 않습니다.
Aman Mahajan

3

HTTP 인터셉터 메소드가 꽤 잘 작동하고 추가 유연성 및 제어가 가능하다는 것을 알았습니다. 또한 릴리스 해시를 버스터 변수로 사용하여 각 프로덕션 릴리스에 대해 캐시 버스트 할 수 있습니다.

다음은 dev 캐시 버스 팅 방법을 사용하는 모습 Date입니다.

app.factory('cachebustInjector', function(conf) {   
    var cachebustInjector = {
        request: function(config) {    
            // new timestamp will be appended to each new partial .html request to prevent caching in a dev environment               
            var buster = new Date().getTime();

            if (config.url.indexOf('static/angular_templates') > -1) {
                config.url += ['?v=', buster].join('');
            }
            return config;
        }
    };
    return cachebustInjector;
});

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('cachebustInjector');
}]);

1

다음은 Chrome의 다른 옵션입니다.

히트 F12열린 개발자 도구. 그런 다음 자원 > 캐시 스토리지 > 캐시 새로 고침 .

여기에 이미지 설명을 입력하십시오

다른 답변과 마찬가지로 캐시를 비활성화 할 필요가 없기 때문에이 옵션이 마음에 듭니다.


2016 년 11 월 Chrome v. 54.0.2840.99에서 리소스가 아닌 Application.r이라는 탭에서이를 발견했습니다.
StackOverflowUser

0

브라우저 / 프록시 캐싱을 제어 할 수 없으므로 브라우저 / 프록시 캐싱을 방지 할 수있는 솔루션이 없습니다.

새로운 컨텐츠를 사용자에게 강제로 HTML 파일의 이름을 바꾸는 다른 방법! 정확히 https://www.npmjs.com/package/grunt-filerev 가 자산을 처리하는 것과 같습니다 .


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