概述
传统网站
采用HTML、CSS、JS等技术编写的网络应用,并通过浏览器进行访问。在用户不访问它时,在用户的设备上没有存在感,只能通过用户打开浏览器并导航到该网站来访问,而且高度依赖于网络连接。
平台专属应用
采用IOS、Android、C++等技术编写的原生应用,只能在专属平台下使用,不能方便的跨平台移植。好处是性能更流畅,支持离线,桌面图标的独立体验等。
跨平台框架
能够用同一套代码同时运行在多个平台(iOS、Android、Web、Windows、Mac 等)上的开发框架。它的核心目标是提高开发效率,减少重复开发,同时尽量保证接近原生的体验和性能。如:React Native,Flutter,uni-app等。
渐进式Web应用
渐进式 web 应用结合了传统网站和平台特定应用的最佳特性。具有网站的优势,包括:
- 使用标准的 web 平台技术开发的,所以它们可以从单一代码库在多个操作系统和设备类上运行。
- 可以直接通过浏览器访问。
同时也具有平台特定应用程序的许多优势,包括:
- 可以从平台的应用商店安装,也可以直接从 web 安装。
- 设备上得到一个应用图标,与平台特定应用程序一样,用户黏性更强。
- 具备离线能力,在设备没有网络连接时工作,应用更加可靠。
- 资源具备缓存能力,使得应用启动速度更快,性能更好。
总结: 渐进式 Web 应用(Progressive Web App,简称 PWA)是一种结合了网页与原生应用优点的新型 Web 应用开发模式。PWA 通过现代 Web 技术提供类似原生应用的体验:可安装、离线使用、后台更新、消息推送等。
PWA基本使用
效果演示
Squoosh 一款开源浏览器中运行的图像压缩工具。
同时支持商店安装:
- 适用于 Android 和 ChromeOS 的 Google Play 商店,使用 Trusted Web Activity。
- 适用于 iOS、macOS 和 iPadOS 的 Apple App Store,使用 WKWebView 和应用绑定网域。
- 适用于 Windows 10 和 11 的 Microsoft Store,使用 APPX 软件包。
- Samsung Galaxy Store,使用 Samsung WebAPK 铸造服务器。
- 华为 AppGallery,使用适用于 HTML 应用的 QuickApp 容器。
PWA Builder: 支持将你的 PWA 打包为适合各大应用商店提交的安装包格式,例如 Windows Microsoft Store 的 .msix / .appx ,以及通过 TWA 打包后提交至 Google Play Store。还支持 Samsung Store、Meta Quest 平台等。
具备PWA的条件
- https协议(开发阶段可以localhost)
- 移动端可以采用模拟器或Fiddler代理本地站点
- 可通过github actions提供带有https的static page
- manifest清单
- 官方扩展名为
.webmanifest ,也可以是为 manifest.json 文件
- service worker文件
- 一个特殊的Web Worker文件,可以后台运行
- 充当代理,拦截浏览器和服务器之间的请求,并处理缓存实现离线访问
mainfest清单
用于告知浏览器您希望 Web 内容以何种方式在操作系统中显示为应用。清单可以包含基本信息(例如应用名称、图标和主题颜色);高级偏好设置(例如所需屏幕方向和应用快捷方式);以及目录元数据(例如屏幕截图)。
{
"name": "我的 PWA",
"short_name": "PWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"description": "一个简单的 PWA 示例",
"icons": [
{
"src": "icons/test.png",
"type": "image/png",
"sizes": "512x512"
}
]
}


Service Worker
Service Worker 是渐进式 Web 应用实现离线功能的核心,它运行在浏览器后台的独立线程中,可以拦截和处理网络请求。

为了理解 Service Worker,我们先看一个普通 Web Worker 的例子:
// main.js
// 创建 Worker
const worker = new Worker('worker.js');
// 监听来自 worker 的消息
worker.onmessage = function(event) {
document.getElementById('result').innerText = '来自 Worker 的消息:' + event.data;
};
// 向 worker 发送消息
function sendMessage() {
worker.postMessage('你好,Worker!');
}
// worker.js
// 接收主线程的消息
onmessage = function(event) {
console.log('主线程发来的消息:', event.data);
// 处理完后,发送消息回主线程
postMessage('收到你的消息:"'+ event.data +'",你好,主线程!');
};
Service Worker 是一种特殊的 Worker,它充当了网页与应用服务器之间的代理,能够拦截和处理 fetch 请求,这是实现离线缓存和资源控制的关键。

