uniapp 使用vue/pwa

vue add @vue/pwa

src下创建service-worker.js

/* eslint-disable no-undef*/
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js')
if (workbox) {
  console.log(`Yay! Workbox is loaded 🎉`)
} else {
  console.log(`Boo! Workbox didn't load 😬`)
}
 
workbox.core.setCacheNameDetails({
  prefix: 'ochase-search',
  suffix: 'v1.0.0'
})
workbox.core.skipWaiting() // 强制等待中的 Service Worker 被激活
workbox.core.clientsClaim() // Service Worker 被激活后使其立即获得页面控制权
workbox.precaching.precacheAndRoute(self.__precacheManifest || []) // 设置预加载
 
// 缓存web的css资源
workbox.routing.registerRoute(
  // Cache CSS files
  /.*\.css/,
  // 使用缓存,但尽快在后台更新
  new workbox.strategies.StaleWhileRevalidate({
    // 使用自定义缓存名称
    cacheName: 'css-cache'
  })
)
 
// 缓存web的js资源
workbox.routing.registerRoute(
  // 缓存JS文件
  /.*\.js/,
  // 使用缓存,但尽快在后台更新
  new workbox.strategies.StaleWhileRevalidate({
    // 使用自定义缓存名称
    cacheName: 'js-cache'
  })
)
 
// 缓存web的图片资源
workbox.routing.registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg)$/,
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'images',
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60 // 设置缓存有效期为30天
      })
    ]
  })
)
 
// 如果有资源在其他域名上,比如cdn、oss等,这里做单独处理,需要支持跨域
workbox.routing.registerRoute(
  /^https:\/\/cdn\.ochase\.com\/.*\.(jpe?g|png|gif|svg)/,
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'cdn-images',
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 5 * 24 * 60 * 60 // 设置缓存有效期为5天
      })
    ],
    fetchOptions: {
      credentials: 'include' // 支持跨域
    }
  })
)

在main.js 添加代码

// #ifdef VUE3
import './src/registerServiceWorker'

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/src/service-worker.js').then(registration => {
      console.log('Service Worker registered with scope:', registration.scope);
    }).catch(error => {
      console.error('Service Worker registration failed:', error);
    })
  })
}

import { createSSRApp } from 'vue'
export function createApp() {
	const app = createSSRApp(App)
	return {
		app
	}
}
// #endif

在pulic添加 manifest.json

{
	"short_name": "name",
	"name": "name",
	"icons": [{
		"src": "/static/logo.png",
		"type": "image/png",
		"sizes": "72x72"
	},
	{
		"src": "/static/2.png",
		"type": "image/png",
		"sizes": "320x320"
	}],
	"id": "/?source=pwa",
	"start_url": "index.html",
	"background_color": "#3367D6",
	"display": "standalone",
	"scope": "/",
	"theme_color": "#3367D6",
	"shortcuts": [{
			"name": "",
			"short_name": "",
			"description": "",
			"url": "/today?source=pwa",
			"icons": [{ "src": "/static/1.png", "sizes": "96x96" }]
		},
		{
			"name": "",
			"short_name": "",
			"description": "",
			"url": "/tomorrow?source=pwa",
			"icons": [{ "src": "/static/1.png", "sizes": "96x96" }]
		}
	],
	"description": "",
	"screenshots": [{
			"src": "",
			"type": "image/png",
			"sizes": "320x320",
			"form_factor": "narrow"
		},
		{
			"src": "",
			"type": "image/jpg",
			"sizes": "320x320",
			"form_factor": "wide"
		}
	]
}

在index.html添加

//主题颜色		
<meta name="theme-color" content="#00142A">
//引入manifest.json
<link rel="manifest" href="/public/manifest.json" />

然后运行 支持https协议和localhost

判断当前处于h5 或者pwajianti

<script setup>
	import { onMounted } from 'vue'
	onMounted(() => {
		console.log(checkIfPWA() ? 'PWA 模式' : 'H5 模式');
		if (checkIfPWA()) {
			uni.navigateTo({
				url: '/pages/live/index'
			})
		} else {
			uni.navigateTo({
				url: '/pages/pwa/index'
			})
		}
	})

	const checkIfPWA = () => {
		return (
			window.matchMedia('(display-mode: standalone)').matches ||
			window.navigator.standalone === true ||
			document.referrer.startsWith('android-app://')
		)
	}
</script>

监听下载事件

onMounted(() => {
  window.addEventListener('beforeinstallprompt', (event) => {
    // 防止浏览器默认的安装提示
    event.preventDefault()
    installPromptEvent.value = event;  // 保存事件对象
    console.log('安装事件已保存:', installPromptEvent.value)
  })
})

	const install = () => {
		if (installPromptEvent.value) {
			// 显示pwa安装提示
			installPromptEvent.value.prompt()

			// 监听用户选择结果
			installPromptEvent.value.userChoice.then((choiceResult) => {
				if (choiceResult.outcome === 'accepted') {
					console.log('用户接受了安装')
				} else {
					console.log('用户拒绝了安装')
				}
				installPromptEvent.value = null
			});
		} else {
			console.log('安装事件不可用')
		}
	}
相关推荐
高山我梦口香糖36 分钟前
[react] <NavLink>自带激活属性
前端·javascript·react.js
撸码到无法自拔40 分钟前
React:组件、状态与事件处理的完整指南
前端·javascript·react.js·前端框架·ecmascript
高山我梦口香糖41 分钟前
[react]不能将类型“string | undefined”分配给类型“To”。 不能将类型“undefined”分配给类型“To”
前端·javascript·react.js
CodeChampion1 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
Elena_Lucky_baby1 小时前
实现路由懒加载的方式有哪些?
前端·javascript·vue.js
一雨方知深秋1 小时前
智慧商城:封装getters实现动态统计 + 全选反选功能
开发语言·javascript·vue2·foreach·find·every
海威的技术博客2 小时前
关于JS中的this指向问题
开发语言·javascript·ecmascript
王解2 小时前
Vue CLI 脚手架创建项目流程详解 (2)
前端·javascript·vue.js
刘大浪2 小时前
vue.js滑动到顶便锁定位置
前端·javascript·vue.js
ordinary903 小时前
指令-v-for的key
前端·javascript·vue.js