Google での PWA の作成、パート 1

公開情報チームが PWA の開発中に Service Worker について学んだこと。

Douglas Parker
Douglas Parker
Joel Riley
Joel Riley
Dikla Cohen
Dikla Cohen

これは、Google 速報チームが学んだ教訓を取り上げたブログ投稿シリーズの第 1 回目です 外部向けの PWA を構築できますこれらの投稿では、私たちが直面した課題の一部をご紹介します。 それらに対処するために採用したアプローチや、問題を回避するための一般的なアドバイスが記載されています。これはまったくの PWA の概要を説明しますチームの経験から学んだことを共有することが目的です。

この最初の投稿では、最初に簡単な背景情報をご説明してから、 Service Worker について学びました。

背景

『Bullet』は、2017 年半ばから 2019 年半ばにかけて活発に開発されました。

PWA の構築を選んだ理由

開発プロセスを詳しく見ていく前に、なぜ PWA の構築が魅力的だったのかを確認しましょう オプション:

  • 反復処理を迅速に行えること。公開情報は試験的に試験運用されるため、特に有益 複数の市場に展開しています
  • 単一のコードベース。ユーザーは Android と iOS でほぼ均等に分散していました。PWA とは 両方のプラットフォームで動作する ウェブアプリを構築できましたこれにより 影響するかを検討します
  • ユーザーの行動に関係なくすぐに更新されます。PWA は自動的に更新され、 古くなったクライアントの量を減らすことができます。バックエンドシステムへの 分散の問題を わずかな時間で変更を行う必要がありません。
  • ファーストパーティ製アプリやサードパーティ製アプリと簡単に統合できます。このような統合には あります。PWA では多くの場合、単に URL を開く必要がありました。
  • アプリをインストールする際の煩わしさを解消しました。

Google のフレームワーク

公開情報には Polymer を使用しましたが、十分にサポートされている最新の フレームワークが機能します。

Service Worker について学んだこと

サービスがないと PWA を構築できません worker になります。Service Worker 高度なキャッシュ戦略、オフライン機能、バックグラウンド同期、 Service Worker によって複雑さが増す一方で、そのメリットの方が 複雑になります。

可能であれば生成する

Service Worker のスクリプトを手動で記述することは避けます。Service Worker を手動で作成するには、 キャッシュに保存されたリソースの管理と、ほとんどの Service Worker ライブラリに共通するロジックの書き換え Workbox として指定します。

とはいえ、社内の技術スタックが原因で、ライブラリを使用して生成、管理することは 使用します。以下で学ぶ内容は、時折その内容を反映したものになるでしょう。注意点: 未生成の Service Worker も参照してください。

すべてのライブラリが Service Worker 互換とは限らない

一部の JS ライブラリでは、想定どおりに動作しないことがあります。対象 window または document が使用できる場合、またはサービスで利用できない API を使用していると仮定します。 ワーカー(XMLHttpRequest、ローカル ストレージなど)アプリケーションに必要な重要なライブラリが Service Worker との互換性もあります。今回の PWA では、 認証には gapi.js を使用しますが、 Service Worker に対応していないため、できません。図書館の著者は、 JavaScript コンテキストについて不要な前提条件を可能な限り持たずに、Service Worker の使用をサポート Service Worker と互換性のない API やグローバルなインフラストラクチャの 確認します

初期化中の IndexedDB へのアクセスを回避する

次の場合は IndexedDB を読み取らない Service Worker スクリプトを初期化しないと、この望ましくない状況が発生する可能性があります。

  1. ユーザーが IndexedDB(IDB)バージョン N のウェブアプリを使用している
  2. 新しいウェブアプリが IDB バージョン N+1 で push される
  3. ユーザーが PWA にアクセスすると、新しい Service Worker のダウンロードがトリガーされる
  4. 新しい Service Worker が install イベント ハンドラを登録する前に IDB から読み取り、 IDB のアップグレード サイクルを N から N+1 へ
  5. ユーザーがバージョン N の古いクライアントを使用しているため、Service Worker のアップグレード プロセスがアクティブとしてハングする 古いバージョンのデータベースへの接続が引き続き開かれる
  6. Service Worker がハングし、インストールされない

この例では、キャッシュが Service Worker のインストール時に無効化されました。 更新したアプリがユーザーに届かないという問題です。

復元性を高める

Service Worker スクリプトはバックグラウンドで実行されますが、いつでも終了できます。 I/O オペレーション(ネットワーク、IDB など)の最中にも発生します。長時間実行プロセスは 再開できるようにします。

大きなファイルをサーバーにアップロードして IDB に保存する同期プロセスの場合、 内部アップロード ライブラリの再開可能なスナップショットを利用して、 アップロード前に再開可能なアップロード URL を IDB に保存し、その URL を使用して 失敗した場合はアップロードしますまた、長時間実行 I/O オペレーションの前に、 状態は IDB に保存され、プロセス内の各レコードの位置を示します。

グローバルの状態に依存しない

