如何控制 PWA 是使用缓存版本还是获取最新版本?
Posted
技术标签:
【中文标题】如何控制 PWA 是使用缓存版本还是获取最新版本?【英文标题】:How to control if PWA uses cached version or fetches latest version? 【发布时间】:2019-01-23 07:51:57 【问题描述】:我已经从 android 上的 Chrome 和 Firefox 以及 ios 上的 Safari 安装了我的 PWA。当我在网站上更新我的代码时,我看到 PWA 在使用旧缓存版本和最新版本方面的行为完全不同 - Firefox 创建的 PWA 似乎需要大约 2-3 次终止和重新启动 PWA,Chrome 需要 5 -6,如果不删除 PWA 并从浏览器重新添加到主屏幕,我无法让基于 Safari 的 PWA 开始显示最新版本。
是否有规范定义获取较新的非缓存版本的条件?经过大量阅读,我禁用了我的服务工作者的注册,这应该使 PWA 仅网络(没有服务工作者缓存),但我继续在 PWA 中提供旧版本的站点。一个普通的浏览器窗口似乎也需要多次深度刷新才能获得新版本,所以我认为除了 service worker 之外还有其他东西决定了这一点?
【问题讨论】:
我认为问题更多的是你如何为你的 PWA 提供服务,它是否首先是缓存,如果是,那么它将响应来自缓存文件的请求,而不是从网络获取它 您能否详细说明您的意思? 【参考方案1】:考虑以下代码。我将把它分成几部分:
self.addEventListener('fetch', function(event)
event.respondWith(
caches.match(event.request)
.then(function(response)
// Cache hit - return response
if (response)
return response;
return fetch(event.request).then(
function(response)
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic')
return response;
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have two streams.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache)
cache.put(event.request, responseToCache);
);
return response;
);
)
);
);
这里使用的是缓存优先策略,每当你重新加载页面时,就会触发一个 fetch 事件。
caches.match(event.request)
.then(function(response)
// Cache hit - return response
if (response)
return response;
首先它检查所需的请求是否在缓存中可用,如果是则它将返回响应并且不会从网络获取。
return fetch(event.request).then(
function(response)
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic')
return response;
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have two streams.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache)
cache.put(event.request, responseToCache);
);
return response;
);
)
);
现在,如果文件不存在于缓存中,则此块会进入网络收集所需的文件,然后对其进行响应,并将其保存到缓存中以供进一步使用。
假设您有一个文件 sample.html 并且它已被缓存,现在您对文件的代码进行了一些更改,但这些更改不会在您的浏览器上看到,因为它会看到 sample.html(旧) 已经存在于缓存中并用它来响应。
【讨论】:
谢谢,但如果我没有注册 Service Worker(如上所述),那么它应该总是进行网络获取,而不是缓存? 你可能会使用 window.loaction.reload(true) ***.com/questions/5721704/… 我建议你使用 Service Worker,因为它们适用于 PWA【参考方案2】:关于 SW 和 PWA 的一些通用注意事项: 注册 Service Worker (SW) 后,您必须取消注册以确保获得最新/更新版本,您可以在 Service Worker 下的应用程序选项卡中执行此操作
然后
确保您获得 PWA 的最新/更新版本。除此之外,您还可以做些什么,您可以更改缓存存储的对象名称,如下所示: .
只要您保持对象名称相同并且不注销软件并清除缓存存储,您将不得不刷新您的网站。如果您按住浏览器的刷新按钮几秒钟,还有硬重新加载/清除缓存和硬重新加载选项,但在您取消注册服务工作者之前它仍然不起作用。因此,简而言之,取消注册 SW 并手动清除缓存存储或更改缓存存储对象的名称就可以解决问题。像任何其他技术/资产一样,有利也有弊。这是 PWA 的缺点之一,如果我们没有正确使用它,您的客户将永远无法获得最新版本,或者他获得它的时间可能为时已晚。干杯:)
【讨论】:
以上是关于如何控制 PWA 是使用缓存版本还是获取最新版本?的主要内容,如果未能解决你的问题,请参考以下文章