Bootstrap

前端自动检查更新,适用Vue任何版本项目,包服务端更后客户端更新

实现思路

  1. 请求当前项目根路径
  2. 提前文件中的标签路径
  3. 对比路径和刷新页面

按上思路不做优化项自动更新效率不足50%

  • 优化项
  • 剔除浏览器插件引入的JS包到项目里面,增加对比标签数量,和防止有浏览器插件用户无限刷新
  • 剔除 http 网路地址协议的JS标签路径,减少对比干扰,和其它BUG
  • 对比当前打开页面路径和请求回来的根页面的 JS 标签和路径,大大提高更新后的刷新率(100%更新刷新)
  • 页面切换后台时停止检查更新 (阻止无效的JS逻辑)

完整代码 复制即用

const _window = window as any;

/* 是否在弹框状态 */
let timeoutID: any = 0, isMessageBox = false;


const WithdrawLinks = async (html: string): Promise<string[]> => {
  /* 这段正则全局匹配可以放到外面去,注意lastIndex即可 */
  const scriptReg = /<script.*src=["'](?<src>[^"']+)/gm;
  const linkReg = /<link.*href=["'](?<href>[^"']+)/gm;
  let result: Array<string> = [], link: Array<string> = [], match: any;
  while ((match = scriptReg.exec(html))) {
    result.push(match.groups.src);
  }

  while ((match = linkReg.exec(html))) {
    link.push(match.groups.href);
  }

  const eliminate = <T>(result: string[]): string[] => {
    let filterList: string[] = [];
    filterList = result.filter((element) => !element.startsWith('chrome-extension://'));
    filterList = result.filter((element) => !element.match(/^http(s?):\/\/[^ ]+/g));
    return filterList
  }

  return [...eliminate(link), ...eliminate(result)];

}

// 检查更新
async function CheckForUpdates() {
  const HaulAwayHTML = await WithdrawLinks(await fetch('/').then(resp => resp.text()));
  const renderHTML = await WithdrawLinks(document.documentElement.innerHTML)
  let result = false;
  console.log(HaulAwayHTML, renderHTML);
  if (renderHTML.length !== HaulAwayHTML.length) {
    result = true;
  } else {
    for (let i = 0; i < HaulAwayHTML.length; i++) {
      if (renderHTML[i] !== HaulAwayHTML[i]) {
        result = true;
        break;
      }
    }
  }
  return result;
}


document.addEventListener("visibilitychange", function () {
  const status = document.visibilityState
  if (status === 'hidden') {
    timeoutID && clearTimeout(timeoutID);
    timeoutID = null;
  } else if (status === 'visible') {
    !isMessageBox && autoRefresh();
  }
});




// 调用即可
export const autoRefresh = async () => {
  timeoutID = setTimeout(async () => {
    const willUpdate = await CheckForUpdates();
    if (willUpdate) {
      clearTimeout(timeoutID);
      isMessageBox = true;
      const confirm: boolean = window.confirm('页面有更新,点击确定刷新页面?')
      if (confirm) { _window.location.reload(true); } else {
        isMessageBox = false;
        autoRefresh();
      }
    } else {
      autoRefresh();
    }
  }, 10000);
}

;