ZDF がオフライン サポート、インストール、ダークモードなどの最新機能を備えたプログレッシブ ウェブアプリ(PWA)をどのように作成したかをご確認ください。
放送局の ZDF は、フロントエンドの技術スタックの再設計を検討していた際、ストリーミング サイト ZDFmediathek のプログレッシブ ウェブアプリについて詳しく検討することにしました。開発機関の Cellular は、ZDF のプラットフォーム固有の iOS および Android アプリと同等のウェブベースのエクスペリエンスを構築することに挑戦しました。この PWA には、インストール、オフラインでの動画再生、遷移アニメーション、ダークモードが用意されています。
Service Worker の追加
PWA の重要な機能はオフライン サポートです。ZDF では、面倒な作業のほとんどは Workbox によって行われます。Workbox は、さまざまなキャッシュ戦略を容易にサポートできるライブラリとノード モジュールのセットです。ZDF PWA は TypeScript と React で構築されているため、create-react-app に組み込まれている Workbox ライブラリを使用して静的アセットを事前キャッシュに保存します。これにより、アプリは動的コンテンツ(この場合は動画とそのメタデータ)をオフラインで利用できるようにすることに集中できます。
基本的な考え方は非常にシンプルです。動画をフェッチして blob として IndexedDB に保存します。その後、再生中にオンライン/オフライン イベントをリッスンし、デバイスがオフラインになったら、ダウンロード済みのバージョンに切り替えます。
ところが、事態は少し複雑になりました。プロジェクト要件の 1 つは、オフライン サポートを提供しない公式 ZDF ウェブ プレーヤーを使用することでした。プレーヤーはコンテンツ ID を入力として受け取り、ZDF API と通信して、関連する動画を再生します。
このような場合に役立つのがウェブの最も強力な機能の一つである Service Worker です。
Service Worker は、プレーヤーから送信されたさまざまなリクエストをインターセプトし、IndexedDB からのデータで応答できます。これにより、プレーヤーのコードを 1 行も変更することなく、オフライン機能を透過的に追加できます。
オフライン動画は非常に大きくなる傾向があるため、実際にデバイスに保存できる動画の数が非常に多いことが大きな問題となります。StorageManager API を使用することで、アプリは利用可能な容量を推定し、空き容量が不足している場合はダウンロードを開始する前にユーザーに通知できます。残念ながら、Safari はこの API を実装しているブラウザのリストにありません。また、執筆時点では、他のブラウザでのクォータの適用状況についての最新情報はあまりありませんでした。そのため、さまざまなデバイスでの動作をテストするための小さなユーティリティを作成しました。現時点で、すべての詳細を要約した記事が提供されています。
カスタム インストール プロンプトの追加
ZDF PWA ではカスタムのアプリ内インストール フローが提供され、最初の動画をダウンロードしたらすぐにアプリをインストールするようユーザーに促します。ユーザーはアプリをオフラインで使用する意思を明確に示しているため、この時点でインストールを求めるのに適しています。
ダウンロードにアクセスするためのオフライン ページを作成する
デバイスがインターネットに接続されておらず、オフライン モードで使用できないページにユーザーが移動すると、過去に一時保存されたすべての動画、または(まだコンテンツがダウンロードされていない場合は)オフライン機能の簡単な説明が記載された特別なページが表示されます。
アダプティブ機能にフレーム読み込み率を使用する
リッチなユーザー エクスペリエンスを提供するため、ZDF PWA には、ユーザーがスクロールまたは移動したときに発生する微妙な遷移が含まれています。ローエンド デバイスでは、このようなアニメーションは通常逆の効果となり、60 フレーム/秒で動作しないとアプリの動作が遅く、応答性が低下します。これを考慮するため、アプリは読み込み中に requestAnimationFrame()
を介して実際のフレームレートを測定し、値が特定のしきい値を下回るとすべてのアニメーションを無効にします。
const frameRate = new Promise(resolve => {
let lastTick;
const samples = [];
function measure() {
const tick = Date.now();
if (lastTick) samples.push(tick - lastTick);
lastTick = tick;
if (samples.length < 20) requestAnimationFrame(measure);
else {
const avg = samples.reduce((a, b) => a + b) / samples.length;
const fps = 1000 / avg;
resolve(fps);
}
}
measure();
});
この測定値は、デバイスのパフォーマンスを大まかに示し、負荷ごとに変化する場合でも、意思決定を行う良い基準でした。ユースケースによっては、デベロッパーが実装できるアダプティブ ローディングのその他の手法もあります。このアプローチの大きなメリットの 1 つは、すべてのプラットフォームで利用できることです。
ダークモード
最新のモバイル エクスペリエンスで人気のある機能はダークモードです。特に、暗い場所で動画を視聴する場合、UI が薄い色を好むことがよくあります。ZDF PWA は、ライトモードとダークモードの切り替えを可能にするスイッチを提供するだけでなく、OS 全体の色設定の変更にも反応します。これにより、テーマベースを変更するスケジュールが設定されているデバイスで、アプリの外観が自動的に変更されます。
結果
新しいプログレッシブ ウェブアプリは、2020 年 3 月に公開ベータ版として密かにリリースされ、それ以降、多くの好意的なフィードバックを得ています。ベータ版のフェーズが終わるまで、PWA は引き続き独自の一時ドメインで実行されます。この PWA は一般公開されていなかったものの、ユーザー数は着実に増加しています。その多くは Microsoft Store からのもので、Windows 10 ユーザーは PWA を検出してプラットフォーム固有のアプリと同様にインストールできます。
次のステップ
ZDF は、パーソナライズのためのログイン、クロスデバイスおよびプラットフォームの表示、プッシュ通知などの機能を PWA に引き続き追加する予定です。