Angular 5中用Angular CLI通过Service Worker实现API缓存及数据变更咨询
Hey,作为刚上手Service Worker的新手,你的这两个问题都是实际开发中非常常见的场景,我来给你详细说说~
首先得明确:当你把策略设为"performance"(也就是业内常说的缓存优先策略)时,Service Worker的执行逻辑是固定的:
- 收到前端请求后,第一时间去本地缓存中查找对应的响应
- 如果缓存命中,直接返回旧缓存内容,完全不会发起网络请求去服务器验证数据是否更新
- 只有当缓存中没有该请求的响应时,才会去请求服务器,并把新响应存入缓存
所以回到你的核心疑问:如果数据库数据变更导致服务器上的响应内容更新了,默认情况下,用户还是会拿到旧的缓存数据——因为Service Worker根本不会主动去服务器检查新内容,除非缓存里没有这个条目。
那怎么解决这个问题?给你几个实用的方案:
- 版本化缓存名称:给你的缓存设置带版本号的名称(比如
api-cache-v1),当数据有重大变更时,更新Service Worker脚本里的缓存版本号。这样Service Worker会触发重新安装流程,创建新的缓存空间,后续请求就会拉取新的响应并存入新缓存。 - 主动更新指定缓存条目:当你明确知道数据发生变更时(比如后台管理端触发了数据更新),可以通过Service Worker的API主动更新特定的缓存条目。比如调用:
这样就能强制拉取新的响应并替换旧缓存。caches.open('你的缓存名称').then(cache => cache.add('目标API地址')) - 切换为"Stale-While-Revalidate"策略:如果既想保证性能(优先用缓存),又想尽量获取最新数据,可以换成这个策略。它会先返回缓存内容,同时后台悄悄发起网络请求更新缓存,下次请求就能拿到新数据了。不过这个策略更适合对实时性要求不是极高的场景。
Angular 5已经支持官方的Service Worker,结合Angular CLI可以很方便地配置API缓存,步骤如下:
1. 安装Service Worker依赖
在项目根目录运行命令:
npm install @angular/service-worker --save
2. 启用Service Worker支持
打开.angular-cli.json(Angular 5使用的是旧版CLI配置文件),找到apps数组里你的应用配置项,添加"serviceWorker": true。
3. 配置缓存规则(ngsw-config.json)
在项目根目录创建ngsw-config.json文件,这是Service Worker的配置核心。针对API请求,你需要配置dataGroups字段,示例如下:
{ "index": "/index.html", "assetGroups": [ // 这里可以配置静态资源的缓存规则,比如CSS、JS、图片等 ], "dataGroups": [ { "name": "api-cache", "urls": [ "/api/**" // 匹配你的所有API路径,根据实际业务调整 ], "cacheConfig": { "strategy": "performance", // 这里设置你需要的performance策略 "maxSize": 100, // 最多缓存100个API响应 "maxAge": "7d", // 缓存有效期7天,可按需调整 "timeout": "5s" // 如果5秒内网络请求未返回,直接使用缓存 } } ] }
4. 在AppModule中注册Service Worker
打开src/app/app.module.ts,导入ServiceWorkerModule并在imports数组中注册:
import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; @NgModule({ imports: [ // 其他业务模块 ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) ] }) export class AppModule { }
5. 处理API数据变更的缓存更新
如果你坚持使用performance策略,同样会面临之前提到的缓存不自动更新问题,这里给你两个解决思路:
- 利用Angular提供的
SwUpdate服务,在数据变更后主动检查Service Worker更新。比如在组件中添加逻辑:import { SwUpdate } from '@angular/service-worker'; constructor(private swUpdate: SwUpdate) { if (this.swUpdate.isEnabled) { this.swUpdate.checkForUpdate().then(() => { // 有更新时提示用户刷新页面 if (confirm('有新内容可用,是否刷新?')) { window.location.reload(); } }); } } - 给API响应设置
ETag或Last-Modified头,这样当Service Worker触发缓存更新时,会验证服务器响应是否新鲜,避免缓存旧数据。
注意:Angular 5的Service Worker默认只在生产环境生效(因为我们配置了enabled: environment.production),所以测试缓存功能时,需要构建生产版本来验证。
内容的提问来源于stack exchange,提问作者Aji

