【问题标题】:How to disable caching of single page application HTML file served through IIS?如何禁用通过 IIS 提供的单页应用程序 HTML 文件的缓存?
【发布时间】:2014-12-23 09:58:37
【问题描述】:

我有一个通过 IIS 提供服务的单页应用程序 (angular-js)。如何防止缓存 HTML 文件?该解决方案需要通过更改 index.html 或 web.config 中的内容来实现,因为无法通过管理控制台访问 IIS。

我目前正在研究的一些选项是:

IIS 是 .NET 框架 4 的 7.5 版

【问题讨论】:

    标签: asp.net angularjs caching iis single-page-application


    【解决方案1】:

    在提供您的 html 文件时,您可以附加一个随机查询字符串。即使文件在浏览器缓存中,这也会阻止浏览器使用旧版本。

    /index.html?rnd=timestamp
    

    另一个选项是在 IIS 级别添加无缓存设置。这会在响应中添加 Cache-Control: no-cache,告诉浏览器不要缓存文件。它从 IIS 7 开始工作。

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <!-- Note the use of the 'location' tag to specify which 
           folder this applies to-->
      <location path="index.html">
        <system.webServer>
          <staticContent>
            <clientCache cacheControlMode="DisableCache" />
          </staticContent>
        </system.webServer>
      </location>
    </configuration>
    

    【讨论】:

    • 关于在 URL 中添加时间戳 - 是的,这可行,但我认为这更像是一种临时破解,而不是解决方案。我不相信任何有信誉的 SPA 解决方案都使用这种方法。
    • 不要忘记您的 ng 路由、css 和 javascript。您执行此操作的方式是 web.config for index.html。 ?v=1 对于其他所有内容,例如main.css?v=1.
    • 大多数情况下,像 index.html 这样的登陆页面不是由应用内代码请求的,而是由最终用户请求的,他们只需在浏览器中指定地址,不会附加随机时间戳?所以“另一种选择”是要走的路??
    【解决方案2】:

    将以下内容添加到 web.config 解决方案中适用于 Chrome、IE、Firefox 和 Safari:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    
      <location path="index.html">
        <system.webServer>
          <httpProtocol>
            <customHeaders>
              <add name="Cache-Control" value="no-cache" />
            </customHeaders>
          </httpProtocol>
        </system.webServer>
      </location>
    
    </configuration>
    

    这将确保在请求 index.html 时将 Cache-Control 标头设置为 no-cache

    【讨论】:

    • 我认为这仅在点击直接包含 index.html 的 url 时才有效。SPA 中的所有请求都有虚拟 url,并且不映射到真实的位置路径。可以用它做什么?
    • @MichailMichailidis 对于 SPA,您可能有一个规则将您的网址重写为“/”?如果您也添加该路径怎么办?
    • 虽然这个答案在技术上是准确的,但我认为值得指出的是 Cache-Control: no-cache 不会禁用缓存,而是强制客户端检查源服务器。因此,它与etag 标头或可能不可靠的last-modifed 标头协同工作,但它不会彻底禁用缓存。来自 no-cache 的 MDN:“在使用缓存副本之前,缓存必须与源服务器检查以进行验证。”换句话说,如果服务器没有返回 304,浏览器可能仍然使用缓存副本。
    • 为了解决@MichailMichailidis 的问题,请确保您的全面重写规则为&lt;action type="Rewrite" url="/index.html" /&gt; 或查看this link 以获取完整的Web.config
    【解决方案3】:

    对于 .NET Core,我使用了以下内容。

            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = context =>
                {                   
                    if (context.File.Name == "index.html" ) {
                        context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
                        context.Context.Response.Headers.Add("Expires", "-1");
                    }
                }
            });
    

    感谢How to disable browser cache in ASP.NET core rc2?

    【讨论】:

    • 我对 React 不是很熟悉(只是想解决我们的缓存问题),但是对我来说,在调试的时候,在上面的if 语句上有一个断点,这个断点没有命中index.html。我尝试将代码放在app.UseStaticFilesapp.UseSpaStaticFiles 中。第二个是favicon.icomanifest.json,位于与index.html 相同的文件夹中。有什么想法吗?
    • @Kjell Rilbe,如果没有为index.html 命中断点,请在浏览器控制台中验证它是从服务器请求的,而不是浏览器缓存。如果浏览器正在缓存,那么您需要解决以前没有缓存控制标头的index.html 文件的情况,因此浏览器不知道服务器的更改。目前我不记得如何解决这个问题(将无用的查询字符串附加到路径,手动清除浏览器缓存一次可能有助于调试)。祝你好运。
    • 谢谢,我会再检查一次(我想我已经做过了,但要确保)。断点只被命中两次,这就是我提到的文件,尽管浏览器实际上似乎获取了许多其他资源。页面index.html 可能是作为默认文档/根 URL 获取的,没有指定路径或文件,这就是为什么我在if 上放置一个断点,以查看context.File.name 在该场景中实际出现的内容。但是……没什么……
    【解决方案4】:
      <meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0">
    

    【讨论】:

    • 该标头仅适用于 index.html 文件还是也适用于其中包含的所有内容? (css, js, 图片,...)
    • 我认为只适用于 index.html
    【解决方案5】:

    SPA 的主要前提是从不缓存 index.html

    MDN recommendations to prevent caching 之后,我们必须添加 Cache-Control HTTP 标头和 no-store, max-age=0 资源的值(在我们的例子中是 index.html 文件)。

    为什么 no-store 而不是 no-cache

    使用 no-store,资源不会存储在任何地方。使用no-cache,资源可能会被存储,但在使用前需要通过存储与服务器进行验证。

    为什么max-age=0

    强制清除预先存在的有效缓存响应(no-store 不会)。

    在 IIS 中,我们可以通过 web.config 文件管理我们的应用缓存配置。这是一个完整的 web.config 文件(必须位于我们应用程序的根目录中),其中包括 index.html 文件的缓存配置以及路由配置(我已经添加了 SPA 路由和 HTTP 重定向到 HTTPS 作为示例):

    <configuration>
      <location path="index.html">
        <system.webServer>
          <httpProtocol>
            <customHeaders>
              <add name="Cache-Control" value="no-store, max-age=0" />
            </customHeaders>
          </httpProtocol>
        </system.webServer>
      </location>
      <system.webServer>
        <rewrite>
          <rules>
            <rule name="HTTP to HTTPS" enabled="true" stopProcessing="true">
              <match url="(.*)" />
              <conditions>
                <add input="{HTTPS}" pattern="^OFF$" />
              </conditions>
              <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" />
            </rule>
            <rule name="SPA Routes" enabled="true" stopProcessing="true">
              <match url=".*" />
              <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
              </conditions>
              <action type="Rewrite" url="/index.html" />
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    </configuration>
    

    【讨论】:

      【解决方案6】:

      这些答案都不适合我,因为正如@MichailMichailidis 所提到的,“SPA 中的所有请求都有虚拟 url,并且不映射到真实的位置路径”,所以 location path从不匹配index.html

      我在这个blog post 中找到了解决方案,它链接到this answer。两者都向您展示了如何使用重写模块的outboundRules 根据条件更改cache-control 响应标头。

      所以这就是我的 web.config 在这个配置之后的样子:

      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <system.webServer>
          <rewrite>
            <outboundRules>
              <rule name="RewriteCacheControlForIndexHtmlFile" 
                preCondition="IsIndexHtmlFile">
                <match serverVariable="RESPONSE_Cache_Control" pattern=".*" />
                <action type="Rewrite" value="max-age=0" />
              </rule>
              <preConditions>
                <preCondition name="IsIndexHtmlFile">
                  <add input="{REQUEST_FILENAME}" pattern="index.html" />
                </preCondition>
              </preConditions>
            </outboundRules>
      ...
      

      【讨论】:

        猜你喜欢
        • 2017-05-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 1970-01-01
        • 2010-12-03
        • 2017-05-15
        • 1970-01-01
        • 2019-12-27
        相关资源
        最近更新 更多