PWA 开发指南(一):最简单的 PWA 入门配置

大家好啊我是 HOHO。

PWA 这个技术想必大家都听说过,一个可以把浏览器中的网站转化成桌面端应用的功能。

现在市面上有很多给前端项目部署 PWA 的构建插件,很多都是宣称零配置、开箱即用。但是问题就在这里,入门很简单不代表 PWA 本身很简单。恰恰相反,如果对其机制不了解,随便配置就上线的话,很容易出现各种各样的 bug,比如处理起来相当麻烦的过期缓存问题。

而现在网上的很多文章都是拿着插件的文档搞一个入门 start 介绍就结束了,就更容易会对大家造成误解。

如果你是要给自己的项目部署 PWA,但是又觉得有点无从下手,那么本文就非常适合你。我会通过一系列的文章来全面的介绍下 PWA 相关的生态。整个系列大致分为如下五篇文章:

OK,我们话不多说,直接开始。

了解 PWA 的相关技术

我们先用人话介绍一下 PWA。实际上这个玩意包含两个主要的部件:

  • 一个用于指定 PWA 配置(比如名字、logo)的文件,叫做 manifest.webmanifest
  • 一个前端和后端之间的接口层代理脚本,用于对网站发起的请求进行一些小小的魔改,这个脚本叫做 Service Worker

本篇文章我们先讲来讲讲简单的:manifest.webmanifest

何为 manifest.webmanifest

manifest.webmanifest 说实话没啥东西,虽然这个后缀名有点奇怪,但是他本质上就是一个 json 文件。下面是一个最简单的配置:

json 复制代码
{
  "name": "my-pwa-app",
  "start_url": "/",
  "display": "standalone",
  "icons": [
    {
      "src": "/favicon.svg",
      "sizes": "any",
      "type": "image/svg+xml"
    }
  ]
}

一个名字,一个 logo,没有了。如果你想标准一点,可以用下面这个,具体的配置可以看 这里

json 复制代码
{
  "$schema": "https://json.schemastore.org/web-manifest-combined.json",
  "name": "my-pwa-app",
  "short_name": "my-pwa-app",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#ffffff",
  "lang": "en",
  "scope": "./",
  "icons": [
    {
      "src": "/favicon.svg",
      "sizes": "any",
      "type": "image/svg+xml"
    }
  ]
}

如果这个文件存在,并且其中指定的 logo 文件也能正常获取到。 那么浏览器就明白了,哦~这确实能用的 PWA 应用。它就会在地址栏里给你显示个按钮来提示用户本网站可以安装为 PWA。

至此,你要做的一切工作其实就已经完成了。你的应用现在已经正式成为一个支持 PWA 的应用了。

有的小伙伴可能会诧异,结束了?这就搞完了?

没错,你在网上看到的什么提供离线访问、预先缓存,其实都是可选项。只要你的网站提供了一份可用的 manifest.webmanifest。那它就是一个正式的 PWA 应用。只不过现在 PWA 模式下和浏览器模式下的应用一模一样。

试一下

首先 pnpm create vite 创建一个应用,用什么框架都可以。

在 public 目录下创建 manifest.webmanifest,然后把上面的 json 复制进去。

最后在 index.html 的 header 添加一行代码:<link rel="manifest" href="/manifest.webmanifest" />

刷新页面后就可以看到地址栏里的 PWA 安装按钮了。

实际上就算你不配置这个 manifest,也可以手动把网站安装成 PWA。只不过我们通常不认为这是一个"标准的 PWA 应用",并且这种情况下安装出来的应用 LOGO 是默认的,不是很好看:

我的安装按钮没出现!

如果你实践了一下之后发现地址栏里的安装按钮并没有出现,那你可以按照下面的顺序排查一下。

导致按钮不显示的主要有下面三种可能:

  • manifest.webmanifest 或者 manifest 其中指定的 icons 访问不到 / 返回的响应有问题。
  • manifest.webmanifest 中缺少了关键字段,参考上面最简单配置对比一下。
  • index.html 里没有 link 引入 manifest.webmanifest

第一种情况最常出现,建议不要看代码,直接去浏览器 F12 里看 Network 面板,正常情况下你应该是能看到 manifest.webmanifest 和其中配置的 LOGO 两条 GET 请求的。

如果你发现缺了一条,或者两条都有但是响应是奇奇怪怪的内容(比如一段 html)。那浏览器就不会显示安装按钮。

你也有可能遇到下面的问题,logo 显示的不是你配置的,而是应用名首字母。

这种情况下一般都是 icons 的配置有问题导致的。比如:

  • 文件类型不匹配,例如:src 填的文件后缀名是 .png,但是 type 填的是 image/svg+xml。
  • 图片格式不标准,例如:不是正方形。
  • 图片尺寸和 sizes 不匹配,例如 src 的尺寸是 192x192,但是 sizes 填的是 72x72。

你也可以通过 F12 > Application > Manifest > Installability 来看到具体是为什么安装不了:

