【问题标题】:AngularJS browser cache issuesAngularJS 浏览器缓存问题
【发布时间】:2015-08-05 07:46:54
【问题描述】:

早上好,我在生产环境中有一个 Web 应用程序。用户每天都在使用它,当我发布更新并且用户返回 Web 应用程序时,他会查看旧版本的 Web 应用程序。他需要刷新浏览器才能加载新版本。我怎么解决这个问题?每次发布更新(每周 3-4 次)时,我都无法告诉数百名用户刷新页面。

【问题讨论】:

    标签: angularjs caching


    【解决方案1】:

    经典的缓存问题。除非另有说明(由网络服务器),否则浏览器将根据文件名缓存资产。因此,当它看到具有相同名称的相同脚本/样式/图像时,它将304 并提供缓存版本。有几种方法可以解决这个问题,您可以:

    配置网络服务器告诉浏览器不要缓存文件。这显然是低效的,因为用户将不得不一次又一次地下载相同的文件。

    在文件名后追加查询字符串参数如my-angular-code.js?x=123,同样效率低下。

    指纹您的资产。这在 Rails 的Asset Pipeline 文档中得到了很好的解释。有几种方法可以实现这一点,grunt tasksgulp tasks 也可用于此。本质上是只有在内容发生变化时才更改文件名的过程,迫使浏览器将其视为新文件。

    【讨论】:

    • 这看起来很有希望。需要尝试一下。
    • @juco 为什么将查询字符串附加到文件名效率低下?
    • @AnilVangari 我猜测第一个选项效率低下的原因相同:浏览器将始终发送一个新的文件请求(如果查询字符串是动态的)。
    • 如何生成像 '/js/{$release_id}/my-angular-code.js' 这样的资源 url,其中 '{$release_id}' 是版本的唯一 id ?跨度>
    • 我不认为查询字符串效率低下。如果它一直在变化,但如果你这样做了。 ?version=2.5.1 并在更新发生时更新版本应该没有问题。
    【解决方案2】:

    一个简单的解决方案是将表示时间戳或会话 ID 的查询字符串添加到您的文件中。

    例如,在我们的 spring 应用程序中,我们只需使用:

    <script src="js/angular/lib/app.js?r=<%= session.getId()%>"></script>
    

    您也可以在特定于服务器的实施中实施相同的解决方案。

    【讨论】:

    • 如果我知道我需要更改“index.html”并在文件的查询字符串上添加时间戳。那么这是一个服务器端处理任务吗? (我还发现了一些关于在包含文件中附加“版本”号的帖子)
    • 是的。对于您加载的每个资源,在资源 URL 的末尾添加一个非静态的查询字符串 [例如:会话 ID 或时间戳]。
    • 我怎样才能自动化这个任务?我有大约 80 个资源(javascript 文件和部分视图)
    • 如果您询问 Ajax 调用,您可以开发一种通用方法来进行所有 ajax 调用,然后在每个 url 的末尾附加一个查询字符串。对于静态服务器资源,您没有任何自动方式来执行此操作。
    • 谢谢我解决了 addint 时间戳,每次我向 Web 应用程序发布更新时都会替换它
    【解决方案3】:

    如果您使用的是 HTML5,那么您可以使用Application Cache。它会自动检查更新,你可以提示用户刷新缓存。

    这里有一些很好的使用教程:

    A Beginner's Guide to Using the Application Cache

    Using the application cache

    Let's take this offline(离线网络应用)

    【讨论】:

      【解决方案4】:

      第一步是了解服务器端正在发生的事情。了解和configure Cache-Control and Etag。虽然您可以使用查询字符串参数,但file fingerprinting is a better technique 因为代理服务器将被允许缓存文件。

      这个想法是您将可以更改的文档(如果您有一个 Angular 应用程序,这很可能只是您的index.html)设置为no-cache,并积极缓存该文档引用的资源。当你发布一个新版本时,你的资源都会被重命名,当请求进来时,一切都会按预期工作。

      我在我的 Angular 应用程序中使用 grunt-rev。效果很好。

      【讨论】:

        【解决方案5】:

        第一步是获取时间戳并将时间戳作为 .html 扩展名的 URL 中的查询参数传递。

        在每次加载 html 内容时,由于时间戳附加到 URL,它将使用不同的路由呈现。

        示例:

        var date = new Date().getTime().toString();
        app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider){
        }])
        $stateProvider.state('app', {
            abstract: true,
            url: '/app',
            cache: false,
            templateUrl: 'views/app.html'**+'?t='+ date**
          })
        .state('app.dashboard', {
            url: '/dashboard',
            cache: false,
            controller: 'DashboardCtrl as showCase',
            templateUrl: 'components/dashboard/dashboard.view.html'**+'?t=' + date** ,
          })
        

        【讨论】:

        • 在这一行 `templateUrl: 'views/app.html'**+'?t='+ date**` 通配符的意义何在?
        猜你喜欢
        • 1970-01-01
        • 2011-10-14
        • 2011-08-18
        • 1970-01-01
        • 2017-08-23
        • 2015-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多