浅谈PWA

一、PWA是什么

1、直观感受

可以直接访问 PWA 直接的感受下PWA长什么样。访问了上述网站之后,可以在浏览器的地址栏中看到一个下载的图标,点击下载之后就会下载一个本地应用,这个就是PWA了, 这个PWA的功能就是可以双击全屏的一个黑色图片。这个 PWA 在断网的情况下也可以正常访问。

image.png

2、传统WEB和原生应用

在深入探讨PWA(Progressive Web App)之前,我们有必要回顾Web与原生应用的技术博弈史。现代浏览器已从简单的文档解析器演进为功能完备的运行时环境——Chrome浏览器整合了超过50个核心子系统,支持WebAssembly、WebGL、WebRTC等尖端技术规范,其复杂度堪比轻量级操作系统。据统计,全球Top 1000应用中有72%已提供对应的Web版本(数据来源:HTTP Archive 2023),印证了"浏览器即平台"的技术趋势。

然而,传统Web应用在用户体验层面仍面临双重挑战:

  • 网络依赖性:全球仍有17%的移动用户处于2G/3G网络环境(GSMA 2023数据),传统网页在离线场景下的不可用性导致关键业务中断
  • 性能瓶颈:移动端网页平均加载时间超过3秒时,53%的用户会选择离开(Google Core Web Vitals报告)

相比之下,原生应用凭借以下优势占据移动生态:
✅ 本地资源预加载带来的60fps流畅交互
✅ 后台同步、推送通知等系统级功能集成
✅ 基于Metal/Vulkan的图形渲染性能

但原生开发的高昂成本不容忽视:
⛔ 多平台(iOS/Android/Windows)需维护独立代码库
⛔ 平均安装包体积达82MB(Android Studio 2023统计)
⛔ 应用商店审核导致更新延迟(平均72小时)

3、PWA

好了,在了解了app应用和网页应用的优缺点之后,我们再来看看PWA。
首先什么是PWA?PWA的全称是progressive web app,直译就是渐进式web应用。这里web应用应该很好理解,说明PWA是一个基于网页的应用程序。
那什么是渐进式呢?我们都知道渐进的意思是从一个东西慢慢变成另一个东西,中间是有过度过程的,那这里说的渐进式是指的从什么过度到什么呢?实际上这里指的是从网页应用逐步的变成原生应用。也就是说PWA是一个集合了网页应用和原生应用特性的集合体。

二、PWA的特点

在简单了解什么是PWA之后,我们来看看PWA有什么特点。

2.1、PWA 具有网站的优势

  • PWA 是使用标准的 web 平台技术开发的,也就是我们所熟悉的html、css、js,所以它们可以从单一代码库在多个操作系统和设备类上运行。
  • PWA 可以直接通过 web 访问。

2.2、PWA 可以安装在设备上

  • PWA 可以从平台的应用商店安装,也可以直接从 web 安装。
  • PWA 可以像平台特定的应用程序一样安装,并可以自定义安装过程。
  • 一旦安装,PWA 会在设备上得到一个应用图标,与平台特定应用程序一样。
  • 一旦安装,PWA 可以作为独立的应用程序启动,而不是作为浏览器中的网站。
  • PWA 可以在后台与离线操作:一个典型的网站只在被浏览器加载后才处于活动状态。PWA 可以:
    • 在设备没有网络连接时工作。
    • 在后台更新内容。
    • 对来自服务器的推送消息做出响应。
    • 使用操作系统的通知系统显示通知。
  • PWA 可以使用整个屏幕,而不是在浏览器 UI 中运行。
  • PWA 可以与设备集成,注册为共享目标和来源,并访问设备特性。
  • PWA 可以在应用商店以及通过 web 公开发布。

简而言之,PWA就是一个集成了传统网站和应用app优点的集合。

好了,上面介绍了传统web、原生app、PWA,我们用一个表格来总结下3者的特点:

维度 原生应用 传统Web PWA
安装体积 50-200MB 0 50-500KB (预缓存资源)
网络依赖 可选功能离线 完全依赖网络 核心功能离线
系统集成 完整API访问 受限访问 渐进式API访问
更新机制 应用商店审核 即时更新 静默更新+版本控制
跨平台成本 多代码库 单一代码库 单一代码库+平台适配层

三、实现一个PWA

上面解释了这么多什么是PWA,以及PWA的特点,对于程序员来说都太虚了,让我们进入到程序员最关心的步骤,实现一个PWA。

talk is cheap,show me the code

3.1、PWA的组成

一个最简单的PWA由3个文件组成,一个是html文件,用于展示内容,一个manifest.json文件用于描述PWA,一个service work也就是js文件。

