プログレッシブ ウェブアプリ: PWA を強化する

1. ようこそ

このラボでは、既存のウェブ アプリケーションに高度な機能を追加します。これは、プログレッシブ ウェブアプリ ワークショップの一連のコンパニオン Codelab の 6 番目です。前の Codelab は、インストールを促して測定するでした。このシリーズには、さらに 2 つの Codelab があります。

学習内容

  • File System Access API を使用してユーザーのファイル システムからファイルを開いて保存する
  • インストールされた PWA を File Handling API でファイル ハンドラとして登録する
  • Multi-Screen Window Placement API を使用してウィンドウを開く適切な画面を選択する
  • Screen Wake Lock API を使用して画面がスリープ状態になるのを防ぐ

必要な予備知識

  • JavaScript

必要なもの

  • 上記の API をサポートするブラウザ。一部の API では、デベロッパー トライアルまたはオリジン トライアルが有効になっているブラウザを使用して完了する必要があります。

2. 準備

まず、この Codelab を完了するために必要なスターター コードをクローンするかダウンロードします。

リポジトリのクローンを作成する場合は、pwa05--empowering-your-pwa ブランチにいることを確認してください。zip ファイルには、そのブランチのコードも含まれています。

このコードベースには Node.js 14 以降が必要です。コードが用意できたら、コードのフォルダのコマンドラインから npm ci を実行して、必要なすべての依存関係をインストールします。次に、npm start を実行して、Codelab の開発用サーバーを起動します。

ソースコードの README.md ファイルには、すべての配布ファイルの説明が記載されています。また、この Codelab 全体を通して使用する主な既存のファイルは次のとおりです。

キーファイル

  • js/lib/actions.js - メニューの基本クラスを提供します

重要なアーキテクチャ上の注意事項

この Codelab では、アプリのメニューにあるさまざまなボタンのアクションを管理する js/lib/action.js を編集します。初期化されたメニューのコンストラクタ内の任意のプロパティにアクセスできます。これには、メイン テキスト エディタのインスタンスの this.editor が含まれます。この Codelab で使用する重要なエディタ メソッドは次の 2 つです。

  • this.editor.setContent(content) - エディタのコンテンツを指定されたコンテンツ引数に設定します
  • this.editor.content() - エディタの現在のコンテンツを取得します

3. ファイルを管理する

File System Access API のおかげで、ユーザーのパソコンでファイルを開いたり、保存したり、新しいファイルを作成したりできるようになりました。File Handling API と組み合わせることで、ユーザーが PWA でファイルを直接開けるようになり、PWA がユーザーの日常生活にシームレスに統合されたように感じられます。

アプリ内から開く

最初にフックするアクションは、アプリ内からユーザーのファイルシステムにあるファイルを開くことができるようにすることです。js/lib/actions.jsActions クラスの open メソッドで、次の処理を行うコードを記述します。

  • 拡張子が .md または .markdowntext/markdown ファイルを受け取るファイル選択ツールを開きます。
  • ページのタイトルを開いているファイルの名前に PWA Edit を追加して設定します
  • ファイル ハンドラを this.handler に保存する
  • エディタのコンテンツをファイル内のテキスト コンテンツに設定します。
  • ハンドラを settings-store IndexedDB データベースの settings オブジェクト ストアに保存します。

ポジティブ: クラス コンストラクタは async 関数にできませんが、その中で Promise を呼び出すことはできます

ファイルを読み込んで、読み込まれたファイルを読み込み間で保存できるようになったので、あと 2 つ行う必要があります。アプリの読み込み時にハンドラを再度設定し、ユーザーがアプリをリセットしたときにハンドラの設定を解除します。

最初の処理を行うには、js/lib/actions.jsActions クラスのコンストラクタで次の操作を行います。

  • settings-store データベースを開く
  • 保存されたハンドラを settings オブジェクト ストアから取得する
  • 保存されたハンドラがある場合は、this.handler を取得した値に設定し、ページのタイトルをハンドラのファイル名(+ PWA Edit)に設定します。

アプリの状態をリセットする(CTRL/CMD + Shift + R で実現可能)には、js/lib/actions.jsActions クラスの reset メソッドを更新して、次の処理を行います。

  • ドキュメントのタイトルを PWA Edit に設定します
  • エディタのコンテンツを空の文字列に設定する
  • this.handlernull に設定する
  • 保存されたハンドラを settings オブジェクト ストアから削除する

ユーザーのファイル システムから開く

アプリからファイルを開けるようになったので、ユーザーがファイルからアプリを開けるようにしましょう。デバイスのファイル ハンドラとして登録すると、ユーザーはファイル システムのどこからでもアプリでファイルを開けるようになります。

ネガティブ : これを機能させるには、デベロッパーまたはオリジン トライアルを有効にする必要がある場合があります。デベロッパー トライアルを有効にする必要がある場合は、通常のブラウザではなく、Chrome Canary のコピーで有効にすることをおすすめします。オリジン トライアルを有効にする必要がある場合は、通常どおり登録し、 タグを index.html に追加する必要があります。

まず、manifest.json で、次の処理を行う file_handlers エントリを追加します。

  • 営業開始: /
  • .md または .markdown のファイル拡張子を持つ text/markdown を指定します。

