Uniapp + PWA 基础入门 03,从 0 到 1:Uniapp 集成 PWA 核心能力(离线缓存 / 添加到桌面 / 启动页定制)
在移动互联网时代,用户对应用的体验要求越来越高。Uniapp 作为跨平台开发的利器,能让我们一套代码运行多端,但 Web 端体验往往不如原生 App——比如无法离线访问、不能添加到桌面、启动时白屏等。而 PWA(Progressive Web App,渐进式 Web 应用)的核心能力恰好能解决这些痛点。本文将带你从 0 到 1 实现 Uniapp 集成 PWA 核心能力,包括离线缓存、添加到桌面、启动页定制,让你的 Web 端应用更接近原生体验。
一、前置知识:什么是 PWA 及核心能力
PWA 不是单一技术,而是一系列 Web 技术的集合,核心目标是让 Web 应用拥有原生 App 的体验。其关键能力包括:
-
离线缓存:通过 Service Worker 拦截网络请求,缓存核心资源,实现离线访问或弱网下快速加载;
-
添加到桌面:支持用户将应用添加到手机/电脑桌面,像原生 App 一样启动,无需通过浏览器访问;
-
启动页定制:通过 Web App Manifest 配置启动页(闪屏),解决启动白屏问题,提升品牌辨识度;
-
其他能力:推送通知、后台同步等(本文重点聚焦前三项核心能力)。
Uniapp 本身对 PWA 有一定的支持,但需要手动配置和扩展,下面我们逐步实现。
二、环境准备
在开始集成前,确保你已具备以下环境:
-
Uniapp 项目:已创建并能正常运行(本文基于 Vue 3 + Vite 版本,Vue 2 版本配置类似,略有差异);
-
开发工具:HBuilderX 或 VS Code + Uniapp 插件;
-
测试环境:支持 HTTPS 的服务器(PWA 核心能力依赖 HTTPS,本地测试可使用
localhost或开启 SSL 的本地服务); -
依赖包:
workbox-cli(用于生成 Service Worker,简化离线缓存配置)。
首先,安装 workbox-cli(全局安装或项目本地安装均可):
npm install workbox-cli -g
# 或本地安装
npm install workbox-cli --save-dev
三、核心步骤 1:配置 Web App Manifest(实现添加到桌面 + 启动页定制)
Web App Manifest 是一个 JSON 文件,用于定义应用的名称、图标、启动页、显示模式等信息,是实现“添加到桌面”和“启动页定制”的基础。
3.1 创建 Manifest 文件
在 Uniapp 项目的 public 目录下(Vue 3 + Vite 项目,Vue 2 项目为 static 目录),创建 manifest.json 文件,内容如下:
{
"name": "我的 Uniapp PWA 应用", // 应用全称(添加到桌面时显示)
"short_name": "Uniapp PWA", // 应用简称(桌面图标下方显示)
"start_url": "/", // 启动页 URL(默认根路径)
"display": "standalone", // 显示模式:standalone(类似原生 App,无浏览器导航栏)
"background_color": "#ffffff", // 启动页背景色(与启动页图片背景色一致,避免闪屏)
"theme_color": "#42b983", // 主题色(浏览器地址栏/状态栏颜色)
"icons": [ // 应用图标(不同尺寸,适配不同设备)
{
"src": "icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable" // 适配圆形/异形图标(部分安卓设备)
}
],
"splash_pages": null // 禁用默认闪屏,使用自定义启动页
}
3.2 放置图标资源
在 public 目录下创建 icons 文件夹,放入上述配置中对应的图标(建议使用工具生成不同尺寸的图标,比如 favicon-generator)。
3.3 在 index.html 中引入 Manifest
修改 public/index.html,在 <head> 标签中添加以下代码,引入 Manifest 文件并配置相关元标签:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Manifest -->
<link rel="manifest" href="/manifest.json">
<!-- 适配 iOS 设备(iOS 不完全支持 manifest,需额外配置) -->
<link rel="apple-touch-icon" href="/icons/icon-192x192.png"> <!-- iOS 桌面图标 -->
<meta name="apple-mobile-web-app-capable" content="yes"> <!-- 启用全屏模式 -->
<meta name="apple-mobile-web-app-status-bar-style" content="#42b983"> <!-- iOS 状态栏颜色 -->
<meta name="apple-mobile-web-app-title" content="Uniapp PWA"> <!-- iOS 应用名称 -->
<!-- 启动页适配 iOS -->
<link rel="apple-touch-startup-image" href="/icons/splash-640x1136.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)">
<link rel="apple-touch-startup-image" href="/icons/splash-750x1334.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)">
<link rel="apple-touch-startup-image" href="/icons/splash-1242x2208.png" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3)">
<!-- 标题 -->
<title>我的 Uniapp PWA 应用</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
说明:iOS 对 PWA 的支持不如安卓完善,需要通过 apple-touch-* 系列元标签额外配置图标和启动页。
3.4 测试“添加到桌面”功能
-
运行 Uniapp 项目,构建 Web 端产物(
npm run build:h5); -
将构建后的
dist/build/h5目录部署到支持 HTTPS 的服务器(或本地使用serve -s dist/build/h5 --ssl-cert cert.pem --ssl-key key.pem启动 HTTPS 服务); -
用手机浏览器(推荐 Chrome、Edge 或 Safari)访问部署后的地址:
-
安卓:点击浏览器菜单,选择“添加到桌面”;
-
iOS:点击 Safari 分享按钮,选择“添加到主屏幕”。
添加成功后,桌面会出现配置的应用图标,点击即可像原生 App 一样启动应用。
四、核心步骤 2:集成 Service Worker(实现离线缓存)
Service Worker 是一个运行在浏览器后台的脚本,独立于网页线程,能够拦截和处理网络请求,从而实现离线缓存。Uniapp 本身不自带 Service Worker 配置,我们使用 Workbox 工具来简化配置。
4.1 创建 Workbox 配置文件
在 Uniapp 项目根目录下,创建 workbox-config.js 文件,配置缓存规则:
module.exports = {
globDirectory: 'dist/build/h5', // 待缓存的文件目录(Web 端构建产物目录)
globPatterns: [ // 缓存文件匹配规则
'**/*.{html,css,js,json,png,jpg,jpeg,gif,svg,woff,woff2,eot,ttf}'
],
swDest: 'dist/build/h5/sw.js', // 生成的 Service Worker 文件路径
runtimeCaching: [ // 运行时缓存规则(动态资源,如接口请求)
{
urlPattern: /^https:\/\/api\.example\.com/, // 匹配需要缓存的接口域名
handler: 'NetworkFirst', // 策略:优先网络,网络失败时使用缓存
options: {
cacheName: 'api-cache', // 缓存名称
cacheableResponse: {
statuses: [200] // 只缓存 200 状态码的响应
},
expiration: {
maxEntries: 50, // 最大缓存条目数
maxAgeSeconds: 60 * 60 * 24 // 缓存有效期:24 小时
}
}
}
],
skipWaiting: true, // 新的 Service Worker 安装完成后立即激活,无需等待旧的 Service Worker 退出
clientsClaim: true // 激活后立即控制所有打开的客户端(网页)
};
缓存策略说明:
-
CacheFirst:优先使用缓存,适用于静态资源(如图片、CSS、JS);
-
NetworkFirst:优先使用网络,适用于动态接口(确保数据最新,网络失败时用缓存兜底);
-
StaleWhileRevalidate:先使用缓存,同时后台请求更新缓存,适用于非核心动态资源。
4.2 生成 Service Worker 文件
在 package.json 中添加脚本,用于生成 Service Worker:
{
"scripts": {
"build:h5": "uni build --platform h5",
"build:h5:pwa": "npm run build:h5 && workbox generateSW workbox-config.js"
}
}
执行以下命令,构建 Web 端并生成 Service Worker:
npm run build:h5:pwa
执行完成后,会在 dist/build/h5 目录下生成 sw.js(Service Worker 脚本)和 workbox-*.js(Workbox 核心库)。
4.3 注册 Service Worker
在 Uniapp 项目的入口文件(如 src/main.js)中,添加 Service Worker 注册代码:
import { createApp } from 'vue'
import App from './App.vue'
import uView from 'uview-plus'
import 'uview-plus/dist/uview-plus.css'
const app = createApp(App)
app.use(uView)
app.mount('#app')
// 注册 Service Worker(仅在 Web 端且支持 Service Worker 的浏览器中执行)
if (process.env.VUE_APP_PLATFORM === 'h5' && 'serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker 注册成功:', registration.scope)
})
.catch(error => {
console.error('Service Worker 注册失败:', error)
})
})
}
说明:process.env.VUE_APP_PLATFORM === 'h5' 用于判断当前环境为 Web 端,避免在其他端(如 App、小程序)执行该代码。
4.4 测试离线缓存功能
-
将重新构建后的
dist/build/h5目录部署到服务器; -
用浏览器访问应用,先正常浏览页面(让 Service Worker 缓存资源);
-
打开浏览器开发者工具(F12),切换到
Application面板:
-
查看
Service Workers选项,确认sw.js已激活; -
查看
Cache Storage选项,可看到缓存的静态资源和接口数据。
- 断开网络(关闭 WiFi 和数据流量),刷新页面:
如果页面能正常显示(静态资源加载成功),且之前缓存的接口数据能正常展示,说明离线缓存功能实现成功。
五、核心步骤 3:定制启动页(优化启动体验)
虽然通过 Manifest 配置了启动页,但 Uniapp Web 端启动时可能仍会出现短暂白屏(因 Vue 初始化需要时间)。我们可以通过以下方式优化:
5.1 静态启动页占位
在 public/index.html 的 #app 容器中添加静态启动页内容,与 Manifest 配置的启动页风格一致:
<div id="app">
<!-- 静态启动页 -->
<div class="splash-screen">
<img src="/icons/icon-512x512.png" alt="应用图标" class="splash-icon">
<p class="splash-text">我的 Uniapp PWA 应用</p>
</div>
</div>
<style>
/* 启动页样式 */
.splash-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 9999;
}
.splash-icon {
width: 80px;
height: 80px;
border-radius: 16px;
margin-bottom: 20px;
}
.splash-text {
font-size: 18px;
color: #42b983;
font-weight: bold;
}
</style>
5.2 Vue 初始化完成后隐藏启动页
在 src/App.vue 中,添加 onMounted 钩子,在 Vue 初始化完成后隐藏静态启动页:
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
// 隐藏静态启动页
const splashScreen = document.querySelector('.splash-screen')
if (splashScreen) {
// 添加过渡动画,提升体验
splashScreen.style.opacity = '0'
splashScreen.style.transition = 'opacity 0.5s ease-out'
setTimeout(() => {
splashScreen.style.display = 'none'
}, 500)
}
})
</script>
<template>
<view class="app">
<!-- 应用内容 -->
<router-view></router-view>
</view>
</template>
这样,启动时会先显示静态启动页,待 Vue 初始化完成后平滑隐藏,彻底解决启动白屏问题。
六、常见问题排查
6.1 无法添加到桌面
-
检查是否部署在 HTTPS 环境(
localhost除外); -
检查
manifest.json配置是否完整(必填项:name、short_name、start_url、display、icons); -
iOS 设备需确保
apple-touch-icon配置正确,且图片尺寸符合要求。
6.2 离线缓存不生效
-
检查
sw.js是否成功生成并部署; -
查看浏览器开发者工具
Application > Service Workers,确认 Service Worker 已激活; -
检查缓存规则是否正确(
globPatterns是否匹配需要缓存的文件); -
确保接口请求符合
runtimeCaching配置的urlPattern。
6.3 启动页仍有白屏
-
检查静态启动页是否添加到
#app容器中; -
确保
onMounted钩子中正确隐藏了启动页; -
优化 Vue 初始化逻辑,减少启动时的同步操作。
七、总结
本文通过三个核心步骤,实现了 Uniapp 集成 PWA 的核心能力:通过 Web App Manifest 配置实现“添加到桌面”和启动页基础配置,通过 Service Worker + Workbox 实现离线缓存,通过静态启动页 + 过渡动画优化启动体验。集成 PWA 后,你的 Uniapp Web 端应用将拥有更接近原生 App 的体验,提升用户留存率和使用体验。
后续还可以探索 PWA 的其他高级能力,比如推送通知、后台同步等,进一步增强应用的功能。如果在集成过程中有任何问题,欢迎在评论区交流!
更多推荐
所有评论(0)