PWA 安装支持

用 Web App Manifest 提供桌面安装入口,不默认启用 Service Worker

什么是 PWA?

PWA(Progressive Web App,渐进式 Web 应用)是一种让网页「像原生应用一样」运行的技术方案。核心思路是:用标准 Web 技术(HTML + CSS + JS)构建一个应用,然后通过浏览器提供的额外能力(安装到桌面、离线使用、推送通知等),让它的使用体验接近从 App Store 下载的原生应用。

PWA 的核心技术包括:

  • Web App Manifest:一个 JSON 文件,告诉浏览器你的应用名称、图标、启动地址和展示模式
  • Service Worker:一个独立于页面的后台脚本,可以拦截网络请求、缓存资源、发送推送通知
  • HTTPS:PWA 要求站点必须通过 HTTPS 提供服务,这是安全底线

当浏览器检测到 Manifest 且满足条件时,会在地址栏或菜单中显示「安装」入口。用户点击后,网站会以独立窗口的形式安装到桌面,出现在系统应用启动器里——看起来就像原生应用一样。

PWA 适合什么场景?

PWA 最有价值的场景是那些用户需要频繁访问、但又不值得为它下载一个原生 App 的网站:

  • 内容型工具:文档站、博客、知识库、资讯站
  • 管理型工具:Dashboard、后台管理面板、数据监控
  • 轻量工具:计算器、记账本、笔记应用、TODO 管理
  • 电商与展示:产品目录、作品集、轻量商城

对这类场景,PWA 可以显著提升用户黏性——安装后出现在桌面和系统搜索中,用户下次访问的成本大幅降低。

PWA 不适合什么场景?

PWA 的局限也很明显,有些场景不要指望 PWA 能替代原生 App

  • 需要深度硬件访问的应用(蓝牙、NFC、USB、高级相机控制)
  • 高性能游戏或复杂图形渲染(WebGL 性能远不如原生)
  • 需要后台长期运行的任务(iOS 上 Service Worker 会被系统很快杀死)
  • 对推送可靠性要求极高的应用(iOS 推送通知支持极其有限)
  • 需要上架应用商店分发(PWA 无法出现在 App Store / Google Play 的主流入口中)

平台兼容性:一份现实的评估

PWA 在不同平台上的支持程度差异很大。这不是技术问题,而是商业博弈的结果。

Apple iOS / iPadOS — 基本不可用

苹果是 PWA 支持最差的平台,原因很直接:如果 PWA 功能完整,用户就不需要 App Store 了。App Store 是苹果的核心利润来源(30% 抽成),让 Web 应用拥有和原生应用一样的能力,会直接威胁这个商业模式。所以苹果在 PWA 支持上一直消极:

  • 不能推送通知(iOS 16.4+ 虽然在 Home Screen Web App 上有限支持,但需要用户主动授权,且不稳定)
  • 不能后台运行(Service Worker 在后台存活时间极短)
  • 没有 Badge(角标)支持
  • 不能访问大多数原生 API(蓝牙、NFC、Touch ID / Face ID 等)
  • 存储空间限制严格,容易被系统清理
  • 安装入口隐藏极深(必须通过 Safari「添加到主屏幕」,没有浏览器安装横幅)
  • 用户认知度极低(大部分 iPhone 用户不知道可以把网页添加到主屏幕)
  • 2024 年欧盟 DMA 压力下,苹果才被迫宣布有限改善,但实际落地缓慢

结论:如果你的目标用户主要是 iPhone 用户,不要把 PWA 作为核心体验来设计。 它可以作为加分项存在,但不能依赖它提供任何关键功能。

Android — 最好的支持

Android 是 PWA 支持最好的平台,也是 Google 大力推广 PWA 的原因(Google 需要对抗 Apple 的 App Store 垄断):

  • Chrome 会自动显示安装横幅,引导用户安装
  • 安装后出现在桌面、应用抽屉、系统设置中,和原生应用几乎无区别
  • 支持推送通知
  • 支持 Badge
  • Service Worker 存活时间较长
  • 可以注册为 Share Target,出现在系统分享菜单中
  • 部分设备支持通过 Play Store 分发 PWA(Trusted Web Activity)

Windows / macOS (桌面端)