これにより、ユーザーはアプリでファイルを開くことができますが、実際にアプリでファイルが開かれるわけではありません。アプリでファイルを開くには、js/lib/actions.jsActions クラスで次の操作を行います。

  • コンストラクタに window.launchQueue コンシューマーを追加し、ハンドラがある場合はハンドラを使用して this.open を呼び出します。
  • オプションの起動ハンドラを受け入れるように this.open を更新
    • 存在し、FileSystemFileHandle のインスタンスである場合は、それを関数のファイル ハンドラとして使用します。
    • そうでない場合は、ファイル選択ツールを開きます。

上記の両方を実行したら、PWA をインストールして、ファイル システムからファイルを開いてみてください。

ファイルを保存する

ユーザーが選択できる保存パスは、すでに開いているファイルへの変更の保存と、新しいファイルへの保存の 2 つです。File System Access API を使用して新しいファイルに保存すると、実際に新しいファイルが作成され、ファイル ハンドラが返されます。まず、既存のハンドラから保存してみましょう。

js/lib/actions.jsActions クラスの save メソッドで、次の操作を行います。

  • this.handler からハンドラを取得するか、存在しない場合はデータベースから保存されたハンドラを取得します。
  • ファイル ハンドラの FileSystemWritableFileStream を作成する
  • エディタのコンテンツをストリームに書き込む
  • ストリームを閉じる

ファイルを保存できるようになったら、名前を付けて保存を実装します。これを行うには、js/lib/actions.jsActions クラスの saveAs メソッドで次の操作を行います。

  • 保存ファイル選択ツールを表示し、Markdown File として説明して、.md 拡張子の text/markdown ファイルを受け入れるようにします。
  • this.handler を返されたハンドラに設定する
  • ハンドラを settings オブジェクト ストアに保存する
  • this.save が完了するまで待ってから、新しく作成したファイルにコンテンツを保存します。

完了したら、save メソッドに戻り、handler が存在するかどうかを確認してから書き込みを試み、存在しない場合は this.saveAs の完了を待ちます。

4. プレビューを表示する

Markdown エディタでは、ユーザーはレンダリングされた出力のプレビューを確認したいと考えています。ウィンドウ管理 API を使用して、ユーザーのプライマリ画面にレンダリングされたコンテンツのプレビューを開きます。

始める前に、js/preview.js というファイルを作成し、次のコードを追加して、読み込み時にプレビューを表示するようにします。

import { openDB } from 'idb';
import { marked } from 'marked';

window.addEventListener('DOMContentLoaded', async () => {
  const preview = document.querySelector('.preview');
  const db = await openDB('settings-store');
  const content = (await db.get('settings', 'content')) || '';

  preview.innerHTML = marked(content);
});

プレビューは次のように動作します。

  • ユーザーがプレビュー ボタンをクリックしたときにプレビューが開いていない場合は、プレビューを開く必要があります
  • ユーザーがプレビュー ボタンをクリックしてプレビューが開いている場合、プレビューを閉じる必要があります
  • ユーザーが PWA を閉じるか更新すると、プレビューが閉じる

これらを順番に処理するため、まず js/lib/actions.jsActions クラスの preview メソッドを編集して、次の処理を行います。

  • Window Management API を使用して利用可能な画面を取得する
  • 画面をフィルタしてプライマリ画面を見つける
  • /preview のウィンドウを開きます。タイトルは Markdown preview で、プライマリ画面の利用可能な幅の半分と利用可能な高さ全体を占め、その画面の利用可能な右半分全体を占めるように配置されます。使用可能なディメンションには、システム メニューバー、ツールバー、ステータス、位置情報など、画面の予約済み領域は含まれません。
  • 開いているウィンドウを this.previewWindow に保存する
  • メソッドの先頭で、this.previewWindow が存在するかどうかを確認し、存在する場合は、ウィンドウ プレビューを開く代わりに、ウィンドウを閉じて this.previewWindow を設定解除します。

最後に、js/lib/actions.jsActions クラスのコンストラクタの末尾で、次の操作を行います。

  • beforeunload イベント中に this.previewWindow を閉じる

5. フォーカス

最後に、ユーザーに集中して執筆できるモードを提供したいと考えています。他のアプリの雑多な情報が表示されないだけでなく、ユーザーの画面がスリープ状態にならないようにすることも、集中モードの目的です。これを行うには、Screen Wake Lock API を使用します。

ウェイクロック ボタンはプレビュー ボタンと同じように機能し、オンとオフの状態を切り替えます。これを行うには、js/lib/actions.jsActions クラスの focus メソッドで、次の操作を行います。

  • ドキュメントに全画面表示要素があるかどうかを確認する
  • その場合は、次の手順を行います。
    • 全画面表示を終了
    • this.wakeLock が存在する場合は、ウェイクロックを解放して this.wakeLock をリセットします。
  • オンになっていない場合は、次の手順を行います。
    • ウェイクロック センチネルをリクエストして this.wakeLock に設定します
    • ドキュメントの本文を全画面表示にするようリクエストします。

6. 完了

File System Access API と File Handling API を使用してシステムファイルを管理し、PWA をシステムに統合する方法、Window Management API を使用してさまざまな画面でウィンドウを開く方法、Screen Wake Lock API を使用して画面がスリープ状態になるのを防ぐ方法について説明しました。

このシリーズの次の Codelab は、Service Worker の組み込みです。