服务工作者更新时重新加载 Create-react-app
Create-react-app reload on service worker update
我想修改 create-react-app
service worker file 并实现弹出消息,如果更新的 service worker 准备好被激活,它会要求用户更新应用程序。我几乎完成了解决方案,但有一个陷阱。我想在用户确认服务工作者更新弹出窗口时重新加载应用程序,所以我在 register
函数的末尾添加了一些代码,见下文:
export default function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker."
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config)
}
let preventDevToolsReloadLoop
navigator.serviceWorker.addEventListener("controllerchange", function() {
// ensure refresh is called only once
if (preventDevToolsReloadLoop) {
return
}
preventDevToolsReloadLoop = true
console.log("reload")
window.location.reload(true)
})
})
}
}
但问题是,它也会在第一次访问时重新加载应用程序,当时还不存在任何服务工作者。我该如何解决?
尝试在installingWorker.state中添加onload函数==='installed'
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// do something ..
}
}
更新到 react-scripts
^3.2.0。确认您拥有新版本的 serviceWorker.ts 或 .js。旧的称为 registerServiceWorker.ts
并且 register 函数不接受配置对象。请注意,此解决方案仅在您不是延迟加载时才有效。
然后在 index.tsx:
serviceWorker.register({
onUpdate: registration => {
alert('New version available! Ready to update?');
if (registration && registration.waiting) {
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}
window.location.reload();
}
});
ServiceWorker.tsregister()
函数的最新版本接受一个带有回调函数的配置对象,我们可以在其中处理升级。如果我们 post 一条消息 SKIP_WAITING
这告诉 service worker 停止等待并继续并在下一次刷新后加载新内容。在此示例中,我使用 javascript 警报来通知用户。请将其替换为自定义吐司。
此 postMessage
函数起作用的原因是因为 CRA 在后台使用 workbox-webpack-plugin
,其中包括一个 SKIP_WAITING
侦听器。
关于 Service Worker 的更多信息
好指南:https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68
讨论服务工作者缓存的 CRA 问题:https://github.com/facebook/create-react-app/issues/5316
如果没有使用CRA,可以直接使用workbox:https://developers.google.com/web/tools/workbox
正在完成 :
因为您可能想在检测到比普通 alert
更复杂的更新后询问用户,您需要确保 registration
对象在 React 的组件内部可用树并保存它以在用户接受更新后使用(例如,通过单击按钮)。
作为一个选项,您可以在组件中为全局对象创建一个自定义事件侦听器,例如 document
并在 onUpdate
回调传递给 serviceWorker.register()
时触发此事件,传递resgistration
对象作为额外数据。
这正是我最近发表的 Service Worker Updater 所做的(一些自我推销)。要使用它,您只需要:
- 将其添加到依赖项中:
yarn add @3m1/service-worker-updater
- 在您的
index.js
中使用它:
import { onServiceWorkerUpdate } from '@3m1/service-worker-updater';
// ...
// There are some naming changes in newer Create React App versions
serviceWorkerRegistration.register({
onUpdate: onServiceWorkerUpdate
});
- 在你的一些 React 组件中使用它:
import React from 'react';
import { withServiceWorkerUpdater } from '@3m1/service-worker-updater';
const Updater = (props) => {
const {newServiceWorkerDetected, onLoadNewServiceWorkerAccept} = props;
return newServiceWorkerDetected ? (
<>
New version detected.
<button onClick={ onLoadNewServiceWorkerAccept }>Update!</button>
</>
) : null; // If no update is available, render nothing
}
export default withServiceWorkerUpdater(Updater);
我想修改 create-react-app
service worker file 并实现弹出消息,如果更新的 service worker 准备好被激活,它会要求用户更新应用程序。我几乎完成了解决方案,但有一个陷阱。我想在用户确认服务工作者更新弹出窗口时重新加载应用程序,所以我在 register
函数的末尾添加了一些代码,见下文:
export default function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config)
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
"worker."
)
})
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config)
}
let preventDevToolsReloadLoop
navigator.serviceWorker.addEventListener("controllerchange", function() {
// ensure refresh is called only once
if (preventDevToolsReloadLoop) {
return
}
preventDevToolsReloadLoop = true
console.log("reload")
window.location.reload(true)
})
})
}
}
但问题是,它也会在第一次访问时重新加载应用程序,当时还不存在任何服务工作者。我该如何解决?
尝试在installingWorker.state中添加onload函数==='installed'
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// do something ..
}
}
更新到 react-scripts
^3.2.0。确认您拥有新版本的 serviceWorker.ts 或 .js。旧的称为 registerServiceWorker.ts
并且 register 函数不接受配置对象。请注意,此解决方案仅在您不是延迟加载时才有效。
然后在 index.tsx:
serviceWorker.register({
onUpdate: registration => {
alert('New version available! Ready to update?');
if (registration && registration.waiting) {
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}
window.location.reload();
}
});
ServiceWorker.tsregister()
函数的最新版本接受一个带有回调函数的配置对象,我们可以在其中处理升级。如果我们 post 一条消息 SKIP_WAITING
这告诉 service worker 停止等待并继续并在下一次刷新后加载新内容。在此示例中,我使用 javascript 警报来通知用户。请将其替换为自定义吐司。
此 postMessage
函数起作用的原因是因为 CRA 在后台使用 workbox-webpack-plugin
,其中包括一个 SKIP_WAITING
侦听器。
关于 Service Worker 的更多信息
好指南:https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68
讨论服务工作者缓存的 CRA 问题:https://github.com/facebook/create-react-app/issues/5316
如果没有使用CRA,可以直接使用workbox:https://developers.google.com/web/tools/workbox
正在完成
因为您可能想在检测到比普通 alert
更复杂的更新后询问用户,您需要确保 registration
对象在 React 的组件内部可用树并保存它以在用户接受更新后使用(例如,通过单击按钮)。
作为一个选项,您可以在组件中为全局对象创建一个自定义事件侦听器,例如 document
并在 onUpdate
回调传递给 serviceWorker.register()
时触发此事件,传递resgistration
对象作为额外数据。
这正是我最近发表的 Service Worker Updater 所做的(一些自我推销)。要使用它,您只需要:
- 将其添加到依赖项中:
yarn add @3m1/service-worker-updater
- 在您的
index.js
中使用它:
import { onServiceWorkerUpdate } from '@3m1/service-worker-updater';
// ...
// There are some naming changes in newer Create React App versions
serviceWorkerRegistration.register({
onUpdate: onServiceWorkerUpdate
});
- 在你的一些 React 组件中使用它:
import React from 'react';
import { withServiceWorkerUpdater } from '@3m1/service-worker-updater';
const Updater = (props) => {
const {newServiceWorkerDetected, onLoadNewServiceWorkerAccept} = props;
return newServiceWorkerDetected ? (
<>
New version detected.
<button onClick={ onLoadNewServiceWorkerAccept }>Update!</button>
</>
) : null; // If no update is available, render nothing
}
export default withServiceWorkerUpdater(Updater);