摘要:而且,在接下来页面的异步请求中,还能进行缓存尝试这里配置的文件清单在安装激活阶段不会进行缓存,只有在监听到网络请求的时候才进行缓存。
基本知识普及请参考
https://www.jianshu.com/p/623...
https://zhuanlan.zhihu.com/p/...
下面简单介绍一下插件的使用
以下是我在项目中使用的配置
webpack.prod.conf.js中
{ ... plugins: [ new OfflinePlugin({ responseStrategy: "cache-first", // 缓存优先 AppCache: false, // 不启用appCache safeToUseOptionalCaches: true, // Removes warning for about `additional` section usage autoUpdate: true, // 自动更新 caches: { // webpack打包后需要换的文件正则匹配 main: [ "**/*.js", "**/*.css", /.(png|jpe?g|gif|svg)(?.*)?$/, /.(woff2?|eot|ttf|otf)(?.*)?$/ ], additional: [ ":externals:" ] }, externals: [], // 设置外部链接,例如配置http://hello.com/getuser,那么在请求这个接口的时候就会进行接口缓存 excludes: ["**/.*", "**/*.map", "**/*.gz", "**/manifest-last.json"], // 需要过滤的文件 ServiceWorker: { output: "./static/sw.js", // 输出目录 publicPath: "/static/sw.js", // sw.js 加载路径 scope: "/", // 作用域(此处有坑) minify: true, // 开启压缩 events: true // 当sw状态改变时候发射对应事件 } }) ] }
在入口js文件中
OfflinePluginRuntime.install({ // 监听sw事件,当更新ready的时候,调用applyUpdate以跳过等待,新的sw立即接替老的sw onUpdateReady: () => { console.log("SW Event:", "onUpdateReady") OfflinePluginRuntime.applyUpdate() }, onUpdated: () => { console.log("SW Event:", "onUpdated") window.swUpdate = true } })
首先介绍一下assets里面的三个属性:
main: [] 这里配置的是serviceWorker在install阶段需要缓存的文件清单,如果其中有一个失败了,那么整个serviceWorder就会安装失败,所以必须谨慎配置
additional: [] 这里配置的文件清单会在serviceWorker activate的时候进行缓存,与main不一样,如果这里的文件缓存失败,不会影响serviceWorker的正常安装。而且,在接下来页面的ajax异步请求中,还能进行缓存尝试
optional: [] 这里配置的文件清单在serviceWorker安装激活阶段不会进行缓存,只有在监听到网络请求的时候才进行缓存。
刚才说到作用域的时候有坑,如果按照上面的文件配置,最后在网页中会提示,sw最大的作用域权限在/static下面,言外之意这么写是无法将sw的作用域设置在/根路径下面。
所以这边需要服务端在返回sw.js的时候手动设置Service-Worker-Allowed头字段,并且值设置为/,同时这个文件的缓存时间设为0,否则,当更新serviceWorker的时候,由于浏览器缓存了sw.js用户端这边的serviceWorker无法第一时间更新。
最后来一张线上项目,在网速极慢的情况下也能实现秒开
-------------------追加--------------------扩展fetch事件
首先在配置文件里添加入口
sw-entry.js
self.addEventListener("fetch", function (event) { function cachesMatch (request, cacheName) { return caches.match(request, { cacheName: cacheName }).then(function (response) { return response }) // Return void if error happened (cache not found) ["catch"](function () {}) } function cacheFirst(cacheUrl, CACHE_NAME) { var resource = cachesMatch(cacheUrl, CACHE_NAME).then(function (response) { if (response) { return response; } // Load and cache known assets var fetching = fetch(urlString).then(function (response) { if (!response.ok) { return response; } (function () { var responseClone = response.clone(); var storing = caches.open(CACHE_NAME).then(function (cache) { return cache.put(urlString, responseClone); }).then(function () { console.log("[SW]:", "Cache asset: " + urlString); }); event.waitUntil(storing); })(); return response; }); return fetching; }) return resource } function netWorkFirst(cacheUrl, CACHE_NAME) { var resource = fetch(cacheUrl).then(response => { if (response.ok) { var responseClone = response.clone() var storing = caches.open(CACHE_NAME).then(function (cache) { cache.put(cacheUrl, responseClone); }).then(function () { console.log("[SW]:", "Cache asset: " + cacheUrl); }); event.waitUntil(storing); return response; } // Throw to reach the code in the catch below throw new Error("Response is not ok"); }) ["catch"](function () { return cachesMatch(cacheUrl, CACHE_NAME); }); return resource } var url = new URL(event.request.url) url.hash = "" var pathname = url.pathname var urlString = url.toString() var cacheUrl = urlString var IS_KANO = /kano.guahao.cn/ var IS_STATIC = //static// var IS_HOME = /^/(e|u|n)/(d+)$/ var IS_EDITOR = /^/editor(?!.)/ var IS_PREVIEW = /^/preview(?!.)/ var CACHE_PREFIX = __wpo.name var CACHE_TAG = __wpo.version var CACHE_NAME = CACHE_PREFIX + ":" + CACHE_TAG var resource = undefined var isGET = event.request.method === "GET" // 以缓存优先的形式缓存 kano 以及 static/* 静态资源 if ((cacheUrl.match(IS_KANO) || pathname.match(IS_STATIC)) && isGET) { resource = cacheFirst(cacheUrl, CACHE_NAME) event.respondWith(resource) } // 以网络优先的形式缓存 editor页面 preview页面和 production页面 if ((pathname.match(IS_HOME) || pathname.match(IS_EDITOR) || pathname.match(IS_PREVIEW)) && isGET) { resource = netWorkFirst(cacheUrl, CACHE_NAME) event.respondWith(resource) } })
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94157.html
摘要:配合的项,能够实现缓存外部资源的功能。允许接受来自的消息,默认值为。检查新版本的的更新信息。这也是我在研究阶段直接使用时所发现的问题。建议仅在生产模式内使用。 showImg(https://segmentfault.com/img/bVSVG1?w=1178&h=484); 谈起PWA,许多人可能还只停留在了解的层面,比较少在实践中真正地尝试过,更多的仅仅是对着网上的教程和例子大概玩...
摘要:本篇不包含所有坑,暂时只记录自己踩到的部分坑一安装安装最新版本安装新增依赖这个在中,本身和它的是在同一个包中,中将两个分开管理。我记录下自己更新这个的过程,以下前半部分可以直接跳过。以下记录踩坑过程。 本篇不包含所有坑,暂时只记录自己踩到的部分坑 一.安装 安装webpack4最新版本 npm install --save-dev webpack@4 安装新增依赖 webpack-c...
摘要:和的关系不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将在安全性能和体验等方面带来渐进式的提升的一种的模式。这里需要注意的是,首次注册线程的页面需要再次加载才会受其控制。 1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技...
摘要:和的关系不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将在安全性能和体验等方面带来渐进式的提升的一种的模式。这里需要注意的是,首次注册线程的页面需要再次加载才会受其控制。 1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技...
阅读 980·2021-10-27 14:15
阅读 2735·2021-10-25 09:45
阅读 1892·2021-09-02 09:45
阅读 3332·2019-08-30 15:55
阅读 1753·2019-08-29 16:05
阅读 3167·2019-08-28 18:13
阅读 3092·2019-08-26 13:58
阅读 415·2019-08-26 12:01