Angular PWAを使用しています。Angular 5.0から7.2にアップグレードするまで、そのサービスワーカーは問題なく動作していました。
アップグレード後、/ngsw/state
に次のerrorが表示されます
Driver state: SAFE_MODE (Initialization failed due to error: Invariant violated (initialize): latest hash null has no known
manifest initialize/<@https://{{domain}}.com/ngsw-worker.js:2227:27
fulfilled@https://{{domain}}.com/ngsw-worker.js:1772:52 ) Latest
manifest hash: none Last update check: never
アプリの背景
更新を確認するコード
if (this.updates.isEnabled) {
const appIsStable$ = this.appRef.isStable.pipe(first(isStable => isStable === true));
const every21600Ms$ = interval(6 * 60 * 60);
const every21600MsOnceAppIsStable$ = concat(appIsStable$, every21600Ms$);
// poll the service worker to check for updates
every21600MsOnceAppIsStable$.subscribe(() =>
this.updates.checkForUpdate()
);
}
これまでの私の調査とトラブルシューティングの手順:
Chromeの場合
Microsoft Edgeで
私の考えと期待
これはAngularバージョン8.2.14で修正されます。以下の回避策は、古いバージョンでのみ必要です。
これはAngularサービスワーカーのよく知られたバグであり、ある時点でパッチ/作業バージョンを期待しているようです。ほとんどの情報は issue 25611 にあります shobhit vaish はすでに述べたとおりです。
ただし、今すぐに解決策を探している場合、または古いAngular 7/8バージョンを使い続ける予定であり、すぐにパッチが適用されない可能性がある場合は、現在知られている回避策をまとめます。 。 (また、「適切な解決策」と見なされない場合もあります...)
ngsw-worker.js
__ngsw-worker.js
_ファイルは、_ng run app:build:production
_の後にパッチを適用できます。このファイルは通常、プロジェクト内のwww
フォルダーにあります(Angular outputPath
を変更していない場合)。または、_node_modules/@angular/service-worker
_内でビルドする前にパッチを適用できます。
アプリをビルドする頻度に応じて、手動で(つまり、選択したテキストエディターを使用して)、または sed を使用してスクリプトを記述できます。
現在、2つのオプションがあります。
handleMessage()
検索する
_ handleMessage(msg, from) {
return __awaiter$5(this, void 0, void 0, function* () {
_
そしてそれを
_ handleMessage(msg, from) {
return __awaiter$5(this, void 0, void 0, function* () {
if (this.initialized === null) {
this.initialized = this.initialize();
}
try {
yield this.initialized;
}
catch (e) {
this.state = DriverReadyState.SAFE_MODE;
this.stateMessage = `Initialization failed due to handleMessage() error: ${errorToString(e)}`;
}
_
_@angular/service-worker
_バージョンによっては、handleMessage()
のシグネチャが異なって見える場合があり、より洗練されたcatch
を記述できますが、おそらくcatch
ブロックに到達しない可能性があります。
このパッチは基本的に gkalpakによるコメント で提案されているものであり、おそらく公式修正もこのようなものになります。
initialize()
検索する
_ try {
// Read them from the DB simultaneously.
[manifests, assignments, latest] = yield Promise.all([
table.read('manifests'),
table.read('assignments'),
table.read('latest'),
]);
_
そしてそれを
_ try {
// Read them from the DB simultaneously.
[manifests, assignments, latest] = yield Promise.all([
table.read('manifests'),
table.read('assignments'),
table.read('latest'),
]);
if (latest.latest === null) throw new Error('Error latest.latest is null for what ever reason...');
_
これにより、initialize()
のcatch
ブロックが実際に実行され、Service Workerが_SAFE_MODE
_に入るのを防ぐことができます。ただし、これは最初のパッチほど信頼性が高くない可能性がありますが、この問題のためにすでに_SAFE_MODE
_にあるService Workerでも機能する可能性があります。 hstaによるコメント で提案されました。
_ngsw-worker.js
_をいじりたくない場合は、Angularアプリ内から_your-app.domain/ngsw/state
_をフェッチして、サービスワーカーの状態を検出してみてください。 _SAFE_MODE
_(たとえば、単純なregex
検索で確認できます)キャッシュストレージからすべてのアイテムを削除し、Service Workerの登録を解除することで、リセットすることができます。これに対するアイデアは mattlewis92によるコメント で提案され、おそらく gkalpakによるコメント でハッキングの作業として承認されました。
shobhit vaish はすでに判明しているため、手動で問題を解決することもできます。元の投稿ですでに述べられている可能性の横にあるchromeベースのブラウザーの開発ツールでもこれを行うことができます。[アプリケーション]-> [ストレージのクリア]で、[サービスワーカーの登録解除]を選択してヒットします。 「クリアサイトデータ」。明らかに問題は将来のアップデートで再発する可能性があり、おそらく再発するでしょう。通常のユーザーにとってはあまり役に立ちません。ただし、開発者が現時点で迅速に解決したい場合は便利です。