网文介绍PWA是什么的文章一大堆,本文不再过多阐述,PWA能火起来,定然有它的优势!但大部分人关注PWA,大多因为以下几点:
1. GooglePlay或者AppStore上不去架。
2. 意图绕开商店支付,降低支付抽佣压力,提高自身利润。
3. 单纯地想增加一个获客来源。
4. 自用的内部工具类App
PWA虽然有它的优势,但依旧无法和主流应用市场带给开发者的流量有可比性,如果能上架开展业务肯定是最优选择。当然,对于H5游戏出海和不需要获取用户设备信息的应用,例如AI、工具、社交与短剧等也都可以尝试,扩展自身获客来源,增加收入。
PWA运行流程
我们可以通过一张简单的图看下PWA 的运行流程,也就是用户在使用 PWA 应用时,浏览器是如何工作的。
创建PWA项目
本文将带您一步步从零开始创建一个 PWA 项目,项目依托于VitePWA插件,其是一个用于 Vite 项目的插件,可以让您轻松将 Vite 项目转换为 PWA,并提供了简单的配置方式来启用 Service Worker 和其他 PWA 功能。
(1) 使用 Vite 创建 PWA 项目
首先,打开终端并输入以下命令以创建一个 VitePWA 项目。
npm create @vite-pwa/pwa@latest
这个命令会引导你完成项目的初始化。您按照提示选择项目名称、模板等信息就行。
(2) 安装项目依赖
在项目目录下运行以下命令来安装项目依赖。
npm install
(3) 项目构建
完成依赖安装后,可以通过以下命令构建项目。
npm run build
构建后会在项目目录下生成一个 dist 文件夹,里面包含了项目的静态资源。
(4) 使用 http-server 运行项目
构建完成后,我们可以使用 http-server 启动一个本地服务器,来测试 PWA 功能。
npx http-server dist
此时,你已经完成了 PWA 项目的基础创建和构建,可以在浏览器中打开项目,进行进一步的测试和开发了。
Https环境配置
PWA 硬性要求在 HTTPS 环境下运行,确保安全性。因此,我们需要在本地搭建 HTTPS 服务器。初期,可以使用自签名证书来创建一个 HTTPS 环境。
(1) 创建 HTTPS 环境
获取自签名证书文件和私钥文件,并将两个文件放在项目中
在 package.json 文件中,我们可以添加一个 start 脚本来启动 HTTPS 服务器,示例如下:
"scripts": {
"start": "npx http-server dist -S -C example.com+4.pem -K example.com+4-key.pem -p 9090 --index index.html"
}
使用上面的命令时,example.com+4.pem 是自签名证书文件,example.com+4-key.pem 是私钥文件。
(2) 运行 HTTPS 服务器
在项目根目录下执行以下命令以启动 HTTPS 环境
npm run start
然后在浏览器中访问 ,即可测试 PWA 功能。
Service Worker
Service Worker 是 PWA 的核心组件之一。它是一个运行在浏览器后台的脚本,允许网页在不打开的情况下执行任务。Service Worker 可以拦截和处理网络请求,实现离线缓存、消息推送等功能。
(1) Service Worker 的关键特性:
缓存资源:可以缓存静态资源,使得网页在离线状态下仍能使用。
网络请求拦截:在网络不稳定的情况下,可以优先使用缓存资源。
后台同步:在后台完成数据同步任务。
推送通知:即使应用未打开,也能接收消息通知。
(2) 在 PWA 项目中注册Service Worker
// src/sw-register.ts
// 注册 Service Worker 的功能
export function registerServiceWorker() {
// 检查浏览器是否支持 Service Worker
if ('serviceWorker' in navigator) {
// 注册新的 Service Worker
navigator.serviceWorker.register('/sw.js', { scope: '/' })
.then((registration) => {
console.log('注册成功的 Service Worker:', registration);
// 如果有等待中的 Service Worker,则立即接管控制权
if (registration.waiting) {
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}
// 监听 Service Worker 的状态变化事件
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
if (newWorker) {
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed') {
console.log('新的 Service Worker 已安装。');
if (navigator.serviceWorker.controller) {
console.log('新的 Service Worker 正在控制页面。');
} else {
console.log('等待新的 Service Worker 控制页面。');
}
}
});
}
});
})
.catch((error) => {
console.log('Service Worker 注册失败:', error);
});
} else {
console.log('此浏览器不支持 Service Worker。');
}
}
(3) 在 PWA 项目中使用Service Worker
import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching'
import { NavigationRoute, registerRoute } from 'workbox-routing'
declare let self: ServiceWorkerGlobalScope
// install 事件:在 Service Worker 安装阶段触发。
self.addEventListener('install', (event) => {
console.log('Service Worker installing123...');
self.skipWaiting();
// 立即跳过等待阶段,使当前 Service Worker 立即进入激活状态,而不必等待所有页面关闭之前的旧版本停止工作。
});
// Service Worker 激活阶段触发
self.addEventListener('activate', (event) => {
console.log('Service Worker activated.');
event.waitUntil(self.clients.claim());
// 让这个 Service Worker 立即取得对所有客户端(页面)的控制权,而不需要等待页面重新加载。
});
// 当页面发送消息到 Service Worker 时触发
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING')
self.skipWaiting()
// 获取所有窗口类型的客户端,包括那些未受当前 Service Worker 控制的客户端
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clients) => {
clients.forEach((client) => {
client.postMessage(event.data);
// 将收到的消息广播给所有匹配到的客户端
});
});
})
// 当用户点击通知时触发
self.addEventListener("notificationclick", (event) => {
// 关闭通知
event.notification.close();
event.waitUntil(
clients
.matchAll()
.then((clientList) => {
for (const client of clientList) {
// 让某个已经打开的客户端获得焦点
client.focus();
}
}),
);
});
// precacheAndRoute 是 Workbox 提供的用于预缓存静态资源的方法。
// self.__WB_MANIFEST 是 Workbox 在构建时自动生成的资源清单(Manifest),包含所有要预缓存的文件
precacheAndRoute(self.__WB_MANIFEST)
// 清理旧版本缓存,以确保只有最新版本的缓存资源被保留。
cleanupOutdatedCaches()
// registerRoute:用 Workbox 注册一个路由规则。
// NavigationRoute:专门用于处理导航请求(如用户通过链接访问页面或刷新页面)。
// createHandlerBoundToURL('index.html'):创建一个处理器,将所有导航请求引导到 index.html。这对单页应用(SPA)很有用,因为 SPA 依赖客户端路由。
registerRoute(new NavigationRoute(
createHandlerBoundToURL('index.html'),
{ allowlist },
))
VitePWA
VitePWA 是一个用于 Vite 项目的插件,可以让你轻松将 Vite 项目转换为 PWA。它提供了简单的配置方式来启用 Service Worker 和其他 PWA 功能。
(1) VitePWA 的功能
自动生成 manifest.json 文件。
自动注册 Service Worker。
配置缓存策略。
支持推送通知等 PWA 功能。
(2) 配置 VitePWA 插件
在 vite.config.js 文件中引入并配置 VitePWA 插件
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
vue(),
VitePWA({
// 使用的缓存策略,支持 "injectManifest" 和 "generateSW"
// "injectManifest":允许你自定义 Service Worker 逻辑,手动编写 sw.ts 文件
// "generateSW":自动生成 Service Worker 文件
strategies: "injectManifest",
// 指定 Service Worker 的源文件所在目录
// 这里表示 Service Worker 文件在项目的 "src" 目录下
srcDir: "src",
// 定义 Service Worker 文件的文件名
// 在 "src" 目录中,使用 "sw.ts" 作为 Service Worker 文件
filename: "sw.ts",
// 设置注册类型
// "prompt":用户需要手动确认安装
// "autoUpdate":浏览器在检测到更新时会自动更新 Service Worker
registerType: "prompt",
// 控制是否自动注册 Service Worker
// false 表示不自动注册,需要手动调用注册逻辑
injectRegister: false,
// 配置 PWA 资源
// 该选项允许你指定哪些资源需要缓存,以及其他缓存相关的配置
pwaAssets: {
// 是否禁用 PWA 资产
disabled: false, // false 表示启用 PWA 资产缓存
// 是否启用配置文件
config: true,
},
// 应用程序的 manifest 文件配置
manifest: {
// PWA 应用的完整名称
name: "HELLO",
// PWA 应用的短名称
short_name: "HELLO",
// 应用程序的描述
description: "HELLO",
// 应用程序的主题颜色,通常用于控制浏览器地址栏的颜色
theme_color: "#fff",
// PWA 应用的显示模式
// "standalone":以独立应用的形式运行,隐藏浏览器的 UI
display: "standalone",
// 应用的启动 URL
// 通过点击桌面图标启动时的 URL,这里使用相对路径
start_url: './',
// 配置自定义协议处理器
// 允许 PWA 通过自定义协议打开特定 URL
protocol_handlers: [
{
// 自定义的协议名
protocol: `web+pwa`,
// 使用自定义协议时,浏览器会根据协议打开的 URL
// %s 表示 URL 中的自定义数据
url: "/?number=%s",
},
],
// 配置应用的启动处理器
// 控制应用在打开链接时的行为
launch_handler: {
// 设置打开模式
// "focus-existing":如果应用已经在运行,则聚焦现有的应用实例
client_mode: "focus-existing",
},
},
// 使用 Workbox 进行 PWA 的缓存管理
workbox: {
// 配置要缓存的资源文件
// 这里表示缓存所有 `.js`, `.css`, `.html`, `.svg`, `.png`, 和 `.ico` 文件
globPatterns: ['**/*.{js,css,html,svg,png,ico}'],
// 自动清理过时的缓存
cleanupOutdatedCaches: true,
// 让 Service Worker 立即接管所有页面,而不是等待下一次页面刷新
clientsClaim: true,
},
})
],
})
(3) 构建和测试
完成配置后,可以重新构建项目,确保 PWA 配置生效
npm run build
npx http-server dist -S -C example.com+4.pem -K example.com+4-key.pem -p 9090 --index index.html
github下载地址:https://github.com/qulangchuhai/pwa ,有兴趣的可以下载运行体验