Angular 不会在启用缓存的情况下更新页面

标签 angular caching iis webpack

我制作了一个 Angular 网站,其中包含一个“添加”和一个“删除”表单来操作同一页面上表格上的数据。

当我在本地或使用 Chrome 开发控制台(禁用缓存)进行测试时,当我添加新项目或删除项目时,表格会自动刷新。当我在客户端的生产服务器(IIS 服务器)上对其进行测试时,它仅适用于打开的 Chrome 开发控制台。否则,他们必须使用 CTRL+F5 来刷新缓存并在页面上显示更改。

这是组件的代码:

  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;
  }

我的猜测是它要么与某些服务器配置有关,要么与 webpack 代码有关。但是,我对后者不熟悉,我只是将它保留在我使用的起始包中。

我创建了 a gist with the webpack因为它是一个长文件

编辑 1: 经过一些额外的研究,我尝试在应用程序根文件夹的 web.config 文件中添加以下内容。

<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>

但是,我仍然有同样的行为。在 Dev Console 关闭的情况下添加项目,它不会更新表。但是,如果我打开了开发控制台并禁用了缓存,那么它会在不需要刷新的情况下更新它。

编辑 2:使用隐身窗口无法解决问题。

编辑 3:在 index.html 上添加元标记并不能再次解决问题。

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

编辑 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!'));

    }  
  }

编辑5

我能找到的唯一解决方案是每次使用 location.reload(true) 更新数据时重新加载窗口。但同样,这仅适用于 Firefox 而不适用于 Chrome。而且我不会接受您必须放弃拥有单页应用程序才能使其有效的唯一原因。

最佳答案

有一些特定的原因导致您尝试过的所有事情都没有解决问题。

首先,使用 <caching> web.config 中的元素不指示浏览器 如何缓存响应。它用于配置 IIS 服务器 缓存响应的方式,以便它可以在未来的请求中重新使用。 Here是对此进行解释的文档。

接下来,您的 <meta>标签。通常,缓存控制是由实际的 http header 完成的。虽然您可以使用 <meta>标记来设置在您的 http 响应 header 中根本没有指定的 header ,它们将NOT 覆盖已经设置的 http header 。 IIS 在响应 header 中有用于缓存的默认值,您的 <meta>标签实际上不会做任何事情。 <meta>标签真的只有在你加载 file:/// 时才有用。网址。

为了可靠地实现您正在尝试做的事情,您实际上需要让服务器发送您要使用的缓存控制 header 。这可能会因您尝试支持的浏览器而异,但由于您使用的是 Angular ,我可能会假设您支持现代浏览器,这很简单。以下内容将禁用您网站中所有静态文件的缓存,这可能不是您想要的,但可以作为指导。

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

但是,您应该做的第一件事是检查 IIS 发送给您的当前响应 header !这可以使用 Chrome 开发者工具轻松完成。如果您看到 Cache-Control:响应中的 header ,这将证实我关于为什么你的 <meta> 的推理标签不起作用。

如果您不是使用静态 .html 文件而是使用 ASP.NET 为 Angular 应用程序生成 HTML,那么最好的办法是将代码添加到设置缓存 header 的 Controller 中。

Response.Cache.SetCacheability(HttpCacheability.NoCache);

如果您想支持更旧或损坏的浏览器,还有其他资源可以描述您需要添加哪些额外的 header ,这同样可以使用 web.config 或 ASP.NET 代码来完成。我只想重申:如果您仍然遇到问题,请确保您正在查看服务器发送的响应 header 。

关于Angular 不会在启用缓存的情况下更新页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46054957/

相关文章:

javascript - 无法使用 updateNg1Component() 在 Angular 2 应用程序中使用 Angular 1 指令

c# - OutputCache 序列化并发请求

hibernate - Grails应用的tomcat服务器如何实现缓存自动刷新

iphone - 如何将 xml 结果传递给核心数据对象

javascript - 将 TCP 监听器或 HTTP 监听器与 IIS 一起使用

angular - rxjs 条件嵌套可观察对象

angular - 使用 Flask 为 Angular 前端提供服务不会渲染图像

javascript - Angular 8 组件更改和 ngOnInit 调用

html - 利用浏览器缓存

windows - 在 Windows/NTFS 上,可以将符号链接(symbolic link)移动到另一台计算机吗?