Service Worker は異なるコンテキストに存在するため、想定されるシンボルの多くには、 できます。コードの多くは、window コンテキストと Service Worker コンテキスト( (ロギング、フラグ、同期など)です。コードは、使用するサービスに対して防御的である必要があります。たとえば、 ローカルストレージや Cookie などです次を使用: globalThis すべてのコンテキストで機能する方法でグローバル オブジェクトを参照できます。保存されているデータも使用する グローバル変数は控えめに指定してください。スクリプトの終了と停止のタイミングに関する保証がないため、 強制排除されます。

ローカルでの開発

Service Worker の主なコンポーネントは、リソースをローカルにキャッシュ保存することです。ただし 開発中は これは、望ましい動作とはまったく逆で、特に更新が遅延して行われる場合に顕著です。それでも 検出されたため、問題のデバッグや、 通知を設定できますChrome では、Chrome DevTools を使用して次の操作を行います。 [ネットワークのバイパス] チェックボックス([アプリケーション] パネル > [Service Worker] ペイン)を有効にする [ネットワーク] パネルの [キャッシュを無効にする] チェックボックスをオンにすることに加えて、 メモリ キャッシュを無効にします。より多くのブラウザに対応できるようにするために、Google では別のソリューションを選択しました。 Service Worker でキャッシュを無効にするフラグが含まれます。これは、デベロッパー レベルではデフォルトで有効になっています。 説明します。これにより、デベロッパーはキャッシュの問題を生じさせることなく、常に最新の変更を取得できます。です。 Cache-Control: no-cache ヘッダーを含めることと、ブラウザが アセットのキャッシュ保存

灯台

Lighthouse では、さまざまなデバッグ機能を利用できます。 便利なツールを紹介しますサイトをスキャンして、PWA、パフォーマンス、 アクセシビリティ、SEO、その他のベスト プラクティスについて学びます。 Lighthouse の実行は、 インテグレーションが組み込まれており、 要件があります実際に起こったのは一度だけですが Service Worker は 本番環境への移行前には気づきませんでしたLighthouse を CI の一部として活用すると、 防ぎました。

継続的デリバリーの採用

Service Worker は自動更新されるため、ユーザーがアップグレードを制限することはできません。この 古くなったクライアントの数を大幅に削減できます。ユーザーがアプリを開くと Service Worker は古いクライアントにサービスを提供し、新しいクライアントのダウンロードは遅れていました。完了後 新しいクライアントがダウンロードされると、新機能にアクセスするためにページを更新するようユーザーに求められます。たとえ ユーザーがこのリクエストを無視した場合、次回ページを更新したときに新しい クライアントのバージョンを指定します。そのため、ユーザーが 1 回での更新を拒否することは非常に困難です。 iOS/Android アプリの やり方で対応できます

わずかな移行時間で、バックエンドの破壊的変更を push することができました。 できます。通常は、新しいクライアントにアップデートするまで 1 か月ほどかかります。 見ていきましょう。アプリが古い状態で配信されることから、古いクライアントでも実際には可能でした。 ユーザーがアプリを長期間開いていなかった場合、そのアプリを長時間放置します。iOS では、Service Worker は 数週間後に強制排除 このようなケースは起こりません。Android の場合、この問題は、サービス中に広告を配信しないことで軽減できます。 数週間後に手動で期限切れにするよう設定できます実際のところ、 問題を検出します。特定のチームがどの程度厳格にするかは、特定の用途によって異なります。 PWA は iOS/Android アプリよりもはるかに柔軟性があります。

Service Worker での Cookie 値の取得

Service Worker のコンテキストで Cookie 値にアクセスする必要がある場合があります。今回は、 Cookie の値にアクセスして、ファースト パーティの API リクエストを認証するためのトークンを生成する必要があります。新しい Service Worker で、document.cookies などの同期 API は使用できません。いつでもメッセージを送信して、 というメッセージを Service Worker からアクティブな(ウィンドウ処理された)クライアントに送り、 ウィンドウ処理されたクライアントがなくても、Service Worker をバックグラウンドで実行できます。 バックグラウンド同期中などに無効にできますこれを回避するために、 クライアントに Cookie 値を単純にエコーバックするフロントエンド サーバーのことです。Service Worker は、 ネットワーク リクエストをこのエンドポイントに送信し、レスポンスを読み取って Cookie 値を取得します。

Cookie Store API この回避策をサポートするブラウザでは、この回避策が不要になりました。 ブラウザの Cookie に非同期でアクセスでき、Service Worker で直接使用できます。

生成されていない Service Worker の注意点

キャッシュに保存された静的ファイルが変更された場合に Service Worker スクリプトが変更されることを確認する

一般的な PWA パターンは、Service Worker で API 呼び出し中にすべての静的アプリケーション ファイルをインストールすることです。 install フェーズ。クライアントは、すべてのストレージ クラスに対して Cache Storage API のキャッシュを直接ヒットできます。 再訪問。Service Worker はブラウザでサービスが検出された ワーカー スクリプトがなんらかの形で変更されているため、Service Worker スクリプト ファイル自体を キャッシュされたファイルが変更されたときに、なんらかの変更が加えられたためです。そこで、鍵のハッシュを埋め込み、 静的リソース ファイルセットを使用しており、リリースごとに個別の Service Worker の JavaScript ファイルが生成されます。Service Worker ライブラリなど、 Workbox では、このプロセスを自動化できます。

単体テスト

Service Worker API は、グローバル オブジェクトにイベント リスナーを追加することで機能します。例:

self.addEventListener('fetch', (evt) => evt.respondWith(fetch('/foo')));

イベント トリガー、イベント オブジェクトをモックする必要があるため、テストが面倒になる場合があります。 respondWith() コールバックを呼び出して Promise を待機してから、最終的に結果をアサートします。「 これを構成する簡単な方法は、すべての実装を別のファイルに委任することです。 検証できます。

import fetchHandler from './fetch_handler.js';
self.addEventListener('fetch', (evt) => evt.respondWith(fetchHandler(evt)));

Service Worker スクリプトの単体テストは難しかったため、コア Service Worker はそのまま 必要最小限のスクリプトで記述し、実装の大部分を他のモジュールに分割します。以降 これらのファイルは標準の JS モジュールにすぎず、標準テストで 使用できます。

第 2 部、第 3 部もご期待ください

このシリーズのパート 2 と 3 では、メディア管理と iOS 固有の問題について説明します。もし Google における PWA の構築についてご不明な点がある場合は、作成者プロフィールにアクセスしてご確認ください 当社への連絡方法: