为vue项目添加PWA支持

2022-5-16 18:45| 发布者: Hocassian| 查看: 48| 评论: 0|原作者: 神代綺凜

摘要:
C:\Users\Administrator\Downloads\神代綺凜\2019-10-15-14-34-56-19827213465400-文章归档 - 神代綺凜の萌化小基地-采集的数据-后羿采集器.html

标题

为 vue 项目添加 PWA 支持

标题链接

https://moe.best/nodejs-memo/vue-paw.html

正文

前段时间摸鱼终于摸到了 Service Worker 这块,顺理成章的接触了 PWA,于是用这篇文章记录下如何为一个 vue 应用添加 PWA 支持,包括中途遇到的一些坑点和一些技巧

Head Pic:【オリジナル】「Recital」/「RH」的插画 [pixiv]

vue & PWA

如果您的目的不是为现有的 vue 项目添加 PWA 支持,那么更推荐尝试 Lavas

注:PWA 应用要求必须全程 https,且在已安装的 PWA 应用中无法发送 http 请求

为已有项目添加 PWA 支持

1. 安装 PWA 插件

如果你已经在使用@vue/cli,那么可以直接在可视化界面中安装 PWA 插件

否则,可以通过vue add @vue/pwa命令来安装

该插件会使用谷歌的 PWA 框架 Workbox

2. 配置 PWA 插件

需要创建或修改项目中的vue.config.js,配置项以及示例在此处

我想多提几句的配置项有三个:

workboxPluginMode

可选配置项,默认为GenerateSW

GenerateSWInjectManifest如何选择:

  • 如果你只是想简单地将项目 PWA 化,选择GenerateSW,插件会自动帮你生成包含 precache manifest 的service-worker.js
  • 如果你有较高的定制需求,需要在已有 Service Worker 的基础上将项目 PWA 化,则选择InjectManifest,插件会在你指定的service-worker.js的基础上加入 precache manifest

workboxOptions

配置项,请对应workboxPluginMode来参考

通过配置可以做到的一些常用操作:

  1. 将指定(或指定文件夹中的)文件添加到 precache manifest 中,或从中排除,支持使用正则表达式
  2. 自动跳过 Service Worker 的等待阶段
  3. 添加离线 Google Analytics 支持
  4. 运行时缓存runtimeCaching,Workbox 的强大所在,阅读这些内容会使你更好地了解如何配置以及具体能做什么:

iconPaths

该设置项可以自定义在页面<head>中添加的一些图标的<link><meta>中指定的文件路径

public/icons中有安装插件时生成的默认图标

其有一个坑点,就是你无法设置不去添加某些<link><meta>,也就是强制性的

这主要会影响到maskIcon,是 Macbook 的 Touch Bar 上的图标,由于要求必须是 svg,个人开发的小应用一般懒得去制作这个图标,但又无法不去添加这个<link>

3. 配置manifest.json

位于public/manifest.json,安装插件时自动生成,参考 Web App Manifest 进行配置

引导用户添加 PWA 应用

在应用中可以自行通过提示等方式引导用户手动添加 PWA 应用,以下列举目前我所知道的添加方式

Chrome 专有方式

对于 PC 或 Android 的 Chrome 浏览器都可以实现点击一个按钮来添加 PWA 应用,其原理是拦截了beforeinstallprompt这一事件,并在自己需要的时候触发

