返回 blog
2021年10月11日
2 分钟阅读

根据网站版本号判断是否更新网页

目的

  1. 当网页更新功能时可以实时告诉网站用户有新版本可用
  2. 当修复bug时可以让用户及时刷新页面

可行性

目测两个网站已有此功能,可以实现

实现方法

我将采用方案1实现,需后端配合。

实现过程

  1. 后端同事配合实现接口过滤器,每个接口都在 response-header 中返回 version 。这里需注意,非标准的响应头需要设置在 Access-Control-Expose-Headers
httpServletResponse.setHeader("Access-Control-Expose-Headers", "version");
httpServletResponse.setHeader("version", version);
  1. 后端同事提供一个可以修改version的接口,前端通过调用这个接口来设置version
  2. 前端在接口response拦截器中获取版本号(此处用的 umi-request)
// 网站版本号
let versionCache: string | null = null;
let updateVersion: boolean = true;

request.interceptors.response.use(
  (response) => {
    const version = response.headers.get('Version') || response.headers.get('version');

    if (versionCache && version && versionCache !== version && updateVersion) {
      // 提示用户刷新页面
      updateVersion = false;
      showUpdateVersionModal();
    }

    if (!versionCache) {
      versionCache = version;
    }

    return response;
  },
  { global: true },
);
  1. 判断前后两次版本不一致时弹出弹窗
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import { Modal } from 'antd';

type UpdateVersionModalType = {
  show: (dom?: HTMLElement | null) => void;
  instance: HTMLElement | null;
  hide: () => void;
  parent: HTMLElement | null;
} & React.FC<{
  visible?: boolean;
}>;

const UpdateVersionModal: UpdateVersionModalType = (props) => {
  const { visible: visibleProp = false } = props;

  const [visible, setVisible] = useState<boolean>(false);

  useEffect(() => {
    setVisible(visibleProp);
  }, [visibleProp]);

  const onCancel = () => {
    setVisible(false);
  };

  const onOk = () => {
    window.location.reload();
  };

  return (
    <Modal
      visible={visible}
      title="更新"
      closable={false}
      onCancel={onCancel}
      onOk={onOk}
      okText="立即刷新"
      cancelText="取消"
      maskClosable={false}
    >
      <p>检测到版本更新刷新页面即可查看内容不刷新可能会造成部分内容出错</p>
    </Modal>
  );
};

UpdateVersionModal.instance = null;
UpdateVersionModal.parent = null;

UpdateVersionModal.show = function (parentDom?: HTMLElement | null) {
  if (!UpdateVersionModal.instance) {
    UpdateVersionModal.instance = document.createElement('div');
    UpdateVersionModal.parent = parentDom || document.body;
    UpdateVersionModal.parent.appendChild(UpdateVersionModal.instance);
  }

  ReactDOM.render(<UpdateVersionModal visible />, UpdateVersionModal.instance);
};

UpdateVersionModal.hide = function () {
  const { instance } = UpdateVersionModal;
  if (instance) {
    ReactDOM.render(<UpdateVersionModal visible={false} />, UpdateVersionModal.instance);
  }
};

const showUpdateVersionModal = UpdateVersionModal.show;
const hideUpdateVersionModal = UpdateVersionModal.hide;

export { showUpdateVersionModal, hideUpdateVersionModal };

export default UpdateVersionModal;

如何更新

我司使用流水线部署代码,所以在流水线的部署步骤后面加了个额外的步骤,用来执行更新版本号的js代码,用node命令执行js代码即可调用代码。如果没有部署步骤,也可以在打包完毕后执行更新版本号的js代码

实际效果

若网页版本更新了,那么当老页面的用户调用了任意接口后,就会弹出弹窗