1

在 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 :

Chrome devtools 在真实玩家数据缓存中显示一个条目

(旁注 - 我不确定为什么它说 Content-Length 为 0,您可以清楚地看到底部窗格中的数据。)

现在,安装了 service worker,如果你只是去我的数据文件的旧版本,比如https://play.basketball-gm.com/gen/real-player-data-540506bc45.json应该被上面定义的路由,我相信它应该导致以前的文件从缓存中删除。

它确实被拾取了,但现在缓存中有两个条目,另一个没有被删除:

Chrome devtools 在真实玩家数据缓存中显示 2 个条目

它们不仅仅是空的占位符,您可以在底部窗格中查看两个文件中的数据。

尝试更多,您会在列表中获得更多,似乎没有限制:

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

Chrome devtools 在真实玩家数据缓存中显示 5 个条目

我在 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 中的错误吗?工作箱中的错误?还有什么?我在这里没有想法。

4

1 回答 1

1

问题是在我对数据文件的响应中设置了“Vary”标头,这意味着除非启用ExpirationPlugin选项,否则它将不起作用。ignoreVary

于 2021-04-16T00:44:40.367 回答