手把手带您从0搭建自己的第一个PWA应用

网文介绍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 buildnpx 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 ,有兴趣的可以下载运行体验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值