更新使用 cra-template-pwa 创建的 PWA
Updating PWA created with cra-template-pwa
我使用 cra-template-pwa
模板创建了一个带有 create-react-app
的 PWA,但我在更新应用程序时遇到了问题。
现在可以正确检测到内容并在控制台中显示消息:
New content is available and will be used when all tabs for this page are closed. See https://cra.link/PWA
问题是,即使通过 window.location.reload(true);
刷新页面后,内容也没有更新。在浏览器中,我实际上必须使用 Shift + F5 进行硬重新加载才能显示新内容。
这让我相信我可能需要删除缓存,但这样做会导致在浏览器中出现 ERR_FAILED
。
那么在更新后重新加载我的 PWA 的正确方法是什么?
这是处理更新的相关函数:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.
register(swUrl).
then((registration) => {
registration.update();
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker === null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
console.log('New content is available and will be used when all ' +
'tabs for this page are closed. See https://cra.link/PWA.',);
toast.info('Update available! Click to update app.', {
toastId: 'appUpdateAvailable',
onClose: () => {
window.caches.keys().then((keys) => {
for(let i = 0; i < keys.length; i += 1) {
caches.delete(keys[i]);
}
window.location.reload(true);
});
},
autoClose: false
});
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
}).
catch((error) => {
console.error(
'Error during service worker registration:',
error
);
});
}
诀窍是跳过等待新服务工作者。
我这样调整了 service worker 注册:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.
register(swUrl).
then((registration) => {
registration.update();
setInterval(() => {
// Check for updates every 5 minutes
registration.update();
}, 1000 * 60 * 5);
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.',);
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
toast.info('Update available! To update, refresh this tab.', {
toastId: 'appUpdateAvailable',
autoClose: false
});
// 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.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
}).
catch((error) => {
console.error(
'Error during service worker registration:',
error
);
});
}
这将通知用户有新的更新可用,他必须刷新浏览器。简单的重新加载后,将加载新版本。无需手动清除缓存。
我使用 cra-template-pwa
模板创建了一个带有 create-react-app
的 PWA,但我在更新应用程序时遇到了问题。
现在可以正确检测到内容并在控制台中显示消息:
New content is available and will be used when all tabs for this page are closed. See https://cra.link/PWA
问题是,即使通过 window.location.reload(true);
刷新页面后,内容也没有更新。在浏览器中,我实际上必须使用 Shift + F5 进行硬重新加载才能显示新内容。
这让我相信我可能需要删除缓存,但这样做会导致在浏览器中出现 ERR_FAILED
。
那么在更新后重新加载我的 PWA 的正确方法是什么?
这是处理更新的相关函数:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.
register(swUrl).
then((registration) => {
registration.update();
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker === null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
console.log('New content is available and will be used when all ' +
'tabs for this page are closed. See https://cra.link/PWA.',);
toast.info('Update available! Click to update app.', {
toastId: 'appUpdateAvailable',
onClose: () => {
window.caches.keys().then((keys) => {
for(let i = 0; i < keys.length; i += 1) {
caches.delete(keys[i]);
}
window.location.reload(true);
});
},
autoClose: false
});
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
}).
catch((error) => {
console.error(
'Error during service worker registration:',
error
);
});
}
诀窍是跳过等待新服务工作者。
我这样调整了 service worker 注册:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.
register(swUrl).
then((registration) => {
registration.update();
setInterval(() => {
// Check for updates every 5 minutes
registration.update();
}, 1000 * 60 * 5);
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.',);
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
toast.info('Update available! To update, refresh this tab.', {
toastId: 'appUpdateAvailable',
autoClose: false
});
// 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.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
}).
catch((error) => {
console.error(
'Error during service worker registration:',
error
);
});
}
这将通知用户有新的更新可用,他必须刷新浏览器。简单的重新加载后,将加载新版本。无需手动清除缓存。