Service Worker:如何缓存第一个(动态)页面

yPh*_*hil 3 javascript progressive-web-apps

我有这个单页应用程序,带有使用令牌构建的动态 URL,例如example.com/XV252GTHcss、favicon 等各种资产。

以下是我注册 Service Worker 的方法:

navigator.serviceWorker.register('sw.js');
Run Code Online (Sandbox Code Playgroud)

在所述中sw.js,我在安装时预先缓存了资源:

var cacheName = 'v1';

var cacheAssets = [
    'index.html',
    'app.js',
    'style.css',
    'favicon.ico'
];

function precache() {
    return caches.open(cacheName).then(function (cache) {
        return cache.addAll(cacheAssets);
    });
}

self.addEventListener('install', function(event) {
    event.waitUntil(precache());
});
Run Code Online (Sandbox Code Playgroud)

请注意,index.html(注册 Service Worker 的)页面只是一个模板,在发送到客户端之前会在服务器上填充;所以在这个预缓存阶段,我只缓存模板,而不缓存页面。

现在,在 fetch 事件中,任何不在缓存中的请求资源都会被复制到缓存中:

addEventListener('fetch', event => {
    event.respondWith(async function() {
        const cachedResponse = await caches.match(event.request);
        if (cachedResponse) return cachedResponse;       
        return fetch(event.request).then(updateCache(event.request));
    }());
});
Run Code Online (Sandbox Code Playgroud)

使用此更新功能

function updateCache(request) {
    return caches.open(cacheName).then(cache => {
        return fetch(request).then(response => {
            const resClone = response.clone();
            if (response.status < 400)
                return cache.put(request, resClone);
            return response;
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

在这个阶段,所有资源都在缓存中,但动态生成的页面还没有。只有重新加载后,我才能在缓存中看到另一个条目:/XV252GTH现在,该应用程序已离线就绪;但页面的重新加载有点违背了整个 Service Worker 的目的。

问题:如何将/XV252GTH客户端(注册worker的页面)的请求( )发送到SW?我想我可以设置一个监听器sw.js

self.addEventListener('message', function(event){
    updateCache(event.request)
});
Run Code Online (Sandbox Code Playgroud)

但我如何才能确保它会及时兑现,即:在软件安装完成后由客户端发送?在这种情况下,什么是好的做法?

yPh*_*hil 5

好的,我从这个页面得到了答案:要缓存在激活时注册工作人员的页面,只需列出所有 SW 的客户端,并获取它们的URLhref属性)。

self.clients.matchAll({includeUncontrolled: true}).then(clients => {
    for (const client of clients) {
        updateCache(new URL(client.url).href);
    }
});
Run Code Online (Sandbox Code Playgroud)