Google Play 上架难?手把手教您从0搭建自己的第一个PWA应用!

464 阅读9分钟

网文介绍PWA是什么的文章一大堆,本文不再过多阐述,PWA能火起来,定然有它的优势!但大部分人关注PWA,大多因为以下几点:

1. GooglePlay或者AppStore上不去架。

2. 意图绕开商店支付,降低支付抽佣压力,提高自身利润。

3. 单纯地想增加一个获客来源。

4. 自用的内部工具类App

PWA虽然有它的优势,但依旧无法和主流应用市场带给开发者的流量有可比性,如果能上架开展业务肯定是最优选择。当然,对于H5游戏出海和不需要获取用户设备信息的应用,例如AI、工具、社交与短剧等也都可以尝试,扩展自身获客来源,增加收入。

接下来,由小编手把手教您从0搭建自己的第一个PWA应用,开展一次新的技术尝试吧! 

友情提醒:不想看具体分析过程的朋友可以直接滑到PWA示例视频及Demo链接。观看示例视频和下载Github Demo运行体验哈。

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 buildnpx http-server dist -S -C example.com+4.pem -K example.com+4-key.pem -p 9090 --index index.html

PWA示例视频及Demo链接

github下载地址:github.com/qulangchuha…

目前掘金不支持插入视频,如果需要,可联系小编获取。

App出海交流群,寻找志同道合的你

经常分享Google Play,App Store市场政策解决方案,大家共同深入了解应用市场App上架、下架背后的原因,如政策违规、安全漏洞、版权问题、市场策略调整等,确保海外App合规、安全并提升我们的用户体验。也不限于分享其他App出海快讯,一起见证行业的蓬勃发展。

欢迎您来到App出海交流群讨论出海的任何问题!想进群的可以点击这里,或者关注公众号趣浪出海,我拉您进来。

这是一个高质量的属于App出海浪潮儿的技术交流中心!

在这里,都是一群热衷于在海外发展的人群:

1、你的各种谷歌&苹果应用上架问题都能得到解决。

2、你可以了解到各种最新的谷歌&苹果政策更新。

3、你可以获得每日的应用上架数据,了解谷歌&苹果审核严松状态。

4、你可以获得各种资源信息,助力企业出海。

推荐阅读(更多问题咨询请点击这里 ****或者关注****vx 趣浪出海)

Google Play上架审核时间过长?要不要催审!

这都能封!开发者行为导致Google账号关联?

另类封号!别让你的Google老账号为你的粗心买单

GooglePlay账号关联审查机制详解