使用 Angular 10 部署后为客户端自动重新加载

Posted

技术标签:

【中文标题】使用 Angular 10 部署后为客户端自动重新加载【英文标题】:Auto reload for clients after deploy with Angular 10 【发布时间】:2021-04-11 01:40:21 【问题描述】:

目前,我的应用已经部署完毕,所有的js都有时间戳版本。现在,当我再次构建我的 Angular 应用程序时,js 将有一个新的时间戳版本。

有没有一种方法可以比较我的构建版本,如果不匹配,则允许用户从应用程序中注销?

【问题讨论】:

我想在博客blog.nodeswat.com/… 上做这样的事情但是在版本文件中创建哈希时出现问题。 这个问题是重复的,不值得 500 赏金。稍加努力,您会惊讶地发现已经有很多答案。例如 - ***.com/q/42411789/3503019 @RiteshMaharjan 是您的服务器仅提供静态文件,还是您可以添加一个端点来返回可用的最新版本? 【参考方案1】:

使用“@angular/service-worker”包的“SwUpdate”,您可以检查应用程序的当前版本和可用版本,并可以通过检查版本执行您想要执行的操作。

例子:

import  SwUpdate  from '@angular/service-worker';

constructor(private swUpdate: SwUpdate) 

//Here you can check the versions
this.swUpdate.available.subscribe((event) => 
   console.log('current version: ', event.current);
   console.log('available version: ', event.available);
   if (confirm('Software update avaialble.')) 
       this.swUpdate.activateUpdate().then(() => 
          //Perform your action here
          window.location.reload()
       );
   
);

【讨论】:

【参考方案2】:

虽然 Service Worker 动态工作,但这里可以使用更通用的解决方案。 @Amirhossein 提出了一种很好的实施方式,并且可以采用实用的实施方式。此外,无需为此目的调用任何 API 或制作 API。我们可以 ping 服务器以获取服务器中可用的最新index.html,并将其与客户端中的当前index.html 进行比较。

另一种工作方法

为 Angular 应用程序生成构建后,在 index.html 文件中添加以下支持。使用我在正文部分添加的脚本并替换实时 URL 而不是 example.com 并替换应用程序构建生成的最新 main-es5 javascript

<html>
    <head>
        <script src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
    </head>
    <body>
        <script>
            $.get("https://example.com/?v=" + Date.now(), data => 
                if (!(String(data).includes('main-es5.014e7f2ada629a9a485a.js'))) 
                    localStorage.clear();
                
            , 'text');
        </script>
    </body>
</html>

这是如何工作的?

脚本 ping 您的 URL 并获取当前的 index.html 文件并将该文件与当前使用的 main-es5 文件进行比较。

如果匹配,则用户正在运行您应用的最新版本。否则,用户没有使用最新版本的应用程序,用户可以根据使用的身份验证类型注销。 99% 的时间使用 localStorage、sessionStorage 或 cookie。这可以清除以删除用户数据。

根据要求,可以通过实现这些方法中的任何一种,让用户使用最新版本的应用程序登录。

是时候使用任何选项重新加载内容了:

    window.location.reload(true); deprecated 显示一个弹出窗口以通知用户有新版本可用。 要求用户使用说明强制重新加载网站。 如果您有基于 CloudFront 的环境,请使那里的缓存无效。

它是不是比 Service Worker / PWA 更好的方法?

不,老实说,服务人员是解决您的用例的最佳企业。但是,某些旧设备、旧 iPhone 和许多设备仍然不能无缝地使用 PWA 的概念。此外,某些 API 在使用 NFC、蓝牙等方面面临困难。在投入生产之前务必进行彻底的研究。

我可以阻止浏览器缓存我的 Angular 应用程序吗?

是的,可以通过多种方式实现。是服务器(字面意思是你)指示浏览器缓存和不缓存。在AWS CloudFront 中查看缓存突发/设置缓存标头的示例。根据您的托管服务提供商,可以设置缓存标头来指示浏览器。 Cache-ControlExpires 是这里的关键。

【讨论】:

@AlexGordon 希望这是一篇长篇文章,但可以在您的脑海中打开一些想法。 这似乎是在不使用 PWA 的情况下注销用户的好方法。【参考方案3】:

这里的关键词是 PWA 和 ServiceWorker。只需按照角度指南的说明进行操作即可:

https://angular.io/guide/service-worker-getting-started

https://angular.io/guide/service-worker-communications

【讨论】:

【参考方案4】:

与其他人的意见不同,这是一个很好的问题,我想提出一个新的解决方案来满足您的目的。

在我看来,不要在您的客户端脚本 (Angular) 中使用新的依赖项,因为这是一个特定于浏览器的问题,有时,客户端可能会有 ISP 捕捉。两者都可以防止客户端知道新资源(不同的哈希)。简单地说,您需要一个 helper 来检查是否存在新版本。那么,如果需要,您为什么不创建一个 API 来检查它,并在他接受后在客户端浏览器上执行硬重新加载

例如,您检查并发现有新版本可用,然后您会显示一个对话框,其中包含如下文本和一个接受按钮以执行硬重新加载:

有一个新版本,你想要吗? 变化是:blob blob blob

通过这种方式,您可以将当前版本号存储在服务器端,或者存储在一个 json 文件中。

【讨论】:

非常感谢您在这里的观点。我不清楚一件事。我理解您在间隔内 ping API 端点的想法。你是说如果我建立了新版本的 index,html 我仍然会提示在 contact.html 上的用户刷新吗?或者它会如何仅通知用户已更新的资源? 在 SPA 项目中,index.html 是我们处理必要资源的地方,因此在此处更新该文件是有意义的,即使客户端浏览其他页面也是如此。如果您的意思是我如何更新客户端浏览器上的某些(或一个)资源?答案是,这在 生产 环境中是不可行的,因为您不这样做与开发环境一样,可以完全控制客户端浏览器。 @AlexGordon 如果我理解你的问题,请告诉我。

以上是关于使用 Angular 10 部署后为客户端自动重新加载的主要内容,如果未能解决你的问题,请参考以下文章

Firebase AuthInstance.currentUser 成功重新加载后为空

在 Angular Material CDK 拖放中,如何防止项目随着元素移动而自动重新排列?

启动后为 Angular 6 项目获取“错误 TS1005,TS1109”

rsyslog客户端自动部署脚本,经测试使用正常

Angular环境配置

Angular:防止资产文件夹发生更改时自动重新编译