例如我们可以在项目的根 vue 实例中(以下示例省略了挂载及渲染等操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new Vue({ data: { deferredPrompt: false }, created() { window.addEventListener('beforeinstallprompt', e => { e.preventDefault(); this.deferredPrompt = e; }); }, methods: { installPWA() { if (this.deferredPrompt) { this.deferredPrompt.prompt(); this.deferredPrompt = false; } } } });

然后就可以像这样自由地在任何 template 中使用了

1
<button @click="$root.installPWA" :disabled="$root.deferredPrompt===false">添加到主屏幕</button>

手动添加方式

iOS ≥ 11.3 可以在 Safari 中打开,点击浏览器底部的分享按钮,选择“添加到主屏幕”

PC 与 Android 的 Chrome 可通过右上角菜单添加(此处以 m.weibo.cn 为例)

PC Android

Service Worker 的更新

这是开发 PWA 应用时需要考虑的一个重要问题

由于 Service Worker 的更新机制(扩展阅读:【Service Worker】生命周期那些事儿),直接单纯的刷新页面并没有结束当前 session,因此依然是旧的 SW 在接管页面,新的 SW 仍旧是 waiting 状态

想要实现在不结束 session 的情况下更新 SW,必须使用 skipWaiting,目前有两种常见的处理方法

注:以下方法中提到的registerServiceWorker.js是由 PWA 插件在src目录中自动生成的,其作用是注册 SW 以及提供其生命周期钩子,具体可以看该 npm 包 register-service-worker

方法一:直接 skipWaiting,并引导用户刷新

这种方法非常暴力且简单,你只需要在步骤2提到的workboxOptions中将skipWaiting设置为true就行了,然后在registerServiceWorker.js中的updated()函数里做一些操作,例如弹出一个对话框来提示用户点击某个按钮以刷新页面

该方法对仅 precache 应用是没有任何影响的

但由于 skipWaiting 后新 SW 会立即接管页面,因此如果你更新了 SW 在处理 runtimeCaching 之类的运行时操作的行为而用户又没有刷新页面,就有可能会出现问题

即除非你能保证同一个页面在两个版本的 SW 相继处理的情况下依然能够正常工作,否则不要使用这个方法

方法二:等待用户同意再 skipWaiting 并刷新

该方法可以解决方法一的局限性,我们可以先弹出一个对话框询问用户是否要更新,用户同意后再 skipWaiting 并刷新

关于这种方法,我只描述大致的思路和做法,因为我没有实际完整地实践过,因为比较复杂麻烦(好的下面我就开始云了)

我们需要在workboxOptions中将skipWaiting设置为false,或者不设置,因为默认值为false

此处,官方文档中提到,当skipWaitingfalse的时候,生成的 SW 会加入以下代码

1
2
3
4
5
self.addEventListener('message', (event) => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting(); } });

其作用是当 SW 接收到{type:'SKIP_WAITING'}的消息后,SW 就会 skipWaiting

但实际情况是,最终生成的 SW 中并没有这一段代码(也并没有放置在其他 js 中),我猜测这可能是因为加入代码的这一特性是 Workbox 4 才加入的,而插件生成的 SW 引用的是 Workbox 3 的缘故……

对于这个问题有两种可能的解决方法:

  1. workboxPluginMode设置为InjectManifest,然后自己指定一个 SW 里面加上该代码内容
  2. 从谷歌那里下载最新的 Workbox 放置在项目内,并配置workboxOptions中的importWorkboxFromdisable,然后在importScripts中指定本地workbox-sw.js的路径

接着在registerServiceWorker.js中我们可以如下所示在updated()函数中加入一些内容,询问用户是否愿意重载页面以更新应用,若用户同意则向 waiting 状态的 SW 发送{type:'SKIP_WAITING'}消息,并在新 SW 控制页面后立即刷新

1
2
3
4
5
6
7
8
9
10
11
12
updated(reg) { // 当控制页面的 SW 改变时刷新 let refreshing = false; navigator.serviceWorker.addEventListener('controllerchange', () => { if (refreshing) return; window.location.reload(); refreshing = true; }); // 接下来询问用户是否更新并重载应用 // 用户同意则执行以下语句 reg.waiting.postMessage({ type: 'SKIP_WAITING' }); }
搬瓦工VPS优惠套餐,建站稳如狗,支持支付宝,循环出账94折优惠码BWH26FXH3HIQ
年付$28CN2线路,1核/512M内存/10G硬盘/500GB@1Gbps【点击购买】(经常售罄,请抓紧机会)
年付$47CN2线路,1核/1G内存/20G硬盘/1T@1Gbps【点击购买
最后修改:2019 年 06 月 27 日 12 : 37 AM
如果觉得我的文章对你有用,请随意赞赏

文章信息

中二病患者: 神代綺凜  发布时间:2019 年 06 月 26 日  1926 次浏览   9 条评论  5456 字数 分类: Node.js 笔记


路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部