使用步骤:
- 注册service worker
- 添加install事件,注册成功触发,主要用于缓存资料
- 添加activate事件,激活的时候触发,主要用于删除旧的资源
- 添加fetch事件,主要用于操作缓存或者读取网络资源
自定义安装
当浏览器检测到您的应用可供安装时,就会触发 beforeinstallprompt 事件。您需要实现此事件处理脚本来自定义用户体验。
window.onload = () => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./sw.js')
.then((res) => console.log('service worker registered', res))
.catch((err) => console.log('service worker not registered', err))
}
const btn1 = document.getElementById('btn1')
btn1.addEventListener('click', () => {
const deferredPrompt = window.deferredPrompt
if (!deferredPrompt) {
console.log('No deferred prompt available.')
return
}
deferredPrompt.prompt()
})
// 可安装PWA的事件
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault()
window.deferredPrompt = e
})
}
PWA离线访问
cache storage
cache storage 是 Service Worker 的核心功能之一,它是浏览器提供的一种 在客户端持久化缓存资源(如 HTML、JS、CSS、图片等) 的机制。 在 PWA中,通常使用 cache storage 来离线缓存页面资源,实现离线访问、快速加载等特性。
| 方法 |
作用 |
caches.open(name) |
打开或创建一个缓存 |
cache.add(url) |
缓存一个 URL 的请求 |
cache.addAll([urls]) |
批量缓存多个资源 |
cache.put(request, response) |
手动放入缓存(需 clone) |
caches.match(request |
匹配缓存中的资源 |
caches.keys() |
获取所有缓存名称 |
caches.delete(name) |
删除某个缓存 |
缓存策略
预缓存(静态资源)

self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(cachedResponse => {
// It can update the cache to serve updated content on the next request
return cachedResponse || fetch(event.request);
}
)
)
});
网络优先(动态缓存)

self.addEventListener("fetch", event => {
event.respondWith(
fetch(event.request)
.catch(error => {
return caches.match(event.request);
})
);
});
在重新验证时过时

self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
const networkFetch = fetch(event.request).then(response => {
// update the cache with a clone of the network response
const responseClone = response.clone()
caches.open(url.searchParams.get('name')).then(cache => {
cache.put(event.request, responseClone)
})
return response
}).catch(function (reason) {
console.error('ServiceWorker fetch failed: ', reason)
})
// prioritize cached response over network
return cachedResponse || networkFetch
}
)
)
})
离线通知
navigator.onLine、online事件
- Notifications API
后台同步
self.addEventListener('sync', (e) => {
if (e.tag === 'send-email') {
console.log('send-email success!')
}
})
PWA框架
Workbox
Workbox 是 Google 推出的一个 PWA(渐进式 Web 应用)工具库,主要用来简化 Service Worker 的编写和管理,让开发者可以更轻松地实现离线缓存、资源预加载、后台同步等功能。
一些常用的模块包括:
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-cache',
})
)
* **`workbox-strategies`**:一组运行时缓存策略,用于处理请求响应,例如先缓存并在重新验证时过时:
```js
import { NetworkFirst, CacheFirst, StaleWhileRevalidate } from 'workbox-strategies'
workbox-precaching:它是 Service Worker 的 install 事件处理程序中缓存文件的实现(也称为预缓存)。

vite-plugin-pwa
vite-plugin-pwa为 Vite 及其生态系统提供 PWA 集成,内部用 Workbox 做 Service Worker 相关的缓存和生成工作。它相当于 “Vite + Workbox 的桥梁”,让你在 Vite 项目里用简单配置就能启用 PWA 功能,而不必手动整合 Workbox 构建流程。
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My Awesome App',
short_name: 'MyApp',
description: 'My Awesome App description',
theme_color: '#ffffff',
icons: [
{
src: 'icon-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
}),
],
})
通过合理配置 Service Worker 和利用 Workbox 等工具,你可以显著提升 Web 应用的用户体验。想了解更多前沿的前端技术与实践,欢迎访问云栈社区与开发者们交流探讨。