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 จะข้ามแคชสำหรับคำขอปกติ คำขอ ajax ที่ทำจากเชิงมุมสำหรับng-include| ng-view| templateUrlไม่ได้รับการจัดการโดยทางลัดนี้
André Werlang

2
คุณไม่สามารถขอให้ผู้ใช้ปลายทางทั้งหมดกด Ctrl + Shift + R เมื่อเยี่ยมชมเว็บไซต์ดังนั้นคำตอบของคำถามนี้สำหรับกรณีที่ไม่ใช่การพัฒนาคืออะไร "สำหรับฉันนี่เป็นปัญหาด้านไคลเอนต์ที่ไม่ควรแก้ไขโดยใช้แฮ็กบนเซิร์ฟเวอร์เหมือนคำแนะนำด้านล่าง" - ฉันไม่เห็นด้วยคุณไม่สามารถควบคุมลูกค้าในสภาพแวดล้อมเว็บดังนั้นการแก้ไขสำหรับการผลิต จะต้องมีการขับเคลื่อนแอปพลิเคชัน ด้วยเหตุนี้ฉันจึงยอมรับ: $ rootScope. $ on ('$ viewContentLoaded', function () {$ templateCache.removeAll ();});
Robert Christian

คำตอบ:


200

เพื่อการพัฒนาคุณสามารถปิดการใช้งานแคชเบราว์เซอร์ - ใน Chrome Dev Tools ที่ด้านล่างขวาคลิกที่เฟืองและทำเครื่องหมายที่ตัวเลือก

ปิดใช้งานแคช (ในขณะที่ DevTools เปิดอยู่)

อัปเดต: ใน Firefox มีตัวเลือกเดียวกันในดีบักเกอร์ -> การตั้งค่า -> มาตราขั้นสูง (เลือกรุ่น 33)

อัปเดต 2: แม้ว่าตัวเลือกนี้จะปรากฏใน Firefox รายงานบางอย่างมันไม่ทำงาน ฉันแนะนำให้ใช้ firebug และทำตามคำตอบ hadaytullah


7
นี่ควรจะเป็นคำตอบที่ยอมรับได้เพราะมันไม่จำเป็นต้องมีการเปลี่ยนรหัสและเป็นมากกว่าจุดที่ร้องขอของ OP แน่นอนว่าคุณต้องการให้แอปที่ผลิตแคชคำขอดังนั้นการทำตามที่คนข้างต้นแนะนำในขณะที่มีความหมายดีก็สามารถพิสูจน์ได้ว่ามีปัญหาหากรหัสเหลืออยู่ในแอปที่ใช้งานจริง
Aaron Wagner

คำแนะนำสำหรับเบราว์เซอร์อื่นเช่น Firefox?
Lereveme

ใน Firefox: ดีบักเกอร์> การตั้งค่า (เฟือง) มีตัวเลือกเดียวกัน
LukeSolar

5
สิ่งนี้ไม่ทำงานใน Firefox แม้ว่าจะปิดใช้งานแคชและกล่องเครื่องมือเปิดอยู่เทมเพลตจะยังคงถูกแคชอยู่
Patrick J Collins

4
การแคชส่งผลกระทบต่อการผลิตด้วยหรือไม่ จะเกิดอะไรขึ้นถ้าฉันส่งไฟล์เว็บใหม่ไปยังเซิร์ฟเวอร์สิ่งที่ป้องกันไม่ให้มีการร้องขอจากไคลเอนต์ที่ใช้งานจริงจากการโหลดเวอร์ชันแคชที่เผยแพร่ล่วงหน้า
meffect

111

สร้างคำตอบของ @ Valentyn ต่อไปนี้เป็นวิธีหนึ่งในการล้างแคชโดยอัตโนมัติทุกครั้งที่มีการเปลี่ยนแปลงเนื้อหาในมุมมอง ng:

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

