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 , …...

【Git】远程仓库的创建、SSH协议克隆、拉取、推送
目录 一、创建远程仓库 二、HTTPS协议克隆仓库 三、SSH协议克隆仓库 四、向远程仓库推送 五、从远程仓库拉取 六、忽略特殊文件 七、配置命令别名 一、创建远程仓库 首先我们可以从GitHub或者Gitee中创建自己的个人仓库 工作台 - Gitee.comhttps://gitee.com/ 二、HTT…...

C#之泛型
目录 一、概述 二、C#中的泛型 继续栈的示例 三、泛型类 (一)声明泛型类 (二)创建构造类型 (三)创建变量和实例 (四)比较泛型和非泛型栈 四、类型参数的约束 (一…...
Scrum敏捷开发管理流程+scrum工具免费
Leangoo领歌它覆盖了敏捷项目研发全流程,包括小型团队Scrum敏捷开发,规模化敏捷SAFe,Scrum of Scrums大规模敏捷。它提供了灵活的敏捷模板和极致的协作体验,可以让团队快速上手,快速落地Scrum敏捷开发管理。 首先建立产…...

【操作系统基础】Linux 中 /var/log/ 文件夹下通常有哪一些文件?分别的作用是什么?
在Linux系统中,/var/log/ 文件夹通常包含了系统日志文件,这些文件记录了系统的各种活动和事件,以便管理员进行故障排除和监控。 以下是/var/log/ 文件夹中常见的一些文件及其含义: auth.log:记录系统认证和授权相关的…...

【构造】CF1758 C
Problem - 1758C - Codeforces 题意: 思路: 思路: #include <bits/stdc.h>#define int long longusing namespace std;const int mxn2e510; const int mxe2e510;int N,x; int ans[mxn];void solve(){cin>>N>>x;if(N%x!0)…...

【etcd】docker 启动单点 etcd
etcd: v3.5.9 etcd-browser: rustyx/etcdv3-browser:latest 本文档主要描述用 docker 部署单点的 etcd, 用 etcd-browser 来查看注册到 etcd 的 key 默认配置启动 docker run -d --name ai-etcd --networkhost --restart always \-v $PWD/etcd.conf.yml:/opt/bitn…...

【单链表OJ题:反转链表】
题目来源 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head){struct ListNode* current head;struct ListNode* newnode NULL;while(current!NULL){struc…...

Unity UGUI的LayoutRebuilder的介绍及使用
Unity UGUI的LayoutRebuilder的介绍及使用 1. 什么是LayoutRebuilder? LayoutRebuilder是Unity UGUI中的一个组件,用于自动重建布局。它可以根据UI元素的变化,自动调整其子元素的位置和大小,以保持布局的一致性。 2. LayoutReb…...

深刻理解python特性-列表推导式和生成器表达式
哈喽大家好,今天给大家介绍两个Python中特性-列表推导式和生成器表达式 今天我想向你介绍python语言的两个非常有用的特性:列表推导式和生成器表达式。这两个特性都可以让你用一行简洁的代码来创建一个序列,而不需要写循环或者函数。但是它们…...

Sentinel dashboard的使用;Nacos保存Sentinel限流规则
Sentinel dashboard的使用 往期文章 Nacos环境搭建Nacos注册中心的使用Nacos配置中心的使用Sentinel 容灾中心的使用 参考文档 Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 限流结果 下载sentinel-dashboard github地址:Sentinel/sentinel-dashboar…...