create-react-app
has registerServiceWorker.js
by default.
I knew that this feature enable offline caching, but I felt it was hard to understand how to handle it (and sometime disalbed it).
I try to make show reload modal example like this.
1. Prepare
By Default create-react-app, is not easy for local service-worker debugging.
I eject
create-react-app and install serve
. ( and need disable serve
cache-control. )
{
"scripts": {
"start":
"NODE_ENV=production webpack --config config/webpack.config.prod.js --watch",
"static": "serve -c 0 -s build -o --local"
}
}
And start like this.
$ yarn start & yarn static
2. Append event dispatching when onupdatefound
When ServiceWorker detects an update, onupdatefound
of registerServiceWorker
is executed, and I append distpatch event here.
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log("New content is available; please refresh.");
// Append dispatch event
const event = new Event("newContentAvailable");
window.dispatchEvent(event);
} else {
:
In next version, service worker script got config.onUpdate
callback.
We do not need to add the code directly to registerServiceWorker.js
2. Create <ReloadModal>
Next, I append <ReloadModal>
that catch global custom newContentAvailable
event.
// Main App
class App extends Component {
render() {
return (
<div className="App">
<ReloadModal />
:
</div>
);
}
}
class ReloadModal extends Component {
state = {
show: false
};
componentDidMount() {
// Handle global event.
window.addEventListener("newContentAvailable", () => {
this.setState({
show: true
});
});
}
onClick = () => {
// Reload when modal click.
window.location.reload(window.location.href);
};
render() {
if (!this.state.show) {
return null;
}
// <Modal> is common fixed component.
return (
<Modal onClick={this.onClick}>
<span> New Content Available!please reload </span>
</Modal>
);
}
}
Conclusion
After this, I can got result like screenshot.
But I'm not confident in this implementation.
Please tell me if more better way.
Top comments (4)
Hi, great post !
What is the eject for?
Thank you.
Eject mean execute
$ npm run eject
It's need when article posted timing, but currently, it's may not need.
Hi, what happens if the user has one more instance of the app open and we try to reload the page?
Sorry, I'm not try that...
But I suspect that effect both browser because cache stored in brower storage.