2.1.1 • Published 1 year ago

generate-service-worker-webpack-plugin v2.1.1

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

generate-service-worker-webpack-plugin

Vue应用或其它单页面应用,集成 Service Worker 开启离线缓存。

Webpack5.x 请使用 v2.1.x 版

Webpack4.x 及以前的版本,使用v2.0.1

介绍

Vue项目 或基于 Webpack 搭建的单页面应用,在打包时自动生成并插入 Service Worker 文件。 网站部署后,用户进入网站会自动安装 Service Worker,并按需加载并离线缓存项目文件,当项目更新时会立即刷新页面并重新离线缓存资源。 目前不支持跨域资源缓存。 您的项目要有 https 协议才能使 Service Worker 生效。

软件架构

Node.js 以及 JavaScript

Service Worker 版本更新思路:
/*
打包之后 sw.js、sw.hash、index.html 中都会保存有一个相同的 hash 值
触发检查更新方式有两种,由index.html触发的如果用户弃用此插件,会导致无法触发,所以两种一起使用:
1、进入页面 index.html 先发送 postMessage 到 sw.js,sw.js 收到 message 立即检查是否更新,并刷新有效时间;(有效时间内不会再次检查更新)
2、若 sw.js 未收到 message,则在发生 fetch 请求时判断 clientId 是否变动,如果变动则检查更新,并刷新有效时间;(用户每次刷新窗口,clientId 都会改变)

检查更新的思路如下:
1、请求 sw.hash 比较返回结果与当前 sw.js 中的是否相同
    相同:向页面发起 postMessage,页面接收把当前页面的 hash 发送回 sw.js,再比较 hash 是否相同,
         如果相同,则离线缓存为最新版本,可用。
         如果不同则立即清除缓存并注销 sw.js;
         如果向页面发起 postMessage,页面在500ms内没有响应 sw.js,可能用户已弃用 sw.js,立即清除缓存并注销 sw.js;
    不同:说明项目已经更新,清除所有缓存,注销 sw.js,刷新页面;
2、如果 请求 sw.hash 失败
    判断用户端网络是否正常,
    如果网络正常,则说明此项目可能已经放弃使用 sw.js,立即清除缓存并注销 sw.js;
    如果网络断开连接,则直接使用离线缓存即可;
*/

安装教程

npm install -D generate-service-worker-webpack-plugin

配置参数:

name      可选,打包之后 Service Worker 文件的名称,默认 sw,全名 sw.js;
version   可选,打包之后 Service Worker 的版本号,默认 1.0.0;
cacheFlag 可选,打包时匹配文件内容中是否包此 flag,有则离线缓存。
          需要你手动在项目文件中加入 flag 字符串,且此配置具有最高优先级。
          注意由于 webpack 打包会自行 tree shaking 清除无用代码,要避免 flag 打包时被清除,可以参考我的做法:
          1、如果文件中有 html 代码,可以把 cacheFlag 写入DOM元素属性中,避免被清除,如下:
          <div sw="ServiceWorkerFlag"></div>
          2、如果是js文件,在不影响程序使用的情况下,把 cacheFlag 赋值到 window 对象 或 其他全局对象内,如下:
          window.sw = 'ServiceWorkerFlag'
excache   可选,用正则表达式匹配 路径 或 文件名,匹配到的文件不进行离线缓存。
size      可选,允许缓存的文件大小范围。单位:字节。默认缓存 0 ~ 10M 内的文件。
time      缓存有效时间,此时间内不再进行检查和更新。单位(ms),默认 10000ms。
filter    可选,自定义过滤函数,有两个参数,返回 离线缓存文件列表 和 webapck assets,可自行处理文件内容。
            cacheFiles    参数1:缓存文件名列表,对此数组操作将直接作用缓存文件列表,注意,赋值将导致引用关系失效。
            assets        参数2:compilation.hooks.processAssets.tap 回调函数的 assets,使用请阅读webpack5文档。
            RawSource     插件内部已经引入了 Source 包,直接暴露出去以供使用。const { RawSource } = require('webpack-sources')
          return 的值如果是数组,将直接赋值给 cacheFiles

使用案例 1

const GenerateServiceWorkerWebpackPlugin = require('generate-service-worker-webpack-plugin')

module.exports = {
  // ...
  configureWebpack: config => {
    let plugins = []

    if (process.env.NODE_ENV === 'production') {
      plugins.push(new GenerateServiceWorkerWebpackPlugin({
        name: 'sw',
        version: '1.0.1',
        cacheFlag: 'ServiceWorkerFlag', // 缓存内容中包含 ServiceWorkerFlag 字符串的文件
        excache: /(edit\/|\.mp4$)/, // 不缓存 edit目录下的所有文件 和 .mp4 后缀的文件
        size: [0, 1024 * 1024 * 10], // 只缓存 10m 以内的文件
        time: 1000*60, // 1分钟内不再检查更新
      }));
    }

    config.plugins = [
      ...config.plugins,
      ...plugins
    ];
  }
  // ...
}

使用案例 2

自定义过滤方法,比如只缓存js文件,可使用以下方式:

plugins.push(new GenerateServiceWorkerWebpackPlugin({
  name: 'sw',
  version: '1.0.1',
  filter: function (cacheFiles, assets) {
    return cacheFiles.filter(m => /(\.js$)/.test(m))
  }
}));

参与贡献

blcyzycc

特技

你可以完全使用默认配置,离线缓存全部项目文件

plugins.push(new GenerateServiceWorkerWebpackPlugin());

filter 函数的 assets 参数是 Webpack 打包时 emit 事件的 compilation.assets 属性,我们可以遍历 assets 得到打包的文件,并对其进行操作。 例如:替换 html 文件的 title。

plugins.push(new GenerateServiceWorkerWebpackPlugin({
  name: 'sw',
  version: '1.0.1',
  filter: function (cacheFiles, assets, RawSource) {
    // 只缓存前五个文件
    cacheFiles.splice(5, cacheFiles.length - 5)

    // 遍历文件列表,可在此修改打包后的代码
    for (let url in assets) {
      let source = assets[url].source()

      if (typeof source === 'object') {
        source = source.toString('utf-8')
      }

      // 判断是否为 html 文件
      if (/\.html$/.test(url)) {
        // 将页面的 title 替换为 hello world
        source = source.replace(/(<title[^>]*>)(.*)(<\/title[^>]*>)/, '$1hello world$3')

        // const { RawSource } = require('webpack-sources')
        // 插件内部已经引入了 RawSource 包,直接暴露出来以供使用
        assets[url] = new RawSource(source)
      }
    }
  }
}));
2.1.1

1 year ago

2.0.2

1 year ago

2.1.0

1 year ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.9

2 years ago

2.0.1

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago