PWA の更新方法
use-pwa をアップデートしました。
今新しい Web サービスをゆっくり作っていまして、PWA 対応を行おうとしています。
上記の旧バージョンのパッケージで PWA 対応自体は問題なく行えるのですが、問題はアップデートでして。
PWA はアップデートが非常にややこしく、自分も詳しくは理解できていないのですが。
基本的にはブラウザと同様で、画面を表示する際にキャッシュを優先するみたいです。
で、おそらくブラウザと同じキャッシュを参照しているようなので、逆に言えばブラウザのキャッシュが削除または更新されない限り PWA 側も更新されないみたいです。
普段から定期的にブラウザのキャッシュを削除する人はそこまで多くないでしょうし、PWA をインストールしたのにブラウザを起動しないと更新できないというのは少し本末転倒感があります。
そのため色々と更新方法を調べたところ PWA におけるキャッシュの更新方法 という記事を見つけました。
上記の記事によると PWA の更新はキャッシュを削除することで実現しているようです。
ただ上記の記事では Service Worker の登録時に更新を管理する処理を仕込むように書かれていますが、Service Worker の登録状態は登録時でなくとも普段時から JavaScript にて取得可能です。
const registration = await window.navigator.serviceWorker.getRegistration();
そのため Service Worker を仕込む処理の有無にかかわらず PWA の更新処理を書くことが可能です。
ということで無事 use-pwa に PWA の更新検知処理、および更新処理を追加することができました。(実際のコードはGitHubで公開しています)
自分の環境で正常動作も確認済みです。
お前の作ったパッケージなんか使わねーよ!という方のために、ざくっとコードを書いておきます。
const [enabledUpdate, setEnabledUpdate] = useState(false);
const unregister = useCallback(async () => {
if (!("serviceWorker" in window.navigator)) {
return;
}
const registration = await window.navigator.serviceWorker.getRegistration();
if (!registration) {
return;
}
const result = await registration.unregister();
return result;
}, []);
const handleClick = useCallback(async () => {
const result = await unregister();
if (result) {
alert("The update was successful, restart the app.");
window.location.reload();
return;
}
alert("Update failed.");
}, [unregister]);
useEffect(() => {
const callback = async () => {
if (!("serviceWorker" in window.navigator)) {
return;
}
const registration = await window.navigator.serviceWorker.getRegistration();
if (!registration) {
return;
}
registration.onupdatefound = async () => {
await registration.update();
setEnabledUpdate(true);
};
};
callback();
}, []);
サンプルのコードも上げていますので、ぜひ参考にしていただければと。