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

Ali*_*Ali 8 html javascript google-chrome cache-control service-worker

重现问题的步骤:

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

告诉用户她/他正在查看一些陈旧的、完全无法使用的网页副本的唯一信息是地址栏中的:

在此处输入图片说明

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

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

该网页通过 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)
})
Run Code Online (Sandbox Code Playgroud)
<p id='msg'> </p>
Run Code Online (Sandbox Code Playgroud)

据我所知:

  • 即使点击刷新,Chrome 也不会在第 5 步中重新运行任何JavaScript。
  • Chrome也不尊重Cache-Control: private, no-store两者;双重检查。

到目前为止,我可以防止这种情况发生的唯一方法是注册一个 Service Worker。当我注册了 Service Worker 时,JavaScript 会重新运行,我可以正确而明确地通知用户她/他处于离线状态。

如果没有Service Worker,如何防止 Chrome 在离线时加载陈旧、无法使用的网页?

通常带有恐龙的“无互联网”页面是合适的,这就是我对Cache-Control: no-store.

tmd*_*ned 7

一个非常不优雅的解决方法是使用 CSS 动画,使“离线”元素在设定的时间后立即出现。使用 JavaScript,您可以不断重置动画,防止动画显示,除非/直到 JavaScript 不再运行来重置它。

下面示例中的动画设置为 3 秒,并使用关键帧保持opacity:0直到动画持续时间的 99%,此时它会更改为opacity:1

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

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

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

在下面的例子中,“模拟停止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);
});
Run Code Online (Sandbox Code Playgroud)
@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;
}
Run Code Online (Sandbox Code Playgroud)
  <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>
Run Code Online (Sandbox Code Playgroud)