基于workbox实现PWA预缓存能力
引言
Service Worker 是一项流行的技术,尽管在许多项目中尚未得到充分利用。基于本次项目首页加载优化的机会,决定尝试使用 Google 出品的 Workbox,以观察其优化效果。
开始
安装
项目使用 Webpack 打包,而 Workbox 提供了 Webpack 插件,因此只需执行 npm i workbox-webpack-plugin --save-dev 即可安装。
初始化配置
安装依赖后,需在原有项目中添加以下 Webpack 配置:
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {// Other webpack config...plugins: [// Other plugins...new WorkboxPlugin.GenerateSW() // 采用默认配置]
};
然后在项目首页加入以下代码以注册 Service Worker:
<script>
// Check that service workers are registered
if ('serviceWorker' in navigator) {// Use the window load event to keep the page load performantwindow.addEventListener('load', () => {// navigator.serviceWorker.register('/sw.js');// 文档中用的是sw.js,实际上webpack生成的文件是service-worker.jsnavigator.serviceWorker.register('/service-worker.js');});
}
</script>
完成这些基本配置后,Service Worker 应该已经生效,会对 Webpack 打包的项目文件进行预缓存。
自定义配置
之前仅采用了 Workbox 的默认配置。具体的完整配置可参照 文档。这里仅介绍一些常用的简单自定义配置,配置使用 key -> value 形式传参:
new WorkboxPlugin.GenerateSW({option: 'value',
});
swDest
此参数指定 Webpack 生成的 service-worker.js 文件相对于 Webpack 输出目录的路径,默认值是 service-worker.js:
new WorkboxPlugin.GenerateSW({swDest: 'sw.js', // {output}/sw.js
});
importWorkboxFrom
此参数指定页面将从何处加载 Workbox 库文件,默认是 CDN,会从 Google Cloud 上获取依赖的文件。考虑到国内的网络环境,这里一般设置成 local,Webpack 会打包出依赖的文件,供页面加载时使用:
new WorkboxPlugin.GenerateSW({importWorkboxFrom: 'local',
});
chunks
此参数可以指定 Workbox 需要预缓存的 chunk,因为在预缓存阶段,如果文件数量太多,依然会占用浏览器请求并发数,可能导致其他请求被阻塞,因此对于较大型的项目,合理配置需要预缓存的文件是必要的:
new WorkboxPlugin.GenerateSW({chunks: ['chunk1', 'chunk2'],
});
excludeChunks
与 chunks 参数相反,这里指定不需要预缓存的文件。
include
此参数的功能与 chunks 类似,但通过正则表达式匹配需要预缓存的文件:
new WorkboxPlugin.GenerateSW({// precache html和js文件include: [/.html$/, /.js$/],
});
exclude
与 include 相反。
runtimeCaching
以上配置针对的是预缓存,即在页面加载完后会自动去缓存一次的文件,而 runtimeCaching 针对的是在页面运行中发起的请求的缓存策略。
urlPattern
此参数是一个正则表达式,命中该规则的请求将被缓存下来:
new WorkboxPlugin.GenerateSW({runtimeCaching: [{// 缓存所有图片urlPattern: /.(?:jpg|jpeg|svg|png)/,}],
});
handler
此参数决定命中的请求使用什么缓存策略,可选的参数有 networkFirst、networkOnly、cacheFirst、cacheOnly、staleWhileRevalidate,分别代表:
- networkFirst:网络优先,即优先使用网络请求返回的结果,当网络请求失败时,尝试使用缓存结果。
- networkOnly:只使用网络请求结果,不使用缓存。
- cacheFirst:缓存优先,即优先使用缓存结果,缓存结果不存在时,尝试使用网络请求结果。
- cacheOnly: 只使用缓存结果。
- staleWhileRevalidate:有缓存的时候,优先使用缓存结果,同时获取新的网络请求结果,更新缓存。
对于大部分情况,使用staleWhileRevalidate就可以了,其他情况根据自身业务的需求,合理使用networkFirst和cacheFirst,networkOnly和cacheOnly用的比较少。
new WorkboxPlugin.GenerateSW({runtimeCaching: [{// 缓存所有图片urlPattern: /.(?:jpg|jpeg|svg|png)/,handler: 'staleWhileRevalidate',}],
});
options
此参数是一个对象,其中包含了很多缓存相关的配置,这里不多说,直接看 文档。
需要注意的点
在完成上述配置后,如果幸运的话,可以直接使用了。不过第一次使用时,还是遇到了不少问题,很大的原因也是之前没用过 Service Worker,有些基本的知识不了解。官方也列出了一些常见的问题和解决方法,详见 常见问题。
本地调试
Service Worker 只有在 HTTPS 或者本地环境才能成功注册,也就是在本地开发时,需要使用 127.0.0.1 或者 localhost 来访问页面才行。
service-worker.js 文件路径
在前面的配置中,我们注册的 service-worker.js 文件默认放在页面的根路径,即 127.0.0.1/service-worker.js,但是在我们项目里,静态文件打包后都放在 public 目录,也就是说访问 URL 是 127.0.0.1/public/service-worker.js,于是把注册的文件路径改成:
<script>
if ('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('/public/service-worker.js');});
}
</script>
这样 Service Worker 可以成功加载注册了,但是却发现很多资源都无法缓存,这是怎么回事?
原因是每个 Service Worker 都有自己的权限域,而这个域的范围依赖于注册文件的路径。如 /public/service-worker.js 注册的 Service Worker 的权限域在 /public 下,所以他只能缓存诸如 127.0.0.1/public/a.png 这种路径的资源,如 127.0.0.1/b.png 就无法缓存了。
要解决这个问题有2种方法:
- 为
service-worker.js文件增加Service-Worker-Allowed='/'响应头,然后修改注册代码:
navigator.serviceWorker.register('/blog/sw.js', {scope: '/'});
- 修改文件路径到根路径,在服务端对该文件重定向,因为我们项目用的是 Egg,所以这里配置下
siteFile即可:
config.siteFile = {'/service-worker.js': fs.readFileSync(path.join(appInfo.baseDir,'/public/service-worker.js',),),};
跨域资源的缓存
官方文档 中有专门对这种情况的解释,说明了为什么跨域资源需要特殊处理。对于我们来说,针对跨域资源要做的就是在标签上加上 crossorigin="anonymous" 的属性:
<link crossorigin="anonymous" rel="stylesheet" href="https://example.com/path/to/style.css">
<img crossorigin="anonymous" src="https://example.com/path/to/image.png">
然后缓存策略使用 networkFirst 或者 staleWhileRevalidate,最重要的是正则匹配规则需要匹配资源 URL 的头部,不然无法命中跨域资源:
new WorkboxPlugin.GenerateSW({runtimeCaching: [{// To match cross-origin requests, use a RegExp that matches// the start of the origin:urlPattern: new RegExp('^https://cors.example.com/'),handler: 'staleWhileRevalidate',}],
});
结尾
Workbox 接入成本低,配置简单灵活,能够满足大部分的页面缓存需求,质量有保障,因此还是十分推荐的。
相关文章:
基于workbox实现PWA预缓存能力
引言 Service Worker 是一项流行的技术,尽管在许多项目中尚未得到充分利用。基于本次项目首页加载优化的机会,决定尝试使用 Google 出品的 Workbox,以观察其优化效果。 开始 安装 项目使用 Webpack 打包,而 Workbox 提供了 We…...
探索Web3生态系统:社区、协议与参与者的角色
Web3代表着互联网的下一个演变阶段,旨在通过去中心化技术赋予用户更大的控制权和参与感。在这个新兴生态系统中,社区、协议和参与者扮演着不可或缺的角色,共同推动着Web3的建设与发展。 社区的核心作用 在Web3中,社区通过提供反馈…...
无人机电机故障率骤降:创新设计与六西格玛方法论双赢
项目背景 TBR-100是消费级无人机头部企业推出的主打消费级无人机,凭借其出色的续航能力和卓越的操控性,在市场上获得了广泛认可。在产品运行过程,用户反馈电机故障率偏高,尤其是在飞行一段时间后出现电机过热、损坏以及运行不稳定…...
samba禁用时拷贝服务器文件到本地的脚本
Android系统开发一般在ubuntu服务器上,我们办公电脑一般是windows。在将编译出来的模块push到板子上时,一般采用adb push 方式。 有时由于种种原因会出现服务器禁用了samba,导致无法直接用adb push 的情况。 下面介绍用winscp 走ssh 拷贝服…...
C#代码 串口通信晋中A2板,控制直流电机
1,在电脑中给晋中板中下载编译好的程序。 0x39 :开启电机的标识 代码: /********************************************************************************** **** 实验名称:串口通信实验 接线说明: 实验现象&…...
3 机器学习之假设空间
归纳(induction)与演绎(deduction)是科学推理的两大基本手段。前者是从特殊到一般的“泛化”(generalization)过程,即从具体的事实归结出一般性规律;后者则是从一般到特殊的“特化”(specialization)过程,即从基础原理推演出具体状况。例如&a…...
基于STM32的风速风向传感器设计
引言 本项目设计了一个基于STM32的风速和风向传感器系统,能够通过组合使用旋转式风速传感器和电子罗盘,实时测量风速和风向,并将数据通过显示屏或无线模块发送给用户。该系统适用于气象监测、环境监控、农业自动化等场景,具有准确…...
域名申请.
操作场景 Internet上有成千上万台主机,每一台主机都对应一个唯一的IP地址。IP地址因不具备实际意义,非常难于记忆,于是就产生了域名。 域名(Domain Name)是一串用点分隔的字符串组成的名称(例如huaweiclo…...
mysql5.7与mysql8.0身份认证插件的区别
MySQL 5.7 和 MySQL 8.0 在身份认证插件方面有一些重要的区别。这些变化主要集中在默认的身份验证插件、密码管理和安全性增强上。 默认身份验证插件 MySQL 5.7 默认插件: mysql_native_password mysql_native_password 是 MySQL 5.7 及更早版本中的默认身份验证插件。它使用…...
进化吧!原始人
如果你想体验一下人类的进化过程~ 如果你有一颗充满探索的好奇心~ 千万不要错过博主新开发的小游戏哦! 点击链接,立即体验! 🙋 欢迎来到冒险互动游戏《进化吧原始人》! 🦍 在这里,你将扮演一…...
SaaS架构:中央库存系统架构设计
大家好,我是汤师爷~ 近年来,越来越多的零售企业大力发展全渠道业务。在销售额增长上,通过线上的小程序、直播、平台渠道等方式,拓展流量变现渠道。在会员增长方面,通过多样的互动方式,全渠道触达消费者&am…...
C语言中点操作符(.)和箭头操作符(->)的区别
在C语言中,点操作符(.)和箭头操作符(->)用于访问结构体的成员,但它们的使用方式有所不同。以下是具体介绍: 点操作符(.)的使用 直接访问结构体变量的成员:…...
基于FPGA的以太网设计(一)
以太网简介 以太网(Ethernet)是一种计算机局域网技术。IEEE组织的IEEE 802.3标准制定了以太网的技术标准,它规定了包括物理层的连线、电子信号和介质访问控制的内容。以太网是目前应用最普遍的局域网技术,取代了其他局域网标准如…...
Insert into on duplicate key update 死锁问题解析
Insert into on duplicate key update 死锁问题解析 背景 前段时间的需求中有这个么一个场景,每天早上需要通过定时任务到不同的平台拉取一些广告投放的相关数据,涉及的表比较多,数据量也比较大,有的需要全量同步,有…...
Apache Lucene 10 已发布!Lucene 硬件效率改进及其他改进
作者:来自 Elastic Adrien Grand Apache Lucene 10 刚刚发布,重点关注硬件效率!查看主要版本亮点。 Apache Lucene 10 终于发布了!自 Lucene 9.0(于 2021 年 12 月发布,距今已有近 3 年)以来&a…...
【SQL】SQL查询语句
目录 🎄 基本查询语法 ⭐查询多个字段 ⭐设置别名 ⭐去除重复记录 ⭐ 数据准备 ⭐ 案例 🎄 条件查询 ⭐ 语法 ⭐ 案例 🎄 聚合函数 ⭐ 介绍 ⭐ 常见的聚合函数 ⭐ 语法 ⭐ 案例 🎄 分组查询 ⭐ 语法 ⭐ where与having的区…...
AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台
AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台 目录 AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台 一、简单介绍 二、Docker 下载安…...
机器学习摘下诺奖桂冠
前言 近日,2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者,这是历史上首次出现这样的情况。这项奖项原本只授予对自然现象和物质的物理学研究作出重大贡献的科学家,如今却将全球范围内对机器学习和神经网络的研究和开发作为了一…...
营销邮件软件:提升邮件营销效率必备工具!
营销邮件软件选择技巧?免费高效的邮件营销软件推荐? 如何高效地管理和优化邮件营销活动成为了企业面临的一大挑战。营销邮件软件成为提升邮件营销效率的必备工具。MailBing将深入探讨营销邮件软件的功能、优势以及如何选择合适的工具。 营销邮件软件&a…...
鸿蒙开发 四十五 鸿蒙状态管理(嵌套对象界面更新)
当运行时的状态变量变化,UI重新渲染,在ArkUI中称为状态管理机制,前提是变量必须被装饰器修饰。不是状态变量的所有更改都会引起刷新,只有可以被框架观测到的更改才会引起UI刷新。其中boolen、string、number类型,可观察…...
Graphormer效果展示:同一分子不同SMILES写法下的预测一致性验证
Graphormer效果展示:同一分子不同SMILES写法下的预测一致性验证 1. 模型概述 Graphormer是一种基于纯Transformer架构的图神经网络,专门为分子图(原子-键结构)的全局结构建模与属性预测而设计。该模型在OGB(Open Graph Benchmark)和PCQM4M等分子基准测…...
5分钟快速上手BilibiliDown:跨平台B站视频下载终极指南
5分钟快速上手BilibiliDown:跨平台B站视频下载终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/…...
Xinference-v1.17.1在Ubuntu上的实战应用:从环境准备到模型推理
Xinference-v1.17.1在Ubuntu上的实战应用:从环境准备到模型推理 1. 引言 Xinference作为一款开源AI模型推理平台,其1.17.1版本在Ubuntu系统上的表现尤为出色。本文将带你从零开始,完成在Ubuntu系统上部署Xinference并运行各类AI模型的完整流…...
2025界面字体设计效率提升指南:Bebas Neue开源字体全解析
2025界面字体设计效率提升指南:Bebas Neue开源字体全解析 【免费下载链接】Bebas-Neue Bebas Neue font 项目地址: https://gitcode.com/gh_mirrors/be/Bebas-Neue 在数字界面设计领域,字体选型直接影响用户体验与开发效率。作为2025年最受瞩目的…...
SpringBoot3与OAuth2.1实战:从/oauth/token到/oauth2/token的平滑迁移指南
1. 为什么需要从/oauth/token迁移到/oauth2/token 最近在升级SpringBoot3项目时,遇到了一个棘手的问题:原先运行良好的OAuth2认证接口突然失效了。仔细排查后发现,原来是Spring Security 6.x彻底重构了OAuth2的实现方式,最直观的…...
虚拟线程调度开销被严重低估?JVM源码级剖析vthread park/unpark的纳秒级损耗与4种对冲方案
第一章:虚拟线程调度开销被严重低估?JVM源码级剖析vthread park/unpark的纳秒级损耗与4种对冲方案虚拟线程(Virtual Thread)虽以轻量著称,但其 park/unpark 操作在 JVM 内部并非零成本——HotSpot 17 中,每…...
浏览器自动化之王:OpenClaw+Qwen3.5-9B实现复杂表单填充
浏览器自动化之王:OpenClawQwen3.5-9B实现复杂表单填充 1. 为什么需要智能表单填充 在日常工作中,我们经常需要处理各种复杂的在线表单。从税务申报到签证预约,这些表单往往包含数十个字段,字段之间存在复杂的逻辑关系。传统自动…...
Pixel Script Temple Java开发全栈入门:从环境安装到项目实战
Pixel Script Temple Java开发全栈入门:从环境安装到项目实战 1. 前言:为什么选择Java全栈开发? Java作为一门经久不衰的编程语言,在企业级应用开发中占据着重要地位。学习Java全栈开发不仅能让你掌握后端服务的构建能力&#x…...
NCM格式解密与转换完全指南:5大核心技巧释放音频文件价值
NCM格式解密与转换完全指南:5大核心技巧释放音频文件价值 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 在数字化音乐收藏日益普及的今天,网易云音乐的NCM加密格式成为许多音乐爱好者的困扰。ncmdump作为一款…...
版本降级实战:在VirtualBox 6.0.24中成功启用嵌套虚拟化
1. 为什么要在旧版本中启用嵌套虚拟化? 最近在调试一个遗留项目时,遇到了一个棘手的问题:客户的生产环境使用的是VirtualBox 6.0.24版本,而我们需要在这个虚拟机里再运行一个虚拟机(也就是嵌套虚拟化)。这个…...
