服务工作者 - 使用 skipWaiting() 在新版本上更新缓存。

问题描述 投票:0回答:1

我已经实施了Workbox来使用webpack生成我的服务工作者。这很好用--当我运行 "generate-sw": "workbox inject:manifest".

问题是--我注意到我的客户在新版本发布后没有更新缓存。即使在更新服务工作者后的几天里,我的客户端仍然在缓存旧代码,新代码只有在多次刷新或取消注册服务工作者后才会加载。对于每一个版本,我都确认修订版已经更新。

我知道我需要实现 skipWaiting 以确保客户端得到更新--尤其是PWA。我已经阅读了,并尝试按照这里的第3种方法。https:/redfin.engineeringghin how-to-fix therefresh-button-when-using-serviceworkers-a8e27af6df68。.

我的应用程序安装在 app.js

我把这段代码添加到 serviceWorker-base.js

addEventListener('message', function(messageEvent){
  if (messageEvent.data === 'skipWaiting') return skipWaiting();
});

我有这样的代码 app.js

const runServiceWorker = true
const serviceWorkerAvailable = ('serviceWorker' in navigator) ? true : false

// reload once when the new Service Worker starts activating
let refreshing
navigator.serviceWorker.addEventListener('controllerchange', function() {
    if (refreshing) return
    refreshing = true
    window.location.reload()
  }
)

function promptUserToRefresh(reg) {
  // this is just an example - don't use window.confirm in real life; it's terrible
  if (window.confirm("New version available! OK to refresh?")) {
    reg.waiting.postMessage('skipWaiting')
  }
}

function listenForWaitingServiceWorker(reg, callback) {
  console.log('listenForWaitingServiceWorker')
  function awaitStateChange() {
    reg.installing.addEventListener('statechange', function() {
      if (this.state === 'installed') callback(reg)
    })
  }
  if (!reg) return
  if (reg.waiting) return callback(reg)
  if (reg.installing) awaitStateChange()
  reg.addEventListener('updatefound', awaitStateChange)
}

// Register service worker
if (runServiceWorker && serviceWorkerAvailable) {
  navigator.serviceWorker.register('/serviceWorker.js')
  .then( (registration) => {
    console.log('Service worker registered', registration)
    listenForWaitingServiceWorker(registration, promptUserToRefresh) // <-- Added to existing code
  })
}else{
  console.log('Service worker disabled - process.env.NODE_ENV', process.env.NODE_ENV)
}

这段代码的问题是 promptUserToRefresh() 只有在首次安装服务工时才会被调用,而不是在新的服务工等待时被调用!

另外,当接受第一次安装时,我得到了以下错误。

TypeError: registration.waiting is null
promptUserToRefresh app.js:154
awaitStateChange app.js:162

该错误在 promptUserToRefresh(registration)registration.waiting.postMessage('skipWaiting')

我也测试过这种方法,结果也是一样。https:/github.comGoogleChromeworkboxissues1120。

javascript caching service-worker workbox
1个回答
1
投票

在简单地重新排列后,代码现在可以工作了

更新了 app.js

// *** PWA Functionality START ***

// skipWaiting() functions
function promptUserToRefresh(registration) {
  // this is just an example - don't use window.confirm in real life; it's terrible
  if (window.confirm("New version available! Refresh?")) {
    registration.waiting.postMessage('skipWaiting')
  }
}
function listenForWaitingServiceWorker(registration) {
  console.log('listenForWaitingServiceWorker', registration)
  function awaitStateChange() {
    registration.installing.addEventListener('statechange', function() {
      if (this.state === 'installed') promptUserToRefresh(registration)
    })
  }
  if (!registration) return
  if (registration.waiting) return promptUserToRefresh(registration)
  if (registration.installing) awaitStateChange()
  registration.addEventListener('updatefound', awaitStateChange)
}
//**

const enableServiceWorker = true
const serviceWorkerAvailable = ('serviceWorker' in navigator) ? true : false
// Register service worker
if (enableServiceWorker && serviceWorkerAvailable) {
  navigator.serviceWorker.register('/serviceWorker.js')
  .then( (registration) => {
    console.log('Service worker registered', registration)
    listenForWaitingServiceWorker(registration) // ** skipWaiting() code
  })
}else{
  console.log('Service worker disabled - process.env.NODE_ENV', process.env.NODE_ENV)
}

// Install prompt event handler
export let deferredPrompt
window.addEventListener('beforeinstallprompt', (event) => {
  // Prevent Chrome 76 and later from showing the mini-infobar
  event.preventDefault()
  deferredPrompt = event // Stash the event so it can be triggered later.
  try{
    showInstallPromotion()
  }catch(e){
    console.error('showInstallPromotion()', e)
  }
})
window.addEventListener('appinstalled', (event) => {
  console.log('a2hs installed')
})
// *** PWA Functionality END *

也许是下面(删除)的线条造成了所有的麻烦?

// reload once when the new Service Worker starts activating
let refreshing
navigator.serviceWorker.addEventListener('controllerchange', function() {
    if (refreshing) return
    refreshing = true
    window.location.reload()
  }
)

现在剩下的就是想办法 在第一次访问应用程序安装时显示提示! (^__^)

© www.soinside.com 2019 - 2024. All rights reserved.