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 提供接近原生的体验,降低获客和使用门槛。

相关推荐
沢田纲吉2 小时前
《LLVM IR 学习手记(二):变量表达式编译器的实现与深入解析》
前端·编程语言·llvm
小徐_23332 小时前
VitePress 博客变身 APP,支持离线访问,只需这一招。
前端·vitepress·pwa
猪哥帅过吴彦祖2 小时前
第 5 篇:WebGL 从 2D 到 3D - 坐标系、透视与相机
前端·javascript·webgl
折七2 小时前
expo sdk53+ 集成极光推送消息推送 ios swift
前端·javascript·ios
猪哥帅过吴彦祖2 小时前
Flutter 系列教程:布局基础 (上) - `Container`, `Row`, `Column`, `Flex`
前端·flutter·ios
lifejump2 小时前
DVWA | XSS 跨站脚本注入
前端·xss
gplitems1232 小时前
Tripfery - Travel & Tour Booking WordPress Theme Tested
前端
流星稍逝2 小时前
前端&后端解决跨域的方法
前端·后端
白水清风2 小时前
【基础】关于函数式编程的知识
前端·javascript·面试