Progressive Web App (PWA)

1. 什么是 PWA?

Progressive Web App (渐进式 Web 应用) 是一种结合 Web 的开放性Native App 的体验 的技术方案。

核心目标:让网站具备 类原生应用体验 ,包括 离线可用、可安装、推送通知、性能优化 等。

PWA 三大核心特性:

  1. 可靠 (Reliable)

    • 离线可用,弱网环境下也能快速打开
  2. 快速 (Fast)

    • 使用缓存和异步加载,用户体验接近原生
  3. 沉浸式 (Engaging)

    • 可添加到桌面,支持推送,独立运行

2. PWA 的核心组件

2.1 Manifest.json

  • 定义应用的 元信息,比如图标、启动页、显示模式。
  • 控制 "添加到主屏幕" 的行为。

示例:

JSON 复制代码
{
  "id": "test",
  "name": "test",
  "short_name": "test",
  "version": "1.0.0",
  "description": "Progressive Web App for main",
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "https://example/icon-72.png",
      "sizes": "72x72",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-96.png",
      "sizes": "96x96",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-128.png",
      "sizes": "128x128",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-144.png",
      "sizes": "144x144",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-152.png",
      "sizes": "152x152",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-384.png",
      "sizes": "384x384",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "https://example/icon-1024.png",
      "sizes": "1024x1024",
      "type": "image/png",
      "purpose": "any"
    }
  ],
  "created": "2025-09-26T10:56:46.822Z"
}

2.2 Service Worker

  • 核心:拦截网络请求,提供缓存能力。
  • 生命周期:install → activate → fetch

示例:

JS 复制代码
// 消息推送(可选)
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-messaging-compat.js');

firebase.initializeApp({
  apiKey: apiKey,
  authDomain: authDomain,
  projectId: projectId,
  storageBucket: storageBucket,
  messagingSenderId: messagingSenderId,
  appId: appId
});

const messaging = firebase.messaging();

messaging.onBackgroundMessage(function(payload) {
  console.log('[SW] Background message received:', payload);

  const notificationTitle = payload.notification?.title || "New Notification";
  const notificationOptions = {
    body: payload.notification?.body,
    icon: payload.notification?.icon
  };

  self.registration.showNotification(notificationTitle, notificationOptions);
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  if (payload?.data?.link) {
    event.waitUntil(clients.openWindow(payload.data.link));
  }
});

const SW_VERSION = '1.0.1'; // 每次改版本号,都会强制刷新

// Service Worker for main
const CACHE_NAME = `main-${SW_VERSION}`;
const urlsToCache = [
  '/',
  '/index.html',
  '/styles.css',
  '/app.js',
  '/manifest.json'
];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(urlsToCache))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => response || fetch(event.request))
  );
});

self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (cacheName !== CACHE_NAME) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

2.3 HTTPS 要求

  • PWA 必须运行在 HTTPS 环境下(保证安全,避免篡改)。
  • 本地调试例外:http://localhost

3. PWA 的关键概念

3.1 start_url

  • PWA 从桌面启动时的入口 URL。
  • 一般要加上 参数 (如 ?source=pwa)用来区分普通访问。

3.2 scope

  • Service WorkerManifest 的作用范围。
  • 超出 scope 的页面不会受控制,会跳到浏览器打开。

3.3 display 模式

  • "fullscreen":全屏运行(游戏常用)。
  • "standalone":独立应用壳,去掉浏览器 UI。
  • "minimal-ui":精简导航栏。
  • "browser":普通网页模式。

4. PWA 的特性

可安装 :添加到主屏幕,独立运行

离线支持 :通过缓存策略快速加载

推送通知 :结合 Web Push 提高用户回访率

跨平台 :支持 Android、桌面 Chrome、Edge

⚠️ 限制:iOS Safari 支持较弱(推送、后台任务受限)

5. 典型应用场景

  • 游戏:降低安装门槛(点击即玩),弱网环境友好
  • 电商:离线浏览商品,提升转化率
  • 内容平台:支持离线阅读、推送提醒
  • 企业应用:跨平台内部工具,无需发布到应用商店

6. PWA 的最佳实践

  1. 缓存策略

    • 静态资源用 Cache First
    • API 数据用 Network FirstStale-While-Revalidate
  2. 版本管理

    • Service Worker 更新机制:旧版本要 skipWaiting,避免用户卡在旧缓存
  3. 埋点分析

    • 区分 PWA 与 Web 用户来源(可在 start_url 中加参数)
  4. 体验优化

    • 自定义加载动画
    • 离线提示页面
    • 保持 scopestart_url 一致,避免出现多个独立 PWA 实例

7. 总结

  • PWA = Web + Native 体验
  • 三要素:Manifest + Service Worker + HTTPS
  • 优点:轻量、跨平台、降低安装门槛
  • 局限:iOS 支持不足,部分 API 受限
  • 应用场景:游戏、电商、内容、工具

🚀 一句话总结

PWA 不是要取代原生应用,而是为 Web 提供接近原生的体验,降低获客和使用门槛。

相关推荐
愚昧之山绝望之谷开悟之坡12 分钟前
什么是uv和传统的区别
前端·chrome·uv
SRC_BLUE_1722 分钟前
NSSCTF - Web | 【第五空间 2021】pklovecloud
android·前端
golang学习记22 分钟前
从0死磕全栈之Next.js 数据安全实战指南:从零信任到安全架构
前端
云中雾丽24 分钟前
flutter中 getx 的使用
前端
Jay丶42 分钟前
聊聊入职新公司两个月,试用期没过这件事
前端·面试
ZTeam前端全栈进阶圈1 小时前
Vue新技巧:<style>标签里的 CSS 也能响应式!
前端
ღ_23331 小时前
vue3二次封装element-plus表格,slot透传,动态slot。
前端·javascript·vue.js
摸着石头过河的石头1 小时前
JavaScript继承的多种实现方式详解
前端·javascript
ybb_ymm1 小时前
前端开发之ps基本使用
前端·css
Ashley的成长之路1 小时前
NativeScript-Vue 开发指南:直接使用 Vue构建原生移动应用
前端·javascript·vue.js