Javascript 服务工作者:如何缓存第一个(动态)页面
我有一个一页的应用程序,它有一个动态URL,其中包含一个令牌,比如Javascript 服务工作者:如何缓存第一个(动态)页面,javascript,progressive-web-apps,Javascript,Progressive Web Apps,我有一个一页的应用程序,它有一个动态URL,其中包含一个令牌,比如example.com/XV252GTH和各种资产,比如css、favicon等等 以下是我注册服务人员的方式: navigator.serviceWorker.register('sw.js'); 在所说的sw.js中,我在安装时预缓存资产: var cacheName = 'v1'; var cacheAssets = [ 'index.html', 'app.js', 'style.css',
example.com/XV252GTH
和各种资产,比如css、favicon等等
以下是我注册服务人员的方式:
navigator.serviceWorker.register('sw.js');
在所说的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());
});
请注意,index.html
(注册服务人员)页面只是一个模板,在发送到客户机之前在服务器上填充;所以在这个预缓存阶段,我只缓存模板,而不是页面
现在,在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));
}());
});
使用此更新功能
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;
});
});
}
但是,我如何才能确保它能够及时得到遵守,即:在软件安装完成后由客户端发送?在这种情况下,什么是好的做法?如果我理解错了,请纠正我
您可以在此处预缓存文件: 应该清楚的是,您缓存了模板,因为您在站点生成之前缓存了模板,而且这种方法没有错,至少对于所有类型的文件都没有错。
例如,您的<代码> FavigIon。ICO < /代码>是一个文件,您可能会将其视为<代码>静态< /代码>。而且,它不会经常更改或根本不会更改,也不像您的
index.html
那样是动态的因为有更新功能,所以在重新加载页面后为什么会有正确的版本也应该很清楚 这个问题的解决办法是回答您的问题: 如何将请求(
/XV252GTH
)从客户端(注册工作者的页面)发送到软件
如果后端构建了您的网页,您希望缓存它,而不是在安装服务工作程序之前缓存它。下面是它的工作原理:
您有一个空缓存,或者至少有一个没有index.html
的缓存
通常会向服务器发送请求以获取index.html
。相反,我们向缓存发出请求,并检查index.html
是否在缓存中,至少在您第一次加载页面时是这样
由于缓存中没有匹配项,请向服务器请求获取它。这与页面正常加载页面时会执行的请求相同。因此,服务器构建您的index.html
,并将其发送回页面
收到index.html
后,将其加载到页面并存储在缓存中
示例方法是重新验证时过时的:
如果有可用的缓存版本,请使用它,但获取更新供下次使用
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
return response || fetchPromise;
})
})
);
});
这些是解决你问题的基础。现在,您可以从中选择多种选项,使用相同的方法,但有一些附加功能。你选择哪一个取决于你自己,在不了解你的项目细节的情况下,没有人能告诉你选择哪一个。您也不限于一个选项。在某些情况下,您可能会将两个或多个选项组合在一起
谷歌写了一篇关于所有选项的文章,并提供了所有选项的代码示例。他们还解释了你的想法。并不是每一个选项都对你来说都是有趣和相关的,但我建议你把它们全部读一遍,并彻底阅读
这就是方法。好的,我从中得到了答案:要缓存在激活时注册工作者的页面,只需列出所有软件的客户端,并获取它们的(href
属性)
你不能使用浏览器历史api吗?我想提请大家注意我的答案,因为我相信这是一个更干净的解决方案,更普遍/最好的做法。你好,Aaron,你似乎是PWA方面的专家,我正在解决类似的问题,我可以设置可以缓存shell,但无法更新。你能看一下吗。谢谢你的夸奖。不幸的是,我不熟悉角。我曾经使用过其他前端框架,但这次没有。我不认为角度集成有什么问题,这部分工作得很好。我在升级过程中遇到的困难是我对SwUpdate
的理解。如果你能看看PwaService
的构造函数,告诉我是否有任何问题,那就足够了。好吧,至少我看不到任何问题。这可能就是你至今没有得到任何答案的原因。我不知道你对PWAs有多熟悉。如果您是新员工,您可能会忘记更新服务人员的步骤。注销您的服务人员,删除缓存(特别是从您的页面),启用“重新加载时更新”。。。否则,可能只是让旧的服务工作者使用旧的缓存运行。如果您更改服务人员的脚本,服务人员不会在默认情况下更新自己。谢谢Aaron。是的,我是PWA的新手,我不太了解注销、删除缓存、重新加载时更新。我想我没有做这些。让我看看这些。我的期望是更改ngsw config.json
将触发此.swUpdate.available
但即使此.swUpdate.isEnabled
为真,它也不会触发。
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('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
return response || fetchPromise;
})
})
);
});
self.clients.matchAll({includeUncontrolled: true}).then(clients => {
for (const client of clients) {
updateCache(new URL(client.url).href);
}
});