PWA系列 - Workbox插件GenerateSW

2,816 阅读2分钟

PWA系列

PWA系列 - 我所知道的 Service Worker

PWA系列 - Workbox插件GenerateSW

PWA系列 - Workbox插件InjectManifest

不论是GenerateSW或是InjectManifest都是对PWA系列 - 我所知道的 Service Worker原生配置的封装,所以首先应该弄懂service workder原始配置

pwa

优势

  • pwa 可离线加载页面
  • pwa 可设置桌面图标,增加用户留存
  • pwa 可发送通知消息
  • pwa 可动态加载加载域名,解决域名防封
  • pwa 运行在浏览器中但是可使用设备特性
  • pwa 可预请求资源文件js,css等,等真正请求时就很快

注意:pwa 在https协议或localhost才可生效

webpack搭建包workbox-webpack-plugin

workbox-webpack-plugin 是谷歌workbox封装为webpack使用pwa的插件,提供GenerateSWInjectManifest两款插件

  • GenerateSW 开箱即用,自动生成serviceWorker和资源配置列表,可配置路由规则
  • InjectManifest 可自定义pwa配置项,更高编程自由

GenerateSW 插件

  • 适用于简单pwa离线缓存
  • 如果需要自定义缓存逻辑,或使用其他消息推送功能用InjectManifest插件

装包

npm install workbox-webpack-plugin -D

vue.config.js 添加插件

const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
module.exports = {
  configureWebpack: () => ({
    plugins: [
      new WorkboxWebpackPlugin.GenerateSW({
        /**
         * 1. 帮助serviceWorker快速启动
         * 2. 删除旧的 serviceWorker
         *
         * 生成一个 service-worker.js 配置文件
         */
        clientsClaim: true,
        skipWaiting: true,
      }),
    ],
  }),
};

main.js 入口添加注册serviceWorker

// 注册 serviceWorker
// 处理兼容性问题
if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then(() => {
        // console.log("sw 注册成功");
      })
      .catch(() => {
        // console.error("sw 注册失败");
      });
  });
}

效果

serviceWorker加载成功

image.png

文件缓存

image.png

验证离线可访问

image.png

更多配置

    new GenerateSW({
      // These are some common options, and not all are required.
      // Consult the docs for more info.
      exclude: [/.../, '...'],
      maximumFileSizeToCacheInBytes: ...,
      navigateFallback: '...',
      runtimeCaching: [{
        // Routing via a matchCallback function:
        urlPattern: ({request, url}) => ...,
        handler: '...',
        options: {
          cacheName: '...',
          expiration: {
            maxEntries: ...,
          },
        },
      }, {
        // Routing via a RegExp:
        urlPattern: new RegExp('...'),
        handler: '...',
        options: {
          cacheName: '...',
          plugins: [..., ...],
        },
      }],
      skipWaiting: ...,
    })

如自定义路由策略:

    new WorkboxPlugin.GenerateSW({
      cacheId: 'webpack-pwa', // 设置前缀
      skipWaiting: true, // 强制等待中的 Service Worker 被**
      clientsClaim: true, // Service Worker 被**后使其立即获得页面控制权
      swDest: 'service-wroker.js', // 输出 Service worker 文件
      globPatterns: ['**/*.{html,js,css,png.jpg}'], // 匹配的文件
      globIgnores: ['service-wroker.js'], // 忽略的文件
      runtimeCaching: [
          // 配置路由请求缓存
          {
              urlPattern: /.*\.js/, // 匹配文件
              handler: 'networkFirst' // 网络优先
          }
      ]
  })

如自定义路由策略:

new GenerateSW({
  skipWaiting: true,
  clientsClaim: true,
  runtimeCaching: [
    {
      // To match cross-origin requests, use a RegExp that matches
      // the start of the origin:
      urlPattern: new RegExp('^https://api'),
      handler: 'staleWhileRevalidate',
      options: {
        // Configure which responses are considered cacheable.
        cacheableResponse: {
          statuses: [200]
        }
      }
    },
    {
      urlPattern: new RegExp('^https://cdn'),
      // Apply a network-first strategy.
      handler: 'networkFirst',
      options: {
        // Fall back to the cache after 2 seconds.
        networkTimeoutSeconds: 2,
        cacheableResponse: {
          statuses: [200]
        }
      }
    }
  ]
})

InjectManifest