总之这个图片确实是比较难搞,尤其是 png,有可能你完全没看出来有什么问题,但是就是不显示。所以推荐大家无脑用 svg,不要用 png。

具体的 icons 说明在 这里

更好的安装页面

眼尖的小伙伴可能在上面的截图里看到了这么一个报错:

这个其实就是在安装时可以配置一些屏幕截图,来给客户更好的介绍你的应用。想要解决这些问题的话,可以在 manifest.webmanifest 里加上这些内容:

json 复制代码
{
  "description": "这是一个超棒的 PWA 演示应用!",
  "screenshots": [
    {
      "src": "screenshot-1.jpg",
      "sizes": "2560x1700",
      "type": "image/jpg",
      "form_factor": "wide",
      "label": "Application"
    },
    {
      "src": "screenshot-2.jpg",
      "sizes": "2560x1700",
      "type": "image/jpg",
      "form_factor": "wide",
      "label": "Application"
    },
    {
      "src": "screenshot-3.jpg",
      "sizes": "2560x1700",
      "type": "image/jpg",
      "form_factor": "narrow",
      "label": "Application"
    }
  ]
}

description 属性是安装时展示的介绍文本,而 screenshots 则是安装时要展示的截图。其中的 form_factor 代表这张截图要展示在哪个平台上:桌面设备(wide)和移动设备(narrow)。注意对应的图片 src 要能访问到哦。

这么配置完之后点击安装按钮就可以看到:

如果你想更详细的进行配置的话,可以参考这篇文档:web.dev/patterns/we...

注意,目前 edge 浏览器不会显示出这些配置的内容。

邀请用户安装 PWA

在配置好 manifest 之后,PWA 应用就已经准备就绪了。我们可以通过浏览器提供的一些 API 来在我们的页面上显示。

核心就是 beforeinstallprompt 事件,这个事件会在浏览器认定网站准备就绪可以安装时触发。这个时间会返回一个对象,对象上暴露了两个属性:

  • .prompt():调用后会立刻展示安装弹窗。
  • .userChoice:一个 promise,会在用户同意或者拒绝后触发。

很简单对吧,比如下面这个 demo:

html 复制代码
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite + TS</title>
  <link rel="manifest" href="/manifest.webmanifest" />
</head>

<body>
  <div id="app" style="display:none;">
    <h1>🎉 PWA 已经就绪</h1>
    <div class="card">
      <button id="add-btn">点此安装</button>
    </div>
  </div>
</body>

<script>
  let deferredPrompt;
  const addBtn = document.querySelector("#add-btn");
  const app = document.querySelector("#app");

  window.addEventListener("beforeinstallprompt", (e) => {
    e.preventDefault();
    deferredPrompt = e;
    // 更新 UI 以通知用户可以添加到主屏幕
    app.style.display = "inline-block";
  });

  addBtn.addEventListener("click", (e) => {
    // 隐藏我们的用户界面,显示安装提示
    addBtn.innerHTML = "用户正在做出选择";
    // 显示之前保存的提示
    deferredPrompt.prompt();
    // 等待用户的响应以决定是否安装应用程序
    deferredPrompt.userChoice.then((choiceResult) => {
      if (choiceResult.outcome === "accepted") {
        console.log("用户接受了安装提示");
      } else {
        console.log("用户拒绝了安装提示");
      }
      addBtn.innerHTML = "点此安装";
      deferredPrompt = null;
    });
  });

</script>
</html>

跑起来就是这样的:

不过说实话,这个用的人并不是很多,而且这个特性并没有达成标准,目前只有 edge 和 chrome 支持,firefox 和 safari 都是不支持的,大家了解一下就好。相关文档可以看 这里

小结

本篇文章简单介绍一下如何启用 pwa 安装,没什么技术含量。如果你只是因为客户的需求想添加这么一个按钮,那按照本篇文章搞一下就行了,省时省力。

如果你想深入研究一下相关技术,或者应用要求需要比较硬的 pwa 能力的话,我在下一篇等你。

参考

相关推荐
HOHO10 小时前
PWA 开发指南(二):service worker 相关生态介绍
pwa
Glink2 个月前
Web PWA的极致,比App更像App
pwa
敲代码的彭于晏7 个月前
除了localStorage、sessionStorage,了解Cache Storage吗?
前端·浏览器·pwa
牛老师讲GIS10 个月前
将自己的网站改造成可安装的PWA
前端·pwa
天涯学馆1 年前
PWA离线体验:离线页面与App Shell模式
前端·javascript·pwa
Amd7941 年前
Vue第三方库与插件实战手册
vue·echarts·d3.js·数据处理·pwa·验证·chart.js
黑匣子~1 年前
PWA集成和离线使用
前端·google·uniapp·pwa
胖蔡1 年前
vite-plugin-pwa 离线安装Vite应用
前端·pwa
IronLu2331 年前
让Web应用支持Face ID和指纹一键登录,产品经理对我猛夸!速来看实现原理(附源码)
前端·pwa