【无标题】

只有 WebSocket 页面在 iOS 回退后显示旧版本的问题解决方案

问题背景

在云闪付小程序(Uniapp + Vue3 + H5)中,仅包含 WebSocket 连接的页面在跳转至第三方页面(如支付收银台)并返回后,页面显示为旧版本代码(例如:新增的按钮消失、版本号回退),而其他普通页面表现正常。

根本原因

  1. iOS WKWebView 缓存策略:跳转第三方时,系统会挂起或销毁后台 WebView。
  2. WebSocket 高耗能特性:带 WebSocket 的页面更容易被系统回收(Kill),以节省内存和电量。
  3. 缓存复用:页面被回收后重新加载时,浏览器读取了本地缓存的旧 HTML/JS/CSS 文件,导致显示旧版本。
  4. 普通页面不受影响:因为它们常驻内存(未被销毁),返回时直接从缓存恢复,不会重新加载,因此不会触发缓存问题。

解决方案

方案一:跳转前主动关闭 WebSocket 连接

作用:释放资源,降低页面被系统回收的概率。

javascript 复制代码
// 在跳转第三方页面前执行
const closeWebSocket = () => {
  if (socketTask) {
    socketTask.close({
      success: () => console.log('WebSocket 已关闭'),
      fail: (err) => console.error('关闭失败', err)
    });
    socketTask = null;
  }
};

// 跳转示例
const goToThirdParty = () => {
  closeWebSocket();
  uni.navigateTo({ url: '/pages/third-party/pay' });
};

方案二:跳转前给当前页面 URL 添加时间戳

作用:确保页面即使被回收重新加载,也强制获取最新资源,绕过缓存。

javascript 复制代码
// 方法 A:在跳转前修改当前 URL(推荐)
const addTimestampToUrl = () => {
  const url = window.location.href;
  const separator = url.includes('?') ? '&' : '?';
  const cleanUrl = url.replace(/[?&]_t=\d+/, ''); // 去除旧时间戳
  const newUrl = cleanUrl + separator + '_t=' + Date.now();
  window.history.replaceState({}, '', newUrl);
};

// 方法 B:在 App.vue 或入口文件全局监听(兜底)
window.addEventListener('pageshow', (event) => {
  if (event.persisted) { // 从缓存恢复时强制刷新
    window.location.reload();
  }
});

// 跳转示例(组合方案一+二)
const goToThirdParty = () => {
  closeWebSocket();          // 方案一
  addTimestampToUrl();       // 方案二
  uni.navigateTo({ url: '/pages/third-party/pay' });
};