Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
AngularJS:stale UI试图加载新版本部署时不再存在的缓存破坏HTML文件_Angularjs_Asp.net Core_Caching_Single Page Application - Fatal编程技术网

AngularJS:stale UI试图加载新版本部署时不再存在的缓存破坏HTML文件

AngularJS:stale UI试图加载新版本部署时不再存在的缓存破坏HTML文件,angularjs,asp.net-core,caching,single-page-application,Angularjs,Asp.net Core,Caching,Single Page Application,我有一个angularjs/ui路由器应用程序。所有由框架懒散加载的html模板都被缓存,因此它们被命名为myTemplate.someHash.html,对这些模板的引用也在编译时更新 有时会出现的一个问题是,当用户使用应用程序时,我部署了一个新版本。事件顺序如下: 用户已打开一个页面,该页面上有一个指向状态Summary的链接。摘要状态使用名为Summary.HTML的HTML模板。但是,由于我们正在对HTML模板进行CacheBuster,这个文件实际上在用户浏览器中当前加载的应用程序版本

我有一个angularjs/ui路由器应用程序。所有由框架懒散加载的html模板都被缓存,因此它们被命名为
myTemplate.someHash.html
,对这些模板的引用也在编译时更新

有时会出现的一个问题是,当用户使用应用程序时,我部署了一个新版本。事件顺序如下:

  • 用户已打开一个页面,该页面上有一个指向状态Summary的链接。摘要状态使用名为
    Summary.HTML
    的HTML模板。但是,由于我们正在对HTML模板进行CacheBuster,这个文件实际上在用户浏览器中当前加载的应用程序版本中命名为
    summary.12345.HTML
  • 部署了一个新版本,其中包含对
    summary.html
    的一些更改,导致它得到一个新的散列,因此现在称为
    summary.98765.html
  • 用户点击链接,angular试图获取不再存在的
    summary.12345.html
    ,导致404
  • 有解决这个问题的好模式吗

    我最初的想法是在所有请求中附加一些HTTP头,类似于
    预期版本:999
    (其中999是在CI中生成的内部版本号),如果该版本不是服务器上运行的版本,则服务器将响应类似“410 Gone”的内容,在这种情况下,应用程序将要求用户刷新浏览器

    但这需要在服务器端进行一些工作,我也不确定如何将此逻辑注入到客户端的模板加载中

    此外,由于新版本通常每周部署几次(有时每天部署多次),而且大多数版本甚至不包含任何会以上述方式破坏SPA的更改,因此我不想强迫用户一直重新加载页面

    一种方法是,当请求产生404且响应包含指示您正在运行过时版本的SPA的标题时,仅显示“请刷新”消息吗


    或者有更简单的方法吗?

    我用下面的方法解决了这个问题

    我决定我不想让用户在每次部署新版本时都刷新他们的浏览器,因为很多版本只包含后端更改

    我只想让他们在部署了一个版本(自他们在浏览器中打开应用程序以来)后刷新,该版本包含以下内容之一的更改:

    • javascript应用程序(作为两个包提供),或
    • 任何一个加载的html模板
    所以我不得不引入UI版本的概念。我决定这个UI版本的定义应该是上面提到的html模板的所有文件名的SHA256散列(只是名称,因为这些文件名已经包含用于缓存破坏的散列),与两个js捆绑包的名称连接在一起(它们也是缓存破坏的)

    这是解决办法。 第一部分 我在我的CI管道中添加了一个步骤,在js应用程序被编译和缓存破坏之后,但在整个应用程序构建到Docker映像之前。此新生成步骤如下所示:

    const glob=require(“glob”);
    const crypto=require('crypto');
    常数fs=要求('fs');
    const jsPromise=新承诺(解析=>{
    glob(“./js/*.js”,{},函数(err,文件){
    如果(!err){
    解决(文件);
    }
    });
    });
    const htmlPromise=新承诺(解析=>{
    glob(“./app/***.html”,{},函数(err,文件){
    如果(!err){
    解决(文件);
    }
    });
    });
    Promise.all([jsPromise,htmlPromise])。然后([files1,files2])=>{
    const allFiles=files1.concat(files2);
    fs.writeFileSync(
    “./ui version.env”,
    `UI_VERSION=${crypto.createHash('sha256').update(allFiles.sort().join()).digest('hex')}`
    );
    });
    
    如您所见,它将其写入名为
    ui version.env
    的文件中。然后,我使用
    env_file
    命令在docker-compose.yml中引用该文件。这样,后端应用程序现在可以知道当前的UI版本。后端现在在HTTP端点
    GET/ui version
    上提供这些数据

    第二部分 加载前端应用程序时,它会调用上述端点并将当前UI版本存储在内存中

    部署新版本后,将向所有连接的前端应用程序发送websocket消息,并发出通知,以检查它们是否仍在运行最新的UI版本。他们通过请求上面提到的新端点并将结果与加载时保存的版本进行比较来实现这一点

    当发送websocket消息时,如果用户的计算机处于睡眠模式或没有internet连接,该怎么办?

    我已经在SPA中设置了事件侦听器,当计算机从睡眠模式恢复或恢复internet连接时,该侦听器将关闭。因此,这些事件中的任何一个现在都将触发UI版本检查

    老实说,我对这个解决方案不是特别兴奋。有很多活动部件。如果有人能提供一个更简单的解决方案,那就太好了。但不幸的是,我怀疑自己是否能得到任何好的答案