Skip to content

PWA

渐进式 web 应用(PWA)是一种使用 web 平台技术构建的应用,但它提供了类似于平台特定应用的用户体验。

传统上,网站更像是“用户访问的地方”,而不是“用户拥有的东西”。通常,一个网站:在用户不访问它时,在用户的设备上没有存在感,只能通过用户打开浏览器并导航到该网站来访问,而且高度依赖于网络连接。

而平台特定应用是针对特定操作系统(OS)和/或设备类别开发的,例如 iOS 或 Android 设备,通常使用平台供应商提供的 SDK。它们通常通过供应商的应用商店分发,用户可以在那里找到和安装它们,它们随后对用户来说就像是他们设备的一个永久附加特性,以某种方式扩展了其功能。

渐进式 web 应用结合了传统网站和平台特定应用的最佳特性:

  • PWA 是使用标准的 web 平台技术开发的,所以它们可以从单一代码库在多个操作系统和设备类上运行。
  • PWA 可以直接通过 web 访问。
  • PWA 可以安装在设备上。
  • PWA 可以在后台与离线操作。
  • PWA 可以使用整个屏幕,而不是在浏览器 UI 中运行。
  • PWA 可以与设备集成,注册为共享目标和来源,并访问设备特性。
  • PWA 可以在应用商店以及通过 web 公开发布。

下图为我的主站 ImQi1 在华为平板上开启 PWA 前后访问的界面。

开启PWA前

开启PWA后

开启 PWA 后,桌面上多了一个 ImQi1 的图标,点进去就是第二张图的样子,没有浏览器的操作界面了,完全就像安卓的原生应用。

安装 - Manifest

首先,新建一个manifest文件,它用于定义安装后应用的基本信息。如ImQi1主站:

json
{
  "name": "ImQi1",
  "short_name": "ImQi1",
  "start_url": "https://imqi1.com/",
  "display": "standalone",
  "background_color": "#ffffff",
  "scope": "/",
  "description": "做技术的分享者、生活的摄影师、时事的评论员。",
  "theme_color": "#f9fafb",
  "lang": "zh-CN",
  "icons": [
    {
      "src": "/static/img/imqi1-64.png",
      "sizes": "64x64",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/static/img/imqi1-144.png",
      "sizes": "144x144",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/static/img/imqi1-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ]
}

这里解释一下比较重要的属性:

  • start_url:指定网页的初始打开地址,要和网页加载时的URL保持一致,否则浏览器会忽略 manifest 文件。
  • nameshort_name:应用名称。
  • display:展示的界面尺寸占整个屏幕的大小,这里是 standalone,表示应用程序将在自己的窗口中显示,没有浏览器的导航控件。
  • scope:指定应用程序的范围或生命周期,这里的 "/" 指应用程序在加载时将在当前浏览器标签中打开,并与其它页面共享浏览器历史记录。
  • icon:指定应用程序在桌面上的显示图标,这里推荐至少准备三个尺寸的,从 64 到 512 的。

创建好这个文件后,在浏览器的 <head> 标签中引入如下内容。

html
<link rel="manifest" href="/path/to/your/imqi1-manifest.json">

将路径改为你的 Manifest 的路径,这样第一步就完成了。

安装 - Service Worker

这部分可能有点绕,可以先看个整体了解下原理,再跟着做。

第二步是创建 Service Worker,在网页的合适的部分嵌入下面的代码,或将 JavaScript 代码嵌入到网页的 JS 文件中,比如 service-worker.js

js
importScripts('https://static.qi1.website/js/pwa-sw.js');
if (workbox) {
    console.log(`Workbox成功加载`);
} else {
    console.log(`Workbox加载失败`);
}
workbox.routing.registerRoute(new RegExp('.*\.(?:js|css)'), workbox.strategies.staleWhileRevalidate({
    cacheName: 'css&js-cache',
    plugins: [new workbox.cacheableResponse.Plugin({statuses: [0, 200]}), new workbox.expiration.Plugin({
        maxEntries: 200,
        maxAgeSeconds: 7 * 24 * 60 * 60,
    })]
}));

这里的示例脚本中引用了本教程提供的 Service Worker JS 文件。

.*.(?:js|css)用于匹配以js和css结尾的文件,并缓存7天。你可以根据你的站点制定更详细的缓存规则。

这里需要引入本站存储的 Service Worker JS 文件,你可以将这个 JS 文件下载到你的服务器上然后引用你的地址。

最后,注册 Service Worker 即可。

js
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js'); }); }

将这段代码放在 HTML 中靠后的位置。

总结一下,先创建 Manifest 文件,然后在 head 中引入这个文件,引入了实际上网页就已经支持 PWA 了。然后就是创建 Service Worker 文件,首先创建一个 sw.js 文件,并在 HTML 中引用它,sw.js 文件中填写 importScripts 那部分代码。然后若你在这部分代码中导入的是本教程提供的地址,则直接做最后一步,就是在 script 中注册 Service Worker,就是 if ('serviceWorker' in navigator) 那部分。

验证

接下来我们可以通过以下步骤查看网页是否支持 PWA 了,首先我们先在网页中点击 F12,然后点击【应用】,在应用里可以查看 Service Worker 是否安装成功。

我们也可以查看地址栏中是否有 “安装” 的按钮。

进阶

有时,我们希望用户能看到提示安装 PWA 的按钮,我们可以为网页添加一个按钮,在用户点击之后引导用户安装 PWA。

假设你的按钮 ID 值为 button,如 <button id="button">安装</button>,那么你可以为 #button 添加事件监听,具体:

html
<button id="button">安装</button>

<script>
    const installButton = document.getElementById('button');
    window.addEventListener('appinstalled', () => {
        deferredPrompt = null;
    });
    window.addEventListener('beforeinstallprompt', (event) => {
        event.preventDefault();
        window.deferredPrompt = event;
    });
    installButton.addEventListener('click', async () => {
        const promptEvent = window.deferredPrompt;
        if (!promptEvent) {
            return;
        }
        promptEvent.prompt();
        const result = await promptEvent.userChoice;
        window.deferredPrompt = null;
    });
</script>

本站还提供了一个 PWA 优化文件,它是谷歌推出的,可以解决跨平台的兼容问题,如Safari不能完整地支持PWA,需要加一些额外的处理,使用这个库就可以省去这些处理。

使用方法就是直接引用这个 JS 文件,它会自动检测网页的 Manifest文件,然后为 HTML 添加必要的标签来优化 PWA。

html
<script async src="https://static.qi1.website/js/pwa-pwacompat.js"></script>

为方便开发而创建的常用库指南