You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Safari添加PWA到主屏后缓存丢失问题求助

问题描述

使用VueJS+Ionic开发PWA,已安装@vue/cli-plugin-pwa插件,需求是:用户访问网站时存储URL中的ref参数,待PWA安装到主屏后读取该参数。

当前实现:

  • 在registerServiceWorker.js的ready钩子中通过Cache API存储ref参数:
import { register } from 'register-service-worker'
import { store } from './store/index.js'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    registrationOptions: { scope: '.' },
    async ready () {
      // 获取ref参数
      const queryString = window.location.search
      const urlParams = new URLSearchParams(queryString)
      const ref = urlParams.get('ref')
      console.log(ref)
      // 缓存参数
      try {
        if (ref !== null && ref !== '' && ref !== undefined && ref !== 'undefined') {
          const cache = await caches.open("ref")
          const responseBody = JSON.stringify({ref: ref})
          const response = new Response(responseBody)
          await cache.put("/ref-code", response)
        }
      } catch {
        console.log('referral code not saved')
      } finally {
        store.commit("moduleMain/setInstallReady", true)
      }
    },
    registered () {
      console.log('registered')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}
  • 在Ionic页面的ionViewWillEnter钩子中读取缓存:
try {
    const cache = await caches.open("ref");
    const response = await cache.match("/ref-code")
    if (response) {
        const responseBody = await response.json()
        this.$store.commit('moduleHome/setCode', responseBody["ref"])
        this.$store.commit('moduleSettings/setCode', responseBody["ref"])
    }
} catch (error) {
    console.log("getToken error:", { error });
}

问题:Chrome浏览器测试正常,但iOS Safari添加到主屏后,缓存中的ref参数丢失。

解决方案

核心原因

iOS Safari的主屏PWA与浏览器共享隔离的缓存上下文:Cache API属于Service Worker的缓存空间,主屏启动的PWA会使用独立的Service Worker实例或缓存环境,导致无法读取浏览器中存储的缓存内容。而localStorage是基于域名的存储,同一域名下的浏览器和主屏PWA可共享该数据,是更可靠的选择。

方案1:改用localStorage存储参数

修改存储逻辑(registerServiceWorker.js)

将Cache API替换为localStorage:

async ready () {
  const queryString = window.location.search
  const urlParams = new URLSearchParams(queryString)
  const ref = urlParams.get('ref')
  console.log(ref)
  try {
    if (ref !== null && ref !== '' && ref !== undefined && ref !== 'undefined') {
      // 存储到localStorage
      localStorage.setItem('referral_ref', ref);
    }
  } catch {
    console.log('referral code not saved')
  } finally {
    store.commit("moduleMain/setInstallReady", true)
  }
},

修改读取逻辑(页面钩子)

直接从localStorage读取:

try {
  const ref = localStorage.getItem('referral_ref');
  if (ref) {
    this.$store.commit('moduleHome/setCode', ref);
    this.$store.commit('moduleSettings/setCode', ref);
    // 可选:读取后清除参数,避免重复使用
    localStorage.removeItem('referral_ref');
  }
} catch (error) {
  console.log("getToken error:", { error });
}

方案2:优化存储时机(结合beforeinstallprompt事件)

为确保参数在安装前完成存储,可监听beforeinstallprompt事件(用户触发安装提示时):

// 在main.js或全局组件中添加
let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  deferredPrompt = e;
  // 存储ref参数
  const queryString = window.location.search;
  const urlParams = new URLSearchParams(queryString);
  const ref = urlParams.get('ref');
  if (ref) {
    localStorage.setItem('referral_ref', ref);
  }
  // 显示安装按钮
  store.commit("moduleMain/setInstallReady", true);
});

// 当用户点击安装按钮时触发
// 示例:在组件中调用
async handleInstall() {
  if (deferredPrompt) {
    deferredPrompt.prompt();
    const { outcome } = await deferredPrompt.userChoice;
    if (outcome === 'accepted') {
      console.log('用户已安装PWA');
    }
    deferredPrompt = null;
  }
}

方案3:改用IndexedDB存储(复杂场景)

如果需要存储更多数据或有异步存储需求,IndexedDB是更强大的选择,它在iOS PWA中的支持更稳定:

  • 存储时使用IndexedDB API写入ref参数
  • 读取时从IndexedDB中查询对应数据

内容的提问来源于stack exchange,提问作者dexter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:25:01