Workbox.js precacheAndRoute不提供新内容

时间:2018-08-24 17:13:06

标签: service-worker workbox

我已经使用MkDocsWorkboxjs创建了一个脱机文档。

我对由MkDocs生成的文件执行workbox generateSW,该文件会使用precacheAndRoute函数通过预缓存设置生成Service Worker。

这很好,但是当我更新文档并生成新的html文件和Service Worker时,直到完全关闭浏览器,它才提供新内容。刷新或仅关闭选项卡是不够的。

工作程序正在正确地将内容更新到缓存存储中,这可以从Chrome devtools中看到(应用程序->缓存存储-> workbox-precache *),但是无论我点击多少次刷新,浏览器都不会显示新内容。

我使用此功能来注册Service Worker

async function register() {
    const registration = await navigator.serviceWorker.register(SW_URL);

    registration.onupdatefound = () => {
        const installingWorker = registration.installing;

        installingWorker.onstatechange = () => {
            if (installingWorker.state === "installed") {
                if (navigator.serviceWorker.controller) {
                    console.log(
                        "New content is available; please refresh."
                    );
                } else {
                    console.log("Content is cached for offline use.");
                }
            }
        };
    };
}

我想知道是否需要做一些额外的事情才能使内容正确刷新?

我的workbox-config.js是

module.exports = {
    globDirectory: ".doc_build",
    globPatterns: ["**/*"],
    swDest: ".doc_build/sw.js"
};

在Firefox和Chrome上都会发生这种情况。

1 个答案:

答案 0 :(得分:0)

感谢罗伯特·罗恩特里(Robert Rowntree)在我发现的问题注释中的链接。

我的情况是刷新了内容以缓存,但旧版本的precache服务工作程序仍然保持运行状态,其中包含这样的对象列表

{
  "url": "index.html",
  "revision": "e4919b0cd0e772b3beb2d1f3d09af437"
}

如您所见,它具有旧版本的校验和,它将一直提供该服务,直到停用旧的服务工作者并激活新的服务。

通过查看registration.waiting可以看到,当旧的服务工作者正在等待停用并安装新的服务工作者时。似乎浏览器“在某个时候”执行了此操作。如果我仅将标签关闭足够长的时间,这似乎确实发生了。

我的问题的解决方案是强制服务人员跳过等待时间。可以通过从更新事件向服务工作者发送消息来做到这一点

async function register() {
    const registration = await navigator.serviceWorker.register(SW_URL);
    registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        installingWorker.onstatechange = async () => {
            if (installingWorker.state === "installed") {
                if (navigator.serviceWorker.controller) {
                    console.log(
                        "New content is available; please refresh."
                    );
                    // Send message to the service worker telling
                    // it should stop waiting for browser to deactivate it
                    registration.waiting.postMessage("skipWaiting");
                } else {
                    console.log("Content is cached for offline use.");
                }
            }
        };
    };
}

然后在Service Worker代码中,我必须处理该消息并调用skipWaiting()

self.addEventListener("message", messageEvent => {
    if (messageEvent.data === "skipWaiting") {
        return skipWaiting();
    }
});

为此,我必须从workbox generateSW移至workbox injectManifest才能添加跳过代码。

但是此解决方案中有一些警告。从

开始阅读Robert的链接
  

“最简单,最危险的方法就是跳过安装过程中的等待。”

https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68

幸运的是,这对于我的情况已经足够了。