在 PWA 中,我有一个定期更新的大数据文件。我认为将最新版本缓存在我的服务工作者中以提供离线支持会很好,但只有最新版本。我不希望旧版本的数据文件占用磁盘空间。
我正在使用 Workbox(版本 6.1.2),所以我尝试在我的服务人员中写这个:
registerRoute(
new RegExp("/gen/real-player-data-*"),
new CacheFirst({
cacheName: "real-player-data",
plugins: [
new ExpirationPlugin({
maxEntries: 1,
purgeOnQuotaError: true,
}),
],
}),
);
为了完整起见,我的全方位服务人员是:
import * as googleAnalytics from "workbox-google-analytics";
import { ExpirationPlugin } from "workbox-expiration";
import {
cleanupOutdatedCaches,
createHandlerBoundToURL,
precacheAndRoute,
} from "workbox-precaching";
import { CacheFirst } from "workbox-strategies";
import { NavigationRoute, registerRoute } from "workbox-routing";
registerRoute(
new RegExp("/gen/real-player-data-*"),
new CacheFirst({
cacheName: "real-player-data",
plugins: [
new ExpirationPlugin({
maxEntries: 1,
purgeOnQuotaError: true,
}),
],
}),
);
// Will be filled in by tools/build-sw.js
precacheAndRoute(self.__WB_MANIFEST);
const handler = createHandlerBoundToURL("/index.html");
const navigationRoute = new NavigationRoute(handler, {
denylist: [
new RegExp("^/files"),
new RegExp("^/fonts"),
new RegExp("^/gen"),
new RegExp("^/ico"),
new RegExp("^/img"),
new RegExp("^/manifest"),
new RegExp("^/sw.js"),
],
});
registerRoute(navigationRoute);
// https://developers.google.com/web/tools/workbox/guides/migrations/migrate-from-v3
cleanupOutdatedCaches();
googleAnalytics.initialize();
我的数据文件已命名/gen/real-player-data-HASH.json
,所以我认为这会做我想做的事 - 请注意,当我的应用程序请求我的数据文件的新版本时,将其添加到缓存中,然后删除旧版本。
在实践中,这似乎只是部分起作用。它确实会创建缓存并将数据存储在那里,但文件的旧版本似乎永远不会被删除。
自己试试。转到https://play.basketball-gm.com/new_league/real将安装 service worker 并请求数据文件,如果你让它完全加载的话。您可能需要重新加载一次才能在 Chrome 开发工具中看到它。在撰写此问题时,最新版本的数据文件是https://play.basketball-gm.com/gen/real-player-data-2a6c8e9b0b.json :
(旁注 - 我不确定为什么它说 Content-Length 为 0,您可以清楚地看到底部窗格中的数据。)
现在,安装了 service worker,如果你只是去我的数据文件的旧版本,比如https://play.basketball-gm.com/gen/real-player-data-540506bc45.json应该被上面定义的路由,我相信它应该导致以前的文件从缓存中删除。
它确实被拾取了,但现在缓存中有两个条目,另一个没有被删除:
它们不仅仅是空的占位符,您可以在底部窗格中查看两个文件中的数据。
尝试更多,您会在列表中获得更多,似乎没有限制:
https://play.basketball-gm.com/gen/real-player-data-18992d5073.json
https://play.basketball-gm.com/gen/real-player-data-fe8f297ea7.json
https://play.basketball-gm.com/gen/real-player-data-fd28409152.json
我在 Ubuntu 上使用 Chrome 89。
知道我做错了什么吗?还是有更好的方法来实现我的目标?
次日更新
我在我的服务人员中做了一些 console.log 调试。似乎 Workbox 基本上工作正常,除了这段代码实际上是从缓存中删除旧条目:
for (const url of urlsExpired) {
await cache.delete(url, this._matchOptions);
}
这是我编辑它的内容,用于调试:
console.log('urlsExpired', urlsExpired);
console.log('keys', await cache.keys());
for (const url of urlsExpired) {
console.log('delete', url, this._matchOptions);
const deleted = await cache.delete(url, this._matchOptions);
console.log('after delete', url, deleted);
}
console.log('keys2', await cache.keys());
这是我在执行上面写的操作时看到的输出(加载服务工作者,加载第一个数据文件,加载第二个数据文件,观察这个输出,因为它试图从缓存中删除第一个数据文件但失败):
所以它确实识别了它需要从缓存中删除的旧 URL。它确实会在缓存中看到旧 URL 和新 URL。但该cache.delete
调用解析为false
. MDN 说:
解析为
true
缓存条目是否被删除,false
否则
如果它没有找到该项目,它会解析为 false。
所以我想这意味着它没有找到该项目?但看截图,URL 匹配缓存中的条目。MDN说cache.delete 的第一个参数可以是 Request 对象或 URL。
这是 Chrome 中的错误吗?工作箱中的错误?还有什么?我在这里没有想法。