@ user252690 อาจต้องตรวจสอบให้แน่ใจว่าไม่ได้ส่งแม่แบบ html ด้วยส่วนหัวแคช ดูที่นี่และ ที่นี่เพื่อรับการแก้ไขที่เป็นไปได้
Chris Foster

30
คำเตือนเล็กน้อย: การล้าง $ templateCache จริง ๆ แล้วอาจมีผลกระทบที่ไม่ได้ตั้งใจ ตัวอย่างเช่นUI Bootstrapเพิ่มส่วนเริ่มต้นโดยตรงไปยัง $ templateCache ในระหว่างการเริ่มต้นและในภายหลังคาดว่าพวกเขาจะอยู่ที่นั่น
Strille

@Stille ฉันกำลังพยายามใช้โมดัล -ui-bootstrap Modal ไม่พบป๊อปอัป เพราะ $ templateCache.removeAll (); แก้ไขมันได้หรือไม่
Mukun

4
@Mukun: ไม่มีวิธีแก้ไขอย่างง่าย ๆ ที่ฉันเห็นนอกเหนือจากไม่ใช้ removeAll () แต่เพียงแค่ใช้ remove () เพื่อลบคีย์ที่คุณต้องการล้าง คุณจะต้องมีการทำบัญชีบางอย่างเพื่อทราบว่าต้องลบคีย์ใด
Strille

มีวิธีใดบ้างในการล้างแคชเฉพาะแคชมุมมอง UI ที่ระบุ
Gayan

37

ตามที่กล่าวไว้ในคำตอบอื่น ๆที่นี่และที่นี่แคชสามารถล้างได้โดยใช้:

$templateCache.removeAll();

อย่างไรก็ตามตามคำแนะนำของgatoatigradoในความคิดเห็นสิ่งนี้จะปรากฏขึ้นก็ต่อเมื่อแม่แบบ html ถูกให้บริการโดยไม่มีส่วนหัวแคชใด ๆ

ดังนั้นนี่เหมาะสำหรับฉัน:

ในเชิงมุม:

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

คุณอาจจะเพิ่มส่วนหัวของแคชได้หลายวิธี แต่นี่เป็นวิธีแก้ปัญหาที่เหมาะกับฉัน

หากใช้IISให้เพิ่มไปยังเว็บของคุณ 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

โซลูชันสำหรับ Firefox (33.1.1) โดยใช้ Firebug (22.0.6)

  1. เครื่องมือ> เครื่องมือบนเว็บ> Firebug> เปิด Firebug
  2. ในมุมมอง Firebug ให้ไปที่มุมมอง "Net"
  3. สัญลักษณ์เมนูแบบเลื่อนลงจะปรากฏขึ้นถัดจาก "Net" (ชื่อเรื่องของมุมมอง)
  4. เลือก "Disable Browser Cache" จากเมนูแบบเลื่อนลง

พยายามใช้ Firebug (2.0.11) และ Firefox (38.0.1) บนเครื่อง mac แต่ไม่สามารถใช้งานได้
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) ได้หรือไม่ upvoted!
JackLeEmmerdeur

การใช้งาน .value('DEBUG', trueเหมือนกันกับที่คุณทำ$rootScopeแต่ไม่มีความยุ่งเหยิง :) คุณสามารถฉีดDEBUGเข้าไปในคอนโทรลเลอร์และสอบถามเป็นบริการปกติได้ในภายหลัง
diosney

คุณสามารถขยายรหัสต้นทางในคำตอบของคุณเพื่อรวมสิ่งต่าง.value(...)ๆ ได้หรือไม่ถ้ามันไม่ซับซ้อนเกินไป? ฉันคิดว่าแนวคิดที่อยู่เบื้องหลังนั้นเป็นแนวปฏิบัติที่ดีที่สุดที่ไม่รู้จักสำหรับฉัน
JackLeEmmerdeur