Chrome 和 Edge 在桌面端对 PWA 的支持相当成熟:

  • 安装后以独立窗口打开,有自己的标题栏和任务栏图标
  • 可以固定在任务栏 / Dock
  • 支持推送通知(Windows 上更稳定)
  • 支持 Badge
  • 可以注册为文件处理器、协议处理器
  • Edge 还提供了额外的 PWA 管理功能

桌面端 PWA 对内部工具、Dashboard、后台管理面板这类场景特别实用。用户打开一个独立窗口就像打开一个桌面应用,比在浏览器标签页里管理一堆书签方便得多。

总结

平台PWA 支持程度建议
Android★★★★★PWA 可以作为主力分发方式
Windows★★★★☆适合内部工具和 Dashboard
macOS★★★☆☆能用,但用户认知度低
iOS / iPadOS★☆☆☆☆不要依赖,只作为加分项

概览

01MVP 模板默认提供轻量 PWA 支持。目标不是把网站改造成离线应用,而是让浏览器能识别站点名称、图标和安装方式,让用户可以把站点安装成桌面应用,并在系统应用搜索里找到它。

默认方案只使用 Web App Manifest:

  • 安装后的应用名称使用 01MVP
  • 浏览器可以读取应用图标、启动地址和展示模式
  • 安装后以独立窗口打开,体验接近桌面应用
  • 现有路由、登录、支付、后台页面仍按普通 Web 站点运行

已包含的配置

模板在 apps/01mvp-web/src/app/manifest.ts 中声明 PWA 元信息:

import type { MetadataRoute } from "next";
import { config } from "@/lib/config";

export default function manifest(): MetadataRoute.Manifest {
  return {
    id: "/",
    name: config.appName,
    short_name: "01MVP",
    description: "从想法到上线的 AI 产品实战工具包。",
    start_url: "/",
    scope: "/",
    display: "standalone",
    background_color: "#ffffff",
    theme_color: "#ffffff",
    icons: [
      {
        src: "/icon-192x192.png",
        sizes: "192x192",
        type: "image/png",
      },
      {
        src: "/icon-512x512.png",
        sizes: "512x512",
        type: "image/png",
      },
    ],
  };
}

其中 display: "standalone" 表示用户从桌面应用入口打开时,浏览器会尽量使用独立窗口展示,而不是普通标签页。Chrome、Edge 等浏览器会根据 Manifest、HTTPS、浏览器版本和自身策略决定是否在地址栏或菜单里显示安装入口。

为什么不默认启用 Service Worker

Service Worker 适合做离线能力、资源预缓存、推送通知和后台任务,但它也会成为发布链路的一部分。对 01MVP 这种在线产品模板来说,默认启用它的维护成本高于收益。

常见风险包括:

  • 缓存失效后,用户可能继续看到旧页面或旧 JS
  • 新版本上线后,需要额外处理 Service Worker 更新提示
  • 登录态页面、支付页面、Dashboard、Admin 页面不能被错误缓存
  • API 请求如果被缓存策略误伤,会出现难排查的状态问题
  • 以后每次改路由、认证或静态资源,都要同时考虑缓存策略

所以模板默认不注册 Service Worker。当前目标是“可安装、能被系统搜到、像桌面应用一样打开”,不是“离线 Web App”。

什么时候再加 Service Worker

只有当你的产品明确需要下面这些能力时,再考虑接入 Service Worker:

  • 离线阅读文档或内容
  • 离线 Dashboard,允许用户断网后继续查看或编辑本地数据
  • 推送通知、后台同步或后台任务
  • 需要更精细的静态资源缓存来提升弱网体验
  • 目标浏览器实测后,没有 Service Worker 就无法提供你需要的安装入口

接入时建议从最小缓存策略开始。先只缓存静态资源和离线页,不要缓存登录、支付、后台和 API 响应;确认更新策略稳定后,再逐步扩大范围。

验证方式

本地或线上环境可以用 Chrome DevTools 验证:

  • 打开 Application 面板
  • 查看 Manifest 是否被识别
  • 检查名称、图标、start_urldisplay 是否正确
  • 在线上 HTTPS 域名中测试 Chrome 或 Edge 的安装入口

如果只是改应用名称或图标,更新 manifest.tspublic/ 下的图标文件即可。