Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular doesn't update page with cache enabled

Tags:

I made an angular website which contains an "add" and a "delete" form to manipulate data on a table on the same page.

When I test it locally or with Chrome Dev Console (disabled cache), when I add a new item or delete one, the table refreshes itself automatically. When I test it on the production server (IIS Server) of my client, it works only with the Chrome Dev Console opened. Otherwise, they have to use CTRL+F5 to refresh the cache and show the changes on the page.

This is the code on components:

  addProduct() {     this._productsService.addProduct(this.addFormProductItem)       .subscribe(v => {         this._productsService.getProducts().subscribe(            products => {this.products = products, this.onChangeTable(this.config)}       );     });     this.addmodalWindow.hide();     return;   }      onChangeTable(config: any, page: any = {     page: this.page,     itemsPerPage: this.itemsPerPage   }): any {     if (config.filtering) {       Object.assign(this.config.filtering, config.filtering);     }     if (config.sorting) {       Object.assign(this.config.sorting, config.sorting);     }     this.ng2TableData = this.products;     this.length = this.ng2TableData.length;     let filteredData = this.changeFilter(this.ng2TableData, this.config);     let sortedData = this.changeSort(filteredData, this.config);     this.rows = page && config.paging ? this.changePage(page, sortedData) : sortedData;     this.length = sortedData.length;   } 

My guess is that it is either related to some server configuration or to the webpack code. However, I am not familiar with the latter and I just left it as it was on the starting package I used.

I created a gist with the webpack since it is a long file

Edit 1: After some extra research, I tried to add the following on a web.config file on the root folder of the app.

<caching enabled="false" enableKernelCache="false">       <profiles>          <add extension=".css" policy="DontCache" kernelCachePolicy="DontCache" />          <add extension=".html" policy="DontCache" kernelCachePolicy="DontCache" />          <add extension=".js" policy="DontCache" kernelCachePolicy="DontCache" />       </profiles> </caching> 

However, I still have the same behavior. Adding an item with Dev Console closed, it doesn't update the table. But if I have the dev console opened and disabled the cache, then it updates it without the need of a refresh.

Edit 2: Working on Incognito Window doesn't fix the problem.

Edit 3: Adding meta tags on index.html doesn't fix the problem, again.

<meta http-equiv="Cache-control" content="no-cache, no-store, must-revalidate"> <meta http-equiv="Pragma" content="no-cache"> 

Edit 4:

  getProducts() {     return this._http.get(this.API + '/products/all')       .map((response: Response) => <Product[]>response.json().products);   }    addProduct(product:Product) {     if ( this._loggedInGuard.isLoggedIn() ) {       let token = localStorage.getItem('my.token');       let body = JSON.stringify(product);       let headers = new Headers(          { 'Content-Type': 'application/json',          'Authorization': 'Bearer ' + token});       return this._http       .post(this.API + "/products/store", body, {headers: headers} )       .map(res => res.json())       .catch(this._responseService.catchBadResponse)       .do(() => this._responseService.success('Success. You added a product!'));      }     } 

Edit 5

The only solution I can find is to reload the window every time I do an update on data with location.reload(true). But again, this works only on Firefox and not on Chrome. And I will not accept that you have to abandon the only reason of having a Single Page App to make this works.

like image 934
Tasos Avatar asked Sep 05 '17 12:09

Tasos


1 Answers

There are specific reasons that none of the things that you've tried have fixed things.

First of all, using the <caching> element in web.config does not instruct the browser on how to cache the response. It is used to configure how the IIS server caches the response so that it might be re-used in future requests. Here is the documentation that explains that.

Next, your <meta> tags. Normally, cache control is done by actual http headers. While you can use <meta> tags to set headers that are not specified at all in your http response header, they will NOT override http headers that are already being set. IIS has default values for caching in the response headers, your <meta> tags will not actually do anything. <meta> tags are really only reliably useful when you're loading over a file:/// url.

In order to reliably achieve what you're trying to do, you need to actually get the server to send the cache-control headers that you want to use. This can vary depending on what browsers you're trying to support, but since you're using angular, I might assume that you're supporting modern browsers, which is simple. The following will disable caching for ALL static files in your website, which probably isn't exactly what you want but might serve as a guide.

<?xml version="1.0" encoding="UTF-8"?> <configuration>   <location path=".">     <system.webServer>       <staticContent>         <clientCache cacheControlMode="DisableCache" />       </staticContent>     </system.webServer>   </location> </configuration> 

However, the first thing you should be doing is examining the current response headers that IIS is sending you! This can be done easily using the Chrome developers tools. If you are seeing a Cache-Control: header in the response, this will confirm my reasoning about why your <meta> tags aren't working.

If you're generating the HTML for your angular application not with a static .html file but instead are generating it using ASP.NET, your best bet is to add code into your controller that sets the cache header.

Response.Cache.SetCacheability(HttpCacheability.NoCache); 

If you want to support much older or broken browsers, there are other resources out there that describe what extra headers you will need to add, which again can be done using web.config or ASP.NET code. I just want to re-iterate: If you're still having problems sure that you are viewing the response headers being sent by the server.

like image 188
Avi Cherry Avatar answered Sep 29 '22 20:09

Avi Cherry