Service worker (@nuxtjs/workbox) 采坑记

CarterLi

PWA(Progressive Web App)是前端的大趋势,它能极大的加快前端页面的加载速度,得到近乎原生 app 的展示效果(其实难说)。PWA 其实是多种前端技术的组合,其中最重要的一个技术就是 service worker。

Service worker 在 MDN 上的说明:

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。

其实不用太纠结,简单起见我们就把它当成更高级更先进的 AppCache 就好了。

在 nuxt(Vue) 网站中启用 Service worker

借近期公司官网升级之机,我也给公司官网上了 Service worker 做离线缓存。

大前提:Service worker 只可在 https(或 localhost)下使用,首先确保你的网站上了 https

在 nuxt 程序中启用 Service worker 非常方便。nuxt 提供了官方 module——pwa-module 用于支持 PWA 网站,其中就包含了用于实现 Service worker 的 workbox moduleworkbox 实际上是指的 google 为简化 Service worker 开发而开源的第三方库。

首先安装依赖

$ yarn add @nuxtjs/pwa @nuxtjs/workbox

然后再配置文件中启用

// modules
module.exports = {
  [ '@nuxtjs/pwa' ]
}

就完成了

SW 使用采坑

官网上线后发现,启用 Service worker 后 Safari 不能播放视频了。但是直接输入视频链接却可以播放。经过各种 google 搜索查资料后找到了官方 issue:

  1. https://github.com/nuxt-commu...
  2. https://github.com/angular/an...

甚至还找到了有人给 webkit(Safari 浏览器内核)开了bug:https://bugs.webkit.org/show_...

状态始终是 new,没有人解决。但 issue 中详细说明了 Safari 的行为以及产生问题的原因

问题的原因在于对于视频文件请求,浏览器会发出带有 Range 头的请求部分获取文件内容。Safari 比较奇葩,对于视频文件请求,它一开始就会发一个 Range: 0-1 的请求,但是 Service worker 中处理请求的逻辑不能识别 Range 请求,把 Range 请求当成普通请求处理,返回了 200。Safari 把 200 当成了失败请求,导致请求视频文件失败。

最后开各人的回帖找到了这里:https://developers.google.com...

然后经过各种尝试(中间过程略),说一下可行方案:

首先添加 js plugin:

// workbox-range-request.js
workbox.routing.registerRoute(
  /.*\.(mp4|webm)/,
  workbox.strategies.cacheFirst({
    plugins: [
      new workbox.rangeRequests.Plugin(),
    ],
  }),
  'GET'
);

这个文件给 workbox 注册一个路由,指定对于视频文件(以 .mp4 或 .webm 结尾的文件。如果你的网站有音频文件也要一并处理)处理程序添加 rangeRequests 插件

然后在配置文件中注册插件:

// modules:
[ '@nuxtjs/pwa', {
  workbox: {
    cachingExtensions: '@/plugins/workbox-range-request.js',
  }
} ],

注意必须使用 cachingExtensions 而不能用 routingExtensions,虽然注册的是路由配置

这样 Service worker 就可以处理带 Range 头的请求了,但是还不算完。workbox 会请求 googlecdn 动态加载 js 脚本,如果你身在兲朝,由于众所周知的原因加载脚本会失败。

解决方案:

  1. 首先去 workbox 官网下载 release 包(笔者用的是 3.5.0 版本):https://github.com/GoogleChro...
  2. 解压后放在你项目的 static 文件夹下,笔者是 static/workbox-v3.5.0
  3. 修改配置
// modules:
[ '@nuxtjs/pwa', {
  meta: false,
  workbox: {
    config: { modulePathPrefix: '/workbox-v3.5.0' },
    cachingExtensions: '@/plugins/workbox-range-request.js',
  }
} ],

配置中指定 workbox 从 /workbox-v3.5.0 这个路径加载 js 脚本,而不走 googlecdn。

注意配置中使用的 config 当前版本(@nuxtjs/pwa@2.5.0, 2018-09-20)还不支持,笔者给官方仓库开了 Pull request 还在审核中,笔者是直接修改了 node_modules 里的文件。

在上 Service worker 之前最好想清楚。这玩意和 AppCache 一样,上线简单,想要下线就难了

请上公司官网体验效果:https://www.eoitek.com

clipboard.png

阅读 6k

我大EOI前端
[链接] 虽然公司尚小,但是志向不小
1.3k 声望
99 粉丝
0 条评论
1.3k 声望
99 粉丝
文章目录
宣传栏