如何防止 Chrome 在离线时加载缓存的网页?

How can I prevent Chrome from loading a cached webpage when offline?

重现问题的步骤:

  1. 用户访问网页,见下面代码
  2. 用户关闭Chrome.
  3. 设备完全离线(手动关闭所有网络)。
  4. 用户在完全离线的情况下重新打开浏览器。
  5. Chrome 自动提供上次访问的页面,即显示 Online? true 的网页的保存副本,即使在多次点击刷新后也是如此。

唯一告诉用户 she/he 正在查看一些陈旧的、完全无法使用的网页副本的是地址栏中的这个:

非技术用户很容易忽略这一点,并想知道为什么页面无法使用...这是糟糕的用户体验。

浏览器和设备:Chrome Android 81 在 Acer Iconia Tab 10 A3-40 平板电脑 上 6。

该网页是通过 HTTPS(安全连接)提供的。

代码:

const setMsg = (flag) => {
  const p = document.getElementById('msg')
  p.innerHTML = '<b>Online?</b>  ' + flag
}

setMsg(navigator.onLine)

window.addEventListener("online", () => {
  setMsg(true)
})
window.addEventListener("offline", () => {
  setMsg(false)
})
<p id='msg'> </p>

据我所知:

到目前为止,我唯一能防止这种情况发生的方法是注册一个 service worker。当我有一个 service worker 注册时,JavaScript 是 re-运行 并且我可以正确明确地通知用户 she/he 已离线。

如果没有 service worker,我如何防止Chrome在离线时加载过时的、无法使用的网页?

通常的 "No internet" 恐龙页面是合适的,这正是我对 Cache-Control: no-store 的期望。

一个非常不优雅的解决方法是使用 CSS 动画,使 "offline" 元素在设定的时间后立即全部出现。使用 JavaScript,您可以不断地重置动画,防止它显示 unless/until JavaScript 不再 运行 重置它。

下例中的动画设置为3秒,并使用关键帧停留在opacity:0,直到动画持续时间的99%,此时变为opacity:1

在JavaScript中,我们可以使用JavaScript每隔1-2秒重置一次动画,方法是删除与其关联的class,强制回流(通过fetching the offsetWidth,例如),然后添加动画 class 回来。

理想情况下 我们可以告诉 Chrome 在这些移动设备上根本不缓存页面。我们在问题的评论中尝试的各种 headers 移动设备不尊重 运行 无法访问互联网。

禁用缓存在概念和执行上都是更合适的解决方案。具有永久强制回流的 运行 JavaScript 间隔并不好。但是,它确实向用户表明 JavaScript 引擎已停止 运行,这就是这里的情况。

在下面的示例中,"Simulate stop JS"按钮只是清除了正在继续重置加载动画的间隔。这只是一个模拟,但与 JavaScript 而非 运行 具有相同的效果(在独立服务器上测试)。

const overlay = document.getElementById('offline-overlay');

const stopJS =  document.getElementById('stopJS');

const heartbeat = () => {
  overlay.classList.remove("animate-overlay");
  void overlay.offsetWidth; 
  overlay.classList.add("animate-overlay");
}

const heartbeatInterval = setInterval( heartbeat, 1000);

stopJS.addEventListener("click", function(){
  clearInterval(heartbeatInterval);
});
@keyframes offline {
  0%   {opacity:0;}
  99%  {opacity:0;}
  100% {opacity:1;}
}

.animate-overlay{
  animation-name: offline;
  animation-duration: 3s;
}

#offline-overlay{
  background-color: rgba(255,255,255,.9);
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  display:flex;
  justify-content: center;
  align-items:center;
  pointer-events:none;
}

#offline-overlay span{
  font-size:300%;
  font-family: sans-serif;
  letter-spacing:5px;
  color: #888;
}
  <div id="offline-overlay" class="animate-overlay">
    <span>OFFLINE</span>
  </div>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam varius quam sed nulla feugiat varius. Praesent vitae mi et libero porttitor maximus. Suspendisse eu pulvinar quam. Phasellus id ante a elit faucibus cursus. Curabitur porttitor vehicula ornare. Suspendisse nec risus ex. Aenean bibendum auctor ex eget aliquet. Donec laoreet sem ut tortor viverra aliquam.</p>

<button id="stopJS">Simulate Stop JS</button>