跳转到内容

页面自动检测更新

刀刀

1/8/2025

0 字

0 分钟

每隔一段时间去监测是否是最新的版本。实现步骤为:

  1. 使用 fetch 请求首页为纯文本,获取 html 中的 js 文件
  2. 前端工程化下,对应的 js 文件会绑定文件指纹,只要有变动,文件指纹(也就是 hash 值)也会发生变动,表示当前有新版本

文件指纹代码如下所示:

js
fetch('/').then(resp => resp.text()).then(res=>console.log(res))

具体效果以 B站 为例,效果如下:

xiaoguo

因此可以封装一下相应的方法函数,首先获取最新页面中的 script 链接,代码如下:

js
let lastSrcs // 上一次获取到的 script 地址

const scriptReg = /\<script.*src=["'](?<src>[^"']+)/gm

async function extractNewScripts() {
  // 避免缓存
  const html = await fetch('/?_timestamp=' + Date.now()).then((resp) => resp.text())
  
  // 通过正则把首页js地址保存出来
  scriptReg.lastIndex = 0
  let result = []
  let match
  // 把所有对应js文件名称保存到数组内,最后返回
  while((match = scriptReg.exec(html))) {
    result.push(match.groups.src)
  }
  return result
}

然后调用上方函数,拿到所有 JS 访问地址,并且保存到全局变量内。然后比较旧的地址与新的地址是否一致,不一致则返回 true 表示需要更新。代码如下:

js
async function needUpdate() {
  const newScripts = await extractNewScripts()
  // 如果没有值则是第一次,不需要更新,直接保存值
  if(!lastSrcs) {
    lastSrcs = newScripts
    return false
  }
  let result = false
  // 如果需要更新,result改为true
  if(lastSrcs.length !== newScripts.length) {
    result = true
  }
  for(let i = 0; i < lastSrcs.length; i++) {
    if(lastSrcs[i] !== newScripts[i]) {
      result = true
      break
    }
  }
  lastSrcs = newScripts
  return result
}

调用上方的方法查看是否需要更新,如果需要则显示对应的提示。每隔一段时间调用一次,代码如下:

js
const DURATION = 2000
function autoRefresh() {
  setTimeout(async () => {
    const willUpdate = await needUpdate()
    if(willUpdate) {
      const result = confirm('页面需要更新')
      if(result) location.reload()
    }
    autoRefresh()
  }, DURATION)
}

autoRefresh()