我使用 CRA v4 创建了一个 PWA 模板,并通过注册启用了它附带的 Service Worker,因为我需要创建一个有关安装 PWA 的弹出通知。
应用必须通过灯塔测试才能兼容 PWA,以便浏览器能够触发检测用户是否已安装 PWA 所需的 beforeinstallprompt
事件监听器。
现在的问题是该服务工作人员正在使用缓存优先
策略。因此,刷新页面不会触发更新,部署更新后,我会看到旧版本的应用程序。
如何更改 CRA v4 服务工作线程的缓存策略,以便用户只需刷新页面即可获取新版本的应用程序?
我也有兴趣了解为什么默认使用这种缓存优先
策略。对我来说,用户必须关闭每个选项卡才能获得新版本似乎很糟糕。为什么没有更多人提出这个问题?这显然对用户不友好......
最佳答案
要更改策略,您需要实现自己的代码更改 service-worker.js 并可能 serviceWorkerRegistration.js。 (https://developers.google.com/web/tools/workbox/modules/workbox-strategies)
我实现自己的策略: 开头检查更新 如果开头更新有更新,则每 3 分钟检查一次更新 缓存并刷新网站。如果是在显示弹出窗口后要求刷新
serviceWorkerRegistration.ts
/**
* ...... previous code
**/
const CHECK_INTERVAL_TIME = 1000 * 60 * 3 // 3 min
function registerValidSW(swUrl: string, config?: Config) {
navigator.serviceWorker
.register(swUrl)
.then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://cra.link/PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.info('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
/****************************
start new code
*****************************/
registration.update().then(() => console.debug("Checked for update...")).catch(console.error)
setInterval(() => {
console.debug("Checked for update...");
registration.update().catch(console.error);
}, CHECK_INTERVAL_TIME);
/****************************
end new code
*****************************/
})
.catch((error) => {
console.error('Error during service worker registration:', error);
});
}
应用程序.tsx
/**
* ...... previous code
**/
function App() {
const time = useRef(Date.now()); //can be let, depending of your logic
useEffect(() => {
serviceWorkerRegistration.register({
onSuccess(registration) {
console.debug('serviceWorkerRegistration success')
},
onUpdate(registration) {
console.debug('serviceWorkerRegistration updated',Date.now()-time.current)
const refresh=async ()=>{
await registration?.waiting.postMessage({type: 'SKIP_WAITING'}); //send message to update the code (stop waiting)
if ('caches' in window) { //delete cache, i think is no necessary but you lose nothing
const names = await caches.keys()
for (const name of names) {
await caches.delete(name)
}
}
window.location.reload();
}
if (Date.now()-time.current<=2000){
return refresh()
}
logicToShowPopup({
onClick: refresh
})
}
})
}, [])
return (<div>My App</div>)
}
希望这能满足您的需求
关于reactjs - 创建 React App PWA - 更改 Service Worker 的缓存策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67520627/