8

前后台分离的WEB应用项目上线时,会因浏览器的自动缓存策略而发生一些错误。比如项目的前后台同时由V1.0升级为了V1.1。此时由于浏览器缓存,用户在打开项目地址时仍然使用了缓存中的V1.0的代码。这便会发生V1.0的前台调用V1.1的后台的BUG。

本文以angular为例,阐述一种前台更新后项目浏览器自动刷新的解决方案。

本文示例代码地址:https://stackblitz.com/edit/angular-2k4qy2

基本思路

想实现前台如果更新后便重新强制浏览器刷新的功能,则需要加入一个版本号来进行控制。在系统启动时读取前台的版本号,然后与服务器上的版本号进行比对。如果版本号相同,则说明浏览器当前加载的前台与服务器提供的前台的版本是统一的,则什么也不做;如果版本号不同,则说明浏览器当前加载的版本与服务器提供的版本不统一,则强制浏览进行刷新以清除缓存带来的影响。

image.png

加入版本号

在项目的src/assets文件夹中新建config.json,并加入以下信息以记录当前应用的版本号:

{
    "version":"1.0.0"
}
线上演示的需求,我们必须将其建立在src/assets中。实际的生产项目中,可以将其按需建立在src文件夹下的任意位置。

获取版本号

若要对版本号进行比对,则需要获取两个版本号:第1个为WEB应用运行的版本号,第2个为服务器提供的WEB应用的版本号。

当这两个版本号不统一时,则说明当前运行的版本与服务器提供的版本不一致,便应进行强制刷新。

运行应用的版本号

export class AppComponent implements OnInit {
  private config: {version: string}; ➊
  ngOnInit() {
    this.config = require('./../assets/config.json'); ➋
    console.log(this.config.version);
  }
}
  • ➊ 声明config类型
  • ➋ 使用require加载config.json文件,并将其值赋予this.config

服务器提供应用的版本号

export class AppComponent implements OnInit {
  constructor(private httpClient: HttpClient) {
  }
  private config: {version: string};
  ngOnInit() {
    this.config = require('./../assets/config.json');
    console.log(this.config.version);
    this.httpClient.get<{version: string}>('/assets/config.json')
      .subscribe(config => {
        console.log(config);
      }); ➊
  }
}
  • ➊ 获取config.json并打印

值得注意的是,在请求后台的config.json时,浏览器最终调用的可能也是缓存的数据,这时候就需要在请求的header上做点文章,强制浏览器在请求config.json时弃用缓存:

  ngOnInit() {
    this.config = require("./../assets/config.json");
    console.log(this.config.version);

    const headers = new HttpHeaders()
      .set('Cache-Control', 'no-cache')
      .set('Pragma', 'no-cache'); ➊
      
    this.httpClient
      .get<{ version: string }>("/assets/config.json", {headers➋})
      .subscribe(config => {
        console.log(config);
      });
  }
  • ➊ 新建不使用缓存的header
  • ➋ 在请求中加入header信息,此请求则不使用浏览器缓存

强制刷新当前页面

location中提供了reload(true)方法来进行页面的强制刷新:

      .subscribe(config => {
        if (config.version !== this.config.version) {
          location.reload(true); ➊
        }
      });
  • ➊ 强制刷新页面

但不知何种原因,该方法被标识为弃用。简单的查了一些资料,有人说这个方法可能在后面的版本中被浏览器弃用,于是使用以下代码进行页面刷新操作:

        if (config.version !== this.config.version) {
          this.httpClient
            .get(""➊, { headers➋, responseType: "text"➌ })
            .subscribe(() => location.reload()➍);
        }
  • ➊ 重新拉取首页
  • ➋ 禁用缓存
  • ➌ 响应类型为text
  • ➍ 此时再进行reload操作,则浏览器即使调用了缓存,该缓存也是➊中拉取的服务器中最新的前台应用了。

总结

在前台后分离的应用中,自动的进行缓存的判断当有助于客服人员大幅的减轻压力,增强用户对系统的粘稠度。本文使用暴露前台的版本文件并进行比对的方法,来判断是否要强制刷新浏览器缓存;再结合httpClient发请对loading页的请求,以达到间接的强制刷新浏览器缓存的目的。


潘杰
3.1k 声望238 粉丝