Workbox使用分享
一、简要介绍
1.1 什么是Workbox
官方文档原文:
At this point, service workers may seem tricky. There’s lots of complex interactions that are hard to get right. Network requests! Caching strategies! Cache management! Precaching! It’s a lot to remember. This doesn’t make service worker an ill-designed technology; it works as intended, and solves hard problems.
Good abstractions make complex APIs easier to use. That’s where Workbox comes in. Workbox is a set of modules that simplify common service worker routing and caching. Each module available addresses a specific aspect of service worker development. Workbox aims to make using service workers as easy as possible, while allowing the flexibility to accommodate complex application requirements where needed.
官方介绍文档链接:What is Workbox?
简单的来说 Workbox 是由 Google 开发的一个基于 Service Worker 的js库,提供了很多高效好用的工具和策略,其目的在于更加高效的实现应用缓存和离线优先应用(PWA),不再需要繁杂的编写SW相关的代码
1.2 Workbox的主要特性
- Runtime Caching(运行时缓存):
- Workbox 提供了多种灵活的运行时缓存策略,以缓存动态内容,如 API 响应。
- 内置的策略包括 NetworkFirst(优先从网络获取)、CacheFirst(优先从缓存获取)、StaleWhileRevalidate(边缘过期时刷新)等。
- 开发者可以根据应用程序的需求选择适当的策略,并灵活配置缓存行为。
- Strategies and Routing(策略和路由):
- Workbox 提供了灵活的路由和处理网络请求的能力,开发者可以根据具体需求定义自定义的缓存策略和路由规则。
- 这使得开发者可以根据特定的 URL、请求方法或其他条件来定义不同的缓存行为,以满足应用程序的特定需求。
- Precaching(预缓存):
- Workbox 允许开发者在服务工作者安装阶段预缓存静态资源,包括 HTML、CSS、JavaScript 文件、图像等。
- 预缓存的资源在离线状态下可用,提高应用程序的可靠性和性能。
- Background Sync(后台同步):
- Workbox 简化了实现后台同步的过程,允许将失败的网络请求排队并在用户恢复网络连接时重新尝试发送。
- 后台同步功能可以提高应用程序的可靠性,确保关键操作(如提交表单或数据同步)在离线状态下也能正常完成。
1.3 如何在SW文件中使用
推荐在SW文件中引入Workbox cdn使用
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');
二、具体使用
2.1 请求策略
在使用 Workbox 之前先然我们了解一下其提供的几种常用缓存策略
tips: 此处只介绍了业务中比较能用到的策略,像 Cache only(仅使用缓存)等不大可能使用的策略就不在这里展开了
CacheFirst(优先从缓存获取)
该策略将在页面发出请求时优先使用缓存中的数据作为响应,在缓存中无响应时才会发起网络请求
这种策略适合缓存一些不经常变动的资源,例如在 hoyolab 主站 pc 中使用了这种策略缓存了图片与svga等静态资源
NetworkFirst(优先从网络获取)
该策略将在页面发出请求时优先进行网络请求,请求成功后将响应存至缓存,当请求失败,若缓存中有内容响应则使用缓存响应
这种策略适合对稳定性要求较高的业务场景,保证在服务器错误时,前端应用不至于完全不可用
StaleWhileRevalidate(先从缓存获取,同时向网络请求)
该策略将在页面发出请求时先尝试使用缓存作为响应,然后在后台发起网络请求,将请求的响应更新至缓存,当然若缓存一开始就响应失败则直接使用网络请求
这种策略适合有变动的需求,但能接受当前使用过期缓存,后续访问更新的场景,或是对一些第三方资源的缓存
例如在 hoyolab 主站 pc 业务中就使用了该种策略缓存了语言列表、编辑器分割线资源、第三方播放器脚本(YouTube, twitch),多语言资源等请求
2.2 运行时缓存
运行时缓存 Runtime Caching 支持我们更加灵活和动态的去指定我们的缓存方案,我们可以指定一些路由来配置相应的缓存策略,来捕获一些动态内容,根据我们的策略来做缓存
使用方式
workbox.routing.registerRoute(matchCallback, handlerCallback, method)
| 参数 | 作用 |
|---|---|
| matchCallback | 可以是一个函数或者正则表达式用来匹配请求路由 |
| handlerCallback | 处理匹配请求的策略函数,一般而言直接使用 Workbox 提供的策略new workbox.strategies[‘策略’] |
| method(可选) | 请求方法POST/GET若未指定则会默认匹配所有http方法 |
以下是运行时缓存的代码示例
workbox.routing.registerRoute(new RegExp('\\.(?:svg|svga)$'), // 路由匹配正则new workbox.strategies.CacheFirst({ // 上文提到的缓存策略cacheName: 'svgCache', // 可以为你的缓存起个自定义名字方便后续的管理plugins: [new workbox.expiration.ExpirationPlugin({maxEntries: 50, // 设置最大请求条数maxAgeSeconds: 7 * 24 * 60 * 60, // 设置最长请求时间7天}),],})
);
2.3 预缓存
预缓存是在SW安装的阶段就根据指定的缓存列表将资源存至缓存中,使其在离线状态下也可以进行访问
使用方式
workbox.precaching.precacheAndRoute(cacheArr)
该方法接受一个数组,我们可以在数组中指定我们想要缓存的资源
workbox.precaching.precacheAndRoute([{url: '/A.html', revision: '1.0.0' },{url: '/B.css', revision: '1.0.0'},{url: '/C.js', revision: '1.0.0'}
]);
revision字段主要用于标识我们的缓存版本,当改标识变更时会触发缓存更新
当然提供workbox的一些工具和构建流程结合我们也可以将这个过程自动化,这里先不展开了
2.4 后台同步
后台同步允许你在某个时机或周期性的在后台对后端数据进行同步
比如用户请求了数据,但是当前网络环境不稳定导致用户离线,这时我们可以使用 workbox 将失败的请求收集起来,在用户网络环境恢复时再次请求
下面是一个简单的实例
注册待重试的请求
const bgSyncPlugin = new workbox.backgroundSync.BackgroundSyncPlugin('retryQueue', {maxRetentionTime: 24 * 60 // 最多重试时间
});workbox.routing.registerRoute(/\/api/, // 随便写了个正则new workbox.strategies.NetworkOnly({plugins: [bgSyncPlugin]}),'POST'
);
该实例中我们设置了一个同步队列 retryQueue,然后匹配所有的/api请求,在这些请求失败时将请求加入到我们的重试队列中
注册待执行的函数
workbox.backgroundSync.registerRoute('retryQueue', async ({queue}) => {let entry;while (entry = await queue.shiftRequest()) {try {const response = await fetch(entry.request);const responseData = await response.json();} catch (error) {await queue.unshiftRequest(entry);return;}}
});
该实例函数会在用户重新在线时触发,从 retryQueue 队列中取出请求并执行,请求成功我们可以同步这些数据到业务侧,若请求失败则放回请求队列
除此之外SW的后台同步还能有更多的使用方式如表单后台同步,备份,轮询状态等场景这里就不展开了
三、为什么更倾向与使用Workbox,直接使用原生SW不好吗?
其实就正如介绍中所说的Workbox基于SW提供了非常多的工具和实现,简化了SW的使用,开发者能使用workbox更快的实现业务上的缓存功能,而不必编写底层的缓存策略
比如前文介绍的对svg资源的缓存,我们可以对比一下原生SW与workbox的实现差异
workbox:
workbox.routing.registerRoute(new RegExp('\\.(?:svg|svga)$'), // 路由匹配正则new workbox.strategies.CacheFirst({ // 上文提到的缓存策略cacheName: 'svgCache', // 可以为你的缓存起个自定义名字方便后续的管理plugins: [new workbox.expiration.ExpirationPlugin({maxEntries: 50, // 设置最大请求条数maxAgeSeconds: 7 * 24 * 60 * 60, // 设置最长请求时间7天}),],})
);
SW原生实现demo(生产环境策略指定需要更加的细化)
const CACHE_NAME = 'svga-cache';
const MAX_ENTRIES = 50;
const MAX_AGE = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds// Clean old cache entries
async function cleanCache() {const cache = await caches.open(CACHE_NAME);const keys = await cache.keys();const entries = keys.filter(request => request.url.endsWith('.svga'));// Sort entries by ageentries.sort((a, b) => a.url < b.url ? 1 : -1);// Delete old or excess entriesfor(let i = entries.length - 1; i >= 0; i--) {if(i > MAX_ENTRIES - 1 || (Date.now() - entries[i].url) > MAX_AGE) {await cache.delete(entries[i]);}}
}// Install event
self.addEventListener('install', event => {event.waitUntil(cleanCache());
});// Fetch event
self.addEventListener('fetch', event => {if (event.request.url.endsWith('.svga')) {event.respondWith(caches.open(CACHE_NAME).then(cache => {return cache.match(event.request).then(response => {if (response) {// Cache hitreturn response;}// Cache missreturn fetch(event.request.clone()).then(networkResponse => {cache.put(event.request, networkResponse.clone());return networkResponse;});});}));}
});// Activate event
self.addEventListener('activate', event => {event.waitUntil(cleanCache());
});
很容易看出workbox具备更强大的易用性
当然选择workbox也并不是完全抛弃SW的原生使用,两者其实可以根据业务需要去并存
相关文章:
Workbox使用分享
一、简要介绍 1.1 什么是Workbox 官方文档原文: At this point, service workers may seem tricky. There’s lots of complex interactions that are hard to get right. Network requests! Caching strategies! Cache management! Precaching! It’s a lot to r…...
秋招算法备战第32天 | 122.买卖股票的最佳时机II、55. 跳跃游戏、45.跳跃游戏II
122. 买卖股票的最佳时机 II - 力扣(LeetCode) 通过做差可以得到利润序列,然后只要利润需求的非负数求和就可以,因为这里没有手续费,某天买入之后买出可以等价为这几天连续买入卖出 class Solution:def maxProfit(se…...
Python状态模式介绍、使用
一、Python状态模式介绍 Python状态模式(State Pattern)是一种行为型设计模式,它允许对象在不同的状态下表现不同的行为,从而避免在代码中使用多重条件语句。该模式将状态封装在独立的对象中,并根据当前状态选择不同的…...
Github-Copilot初体验-Pycharm插件的安装与测试
引言: 80%代码秒生成!AI神器Copilot大升级 最近copilot又在众多独角兽公司的合力下,取得了重大升级。GitHub Copilot发布还不到两年, 就已经为100多万的开发者,编写了46%的代码,并提高了55%的编码速度。 …...
Spring AOP API详解
上一章介绍了Spring对AOP的支持,包括AspectJ和基于schema的切面定义。在这一章中,我们将讨论低级别的Spring AOP API。对于普通的应用,我们推荐使用前一章中描述的带有AspectJ pointcuts 的Spring AOP。 6.1. Spring 中的 Pointcut API 这一…...
分治法 Divide and Conquer
1.分治法 分治法(Divide and Conquer)是一种常见的算法设计思想,它将一个大问题分解成若干个子问题,递归地解决每个子问题,最后将子问题的解合并起来得到整个问题的解。分治法通常包含三个步骤: 1. Divid…...
super(Module_ModuleList, self).__init__()的作用是什么?
class Module_ModuleList(nn.Module):def __init__(self):super(Module_ModuleList, self).__init__()self.linears nn.ModuleList([nn.Linear(10, 10)])在这段代码中,super(Module_ModuleList, self).__init__() 的作用是调用父类 nn.Module 的 __init__ 方法&…...
【并发专题】操作系统模型及三级缓存架构
目录 课程内容一、冯诺依曼计算机模型详解1.计算机五大核心组成部分2.CPU内部结构3.CPU缓存结构4.CPU读取存储器数据过程5.CPU为何要有高速缓存 学习总结 课程内容 一、冯诺依曼计算机模型详解 现代计算机模型是基于-冯诺依曼计算机模型 计算机在运行时,先从内存中…...
java基础复习(第二日)
java基础复习(二) 1.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized修饰? 都不能。 抽象方法需要子类重写…...
Ansible自动化运维工具
Ansible自动化运维工具 一、ansible介绍二、ansible环境安装部署三、ansible命令行模块1、command模块2、shell模块3、cron模块4、user模块5、group模块6、copy模块7、file模块8、hostname模块9、ping模块10、yum模块11、service/systemd模块12、script模块13、mount模块14、ar…...
LeetCode-116-填充每个节点的下一个右侧节点指针
一:题目描述: 给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: struct Node {int val;Node *left;Node *right;Node *next; }填充它的每个 next 指针,让这个指…...
前端面试的性能优化部分(3)每篇10题
21.如何优化移动端网页的性能? 优化移动端网页的性能是提升用户体验、降低用户流失的关键。以下是一些优化移动端网页性能的常见方法: 压缩和合并资源: 压缩 CSS、JavaScript 和图片等静态资源,减少文件大小,同时合并…...
如何通过企业工商信息初步判断企业是否靠谱?
银行、投资机构等对企业进行融资、授信、合作时,需要如何评估企业的可靠性。企业工商信息作为企业的基础信息,是初步判断企业是否靠谱的重要依据之一,通过对企业工商信息的综合分析,我们可以了解企业的经营状况、财务实力、法律风…...
ChatGPT+知乎,20分钟超越专业大V的调教方法
AI技术正在迅速发展,渗透到我们的生活中,尤其在内容营销领域。 AI算法帮助我们生成文本、优化搜索引擎排名,提升用户体验等,这些创新正在塑造时代的前进方向,AI也将引领未来十年的变革。对于每个创业者、内容创作者和…...
git branch --show-current 和 git rev-parse --abbrev-ref HEAD 区别
git branch --show-current 和 git rev-parse --abbrev-ref HEAD 区别 git branch --show-current 和 git rev-parse --abbrev-ref HEAD 命令都可以用于获取当前所在的 Git 分支名称。 但是,它们之间有一些不同点: git branch --show-current 命令是 G…...
【TypeScript】接口类型 Interfaces 的使用理解
导语: 什么是 类型接口? 在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement&#x…...
2023-07-31 C语言根据错误号打印详细的错误信息perror(““) 或者strerror(errno)
一、C 语言可以使用perror("perror output"); 或 strerror(errno)打印详细的错误信息。 二、需要的头文件#include <errno.h>。 三、实例测试,这里我让open一个linux 底层杂项设备失败的情况,返回的是一个负数,强制返回-EN…...
JDK17和JDK8完美卸载方法及新版JDK安装教程
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
FPGA设计时序分析二、建立/恢复时间
目录 一、背景知识 1.1 理想时序模型 1.2 实际时序模型 1.2.1 时钟不确定性 1.2.2 触发器特性 二、时序分析 2.1 时序模型图 2.2 时序定性分析 一、背景知识 之前的章节提到,时钟对于FPGA的重要性不亚于心脏对于人的重要性,所有的逻辑运算都离开…...
oracle建立自动增长字段
oracle数据库与其他的数据库不太一样,比如在mysql里自动增长只要设定“auto_increment”即可。可是在oracle里就没有这种配置了。以oracle11g为例,建立自动增长的字段。操作如下: --创建表 create table USERINFO ( ID NUMBER , …...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