1
วิธีนี้มีประโยชน์มากเมื่อทำงานกับ Ionic มันจะช่วยฉันประหยัดเวลาได้มากเพราะมันช่วยให้ตับโหลดมีประโยชน์อีกครั้ง ขอบคุณตัน!
ajuser

11

อย่างที่คนอื่นพูดการเอาชนะการแคชอย่างสมบูรณ์เพื่อผู้พัฒนาสามารถทำได้อย่างง่ายดายโดยไม่ต้องเปลี่ยนรหัส: ใช้การตั้งค่าเบราว์เซอร์หรือปลั๊กอิน ด้านนอกของ dev เพื่อกำจัดการแคชเทมเพลต Angular ของเทมเพลตที่ยึดตามเส้นทางเอา URL เทมเพลตออกจากแคชระหว่าง $ routeChangeStart (หรือ $ stateChangeStart สำหรับ UI Router) ดังที่ Shayan แสดง อย่างไรก็ตามนั่นไม่ได้ส่งผลกระทบต่อการแคชของแม่แบบที่โหลดโดย 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 คุณหมายถึงว่าเป็นผลข้างเคียงที่ดีถูกต้อง - หมายถึงสิ่งที่คุณตั้งใจจะมีให้ 'hotfix' หรือไม่ขอบคุณ
jamie

1
ฉันปล่อยให้รหัสนี้อยู่ในสภาพที่ดีแม้ว่าเราจะโทรกลับไปตามความยาวของการป้องกันแคชถึง 10 นาที ดังนั้นในการใช้งานทุกๆ 10 นาทีผู้ใช้จะทำการโหลดเทมเพลต html ใหม่ สำหรับแอพ biz ของฉันซึ่งเป็นค่าใช้จ่ายที่ยอมรับได้ในการเพิ่มความสามารถในการเทมเพลตฮอตแพทช์ แต่เห็นได้ชัดว่ามันจะทำให้ประสิทธิภาพการทำงานของแอพบางประเภทแย่ลง ... โชคไม่ดีที่การแคช HTTP นั้นแพ้เช่นกัน แต่ฉันไม่เห็นวิธีที่จะเอาชนะการแคชเทมเพลต Angular อย่างชาญฉลาดโดยไม่ต้องเอาชนะ etc ของ etag ด้วยเช่นกัน การแคชเท็มเพลต IMO เชิงมุมนั้นไม่สามารถกำหนดค่าได้เพียงพอ
bradw2k

1
+1 ฉันมีความคิดเหมือนกัน แต่ฉันดักจับเฉพาะ localhost เท่านั้น คุณสามารถดูการใช้งาน interceptor ของฉันได้ที่นี่: 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


ทางเลือกที่ดีกว่าคือการใช้ปลั๊กอินเช่น gulp-angular-templatecache เพื่อลงทะเบียนเทมเพลต js เชิงมุมใน $ templateCache ควรใช้พร้อมกับ 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เพื่อเปิดเครื่องมือสำหรับนักพัฒนา จากนั้นทรัพยากร > จัดเก็บแคช > รีเฟรชแคช

ป้อนคำอธิบายรูปภาพที่นี่

ฉันชอบตัวเลือกนี้เพราะฉันไม่ต้องปิดการใช้งานแคชเหมือนในคำตอบอื่น ๆ


ใน Chrome v. 54.0.2840.99 ในเดือนพฤศจิกายน 2559 ฉันพบสิ่งนี้ในแท็บชื่อ Application.rather มากกว่า Resources
StackOverflowUser

0

ไม่มีวิธีแก้ปัญหาเพื่อป้องกันการแคชของเบราว์เซอร์ / พร็อกซีเนื่องจากคุณไม่สามารถควบคุมได้

อีกวิธีหนึ่งในการบังคับให้เนื้อหาสดแก่ผู้ใช้ของคุณเพื่อเปลี่ยนชื่อไฟล์ HTML! เหมือนhttps://www.npmjs.com/package/grunt-filerevสำหรับสินทรัพย์


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.