├── src/
│   ├── index.html         # 应用入口
│   ├── manifest.webmanifest # 安装描述文件 
│   └── sw.js             # Service Worker核心
├── public/                # 静态资源
│   ├── icons/
│   │   ├── icon-512.webp  
│   │   └── maskable-icon.webp
│   └── splash/
│       └── splash-1080p.jpg
└── server.js             # 本地开发服务器

3.2、PWA版本的hello world

3.2.1、helloworld.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello PWA</title>
    <!-- 引入Web App Manifest -->
    <link rel="manifest" href="/manifest.json">
</head>
<body>
    <h1>Hello World</h1>
    <!-- 注册Service Worker -->
    <script>
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('/sw.js')
                .then(reg => console.log('ServiceWorker已注册'))
                .catch(err => console.log('注册失败:', err));
        }
    </script>
</body>
</html>
  • 这个html文件的功能就是在网页上显示一句hello world
  • 要实现PWA,和普通的html文件相比,多了2个东西,
    • 在head中要引入manifest文件
    • 在script代码块中加载sw.js,也就是service work

3.2.2、manifest文件

{
    "name": "Hello PWA",
    "short_name": "PWA Demo",
    "start_url": "/",
    "display": "standalone",
    "background_color": "#ffffff",
    "theme_color": "#3498db",
    "icons": [
      {
        "src": "/images/icon-512x512.png",
        "type": "image/png",
        "sizes": "512x512"
      },
      
      {
        "src": "/images/icon-512x512.png",
        "type": "image/png",
        "sizes": "512x512",
        "purpose": "maskable"
      }
  ]
}

这个就是PWA应用需要的manifest文件,下面我详细解释下每个参数的作用

3.2.2.1、基础标识字段

字段 作用
name "Hello PWA" 应用全名,显示在浏览器安装提示、启动画面、应用商店
short_name "PWA Demo" 短名称,用于主屏幕图标下方、任务切换器

3.2.2.2、 视觉呈现控制

字段 作用
display "standalone" 显示模式控制: standalone:隐藏地址栏和浏览器控件,fullscreen:全屏(适合游戏),minimal-ui:保留基础导航控件
background_color "#ffffff" 启动画面背景色(必须与CSS背景一致)
theme_color "#3498db" 控制浏览器地址栏/状态栏颜色

3.2.2.3、导航与启动

字段 作用
start_url "/" 用户点击图标后加载的初始页面; 支持带参数路径(如/?from=pwa)

3.2.2.4、 图标配置(核心重点)

"icons": [
  {
    "src": "/images/icon-512x512.png",
    "type": "image/png", 
    "sizes": "512x512"
  },
  {
    "src": "/images/icon-512x512.png",
    "type": "image/png",
    "sizes": "512x512",
    "purpose": "maskable"
  }
]

关键配置说明:

  • src
    图标文件路径(需确保服务器可访问该路径)
    问题提醒:当前两个图标使用相同文件,建议提供不同尺寸(至少包含 192x192 和 512x512)

  • sizes
    声明图标尺寸,浏览器自动选择最合适的
    必须与文件实际尺寸一致(否则会拉伸失真)

  • purpose

    • maskable:允许操作系统对图标进行遮罩处理(适配圆角/特殊形状的图标显示)
    • any:默认值,图标完整显示不裁剪
    • 推荐至少提供一个 maskable 图标(提升安卓设备显示效果)

3.3.3、 sw.js文件

const CACHE_NAME = 'hello-pwa-v1';
const urlsToCache = ['/', '/helloworld.html'];

// 安装阶段:缓存核心资源
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))
    );
});

这个就是PWA应用需要的service worker,通过上面的注释就可以看到,这个service worker主要实现了2个功能,一个是安装PWA到本地,一个是拦截用户的http请求,优先返回缓存中的内容,urlsToCache变量中定义了要缓存的内容。这里缓存的是helloworld.html文件内容。这样在断网的情况下也可以继续访问helloworld.html的内容。

有了以上3个文件, 一个PWA就完成了,可以在本地起一个服务运行上面的网页,就可以看到浏览器上出现了按照PWA的按钮,点击之后就会下载PWA到本地。后面断网之后仍然可以访问hellworld.html的内容。

上面就是PWA应用的hello world版本,大家可以自己尝试下。

4、启程时刻

PWA不是昙花一现的技术热潮,而是重塑Web生态的里程碑。从本文的Hello World出发,您已掌握打开新世界的钥匙。当您下次在地铁无网络环境下流畅打开自己的PWA应用时,或许会真切感受到——Web的未来,此刻正在您手中构建。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容