セキュリティ事例をきっかけにPWAに入門する

Nov 24, 2024 17:00 · 3269 words · 7 minute read PWA JavaScript Security

先週、PWAを使った攻撃キャンペーンの事例についてブログに書きました。

PWAとNFCを使った攻撃キャンペーンの事例が興味深かった · kapieciiのブログ

PWAの仕様が気になったので、ざっと仕様を学び、簡単なPWAを作ってみました。 自分があとで見返すためにブログに情報を整理します。

目次

PWA(プログレッシブウェブアプリ)とは

プログレッシブウェブアプリ (PWA) | MDN

画像引用元: プログレッシブウェブアプリとは - プログレッシブウェブアプリ (PWA) | MDN

Webアプリでネイティブアプリのような使い勝手を実現する

PWAは、Webアプリの技術を利用してネイティブアプリのような使い勝手を実現する技術です。 基本的にはWebアプリなので、同じコードで複数のプラットフォームで動作します。 オフラインでの動作やバックグラウンド処理もでき、Webアプリとネイティブアプリの中間ような存在です。

インストールできる

通常のWebアプリの場合はアプリはサーバーで動作し、ユーザーはWebブラウザーでサーバーのアプリにアクセスします。 ユーザーの端末にインストールするという考えはありません。 PWAはWebアプリをユーザーの端末にインストールして、バックグラウンドの処理やPush通知を実現します。インストールするので、オフラインでの動作も可能です。

アプリストアを経由せずWebブラウザからインストールできるので、ネイティブアプリのインストールよりもユーザーの利用ハードルは低いです。 また、PWAは基本はWebアプリなので、検索エンジンからの流入も期待できる点がネイティブアプリと比較した強味です。

PWAの構成要素

Manifest File

Manifest Fileにアプリ名やアイコンなどの情報を記載します。

Service Worker

Service Workerを使うことで、オフライン操作やバックグラウンドでの処理、Push通知を実現します。 例えばサーバーからPush通知を送信した場合、ブラウザエンジンがService Workerを開始します。

PWAの特徴

インストールできる

スマホやPCにインストールすることで、オフライン時の動作やバックグラウンド処理、Push通知を実現します。 特にスマホの場合はネットワークが不安定である可能性が高いです。 ネットワークが断続的な状態でもユーザーの操作をオフラインで継続したり、ネットワーク復帰後にユーザーの操作を実行するといった実装が可能です。 また、ローカルにデータをキャッシュするため、通信速度が遅い環境でも安定して機能を提供できます。

ブラウザからインストールした場合、インストール以降の動作もインストールしたブラウザで実行されます。例えば端末にChromeとEdgeがインストールされている環境でChromeからPWAをインストールした場合、インストール後のPWAはChromeで実行されます。 また、ChromeとEdgeのそれぞれからPWAをインストールした場合、2つの異なるインスタンスとして実行されます。この時データの共有や連携はできません。

オフライン操作とバックグラウンド処理

通常のWebアプリは単一スレッドなので、何かの処理をしていると画面の操作はロックされます。 PWAの場合、Service WorkerはMainのJavaScriptスレッドとは別のスレッドで実行されるため、画面の操作をロックせずにバックグラウンドで処理を実行できます。 WorkerとMainスレッドは直接お互いの状態にはアクセスできませんが、メッセージを送りあうことで通信は可能です。

Service Workerを使ってHTML, CSS, JavaScriptをローカルのキャッシュに追加してコントロールできます。そのため、「オフラインの場合はキャッシュのデータを使う」「鮮度が大切な情報はサーバーから取得する」といった情報のコントロールができます。

オフラインやネットワークが断続的な環境の場合でも、キャッシュとバックグラウンド処理を使って快適なユーザー体験を提供できます。 例えば「オフラインでユーザーがメッセージを入力したあと、ネットワークに再度接続した場合にメッセージを送信する」といった実装が可能です。

ただし、バックグラウンド処理は常に実行しているわけではありません。 ユーザーのIPアドレスや位置情報が常にサーバーに開示され続けるというプライバシーの問題や、端末のバッテリー消費の問題があるため、一定時間停止しているService Workerのプロセスは自動的に停止されます。 Push通知などService Workerに必要なイベントが発生した場合、再びブラウザエンジンからService Workerが開始されます。

SPAと相性が良い

PWAはネイティブアプリのようなUIを提供できるため、ネイティブアプリのようなスムーズかつリッチな操作体験を期待されます。 通常のWebアプリでは、リンクをクリックして別ページに遷移し、新たなHTMLをレンダリングします。 PWAの場合はネイティブアプリに近い操作体験を期待されるため、SPAで実装される例が多いらしいです。

ネイティブアプリとしてアプリストアに公開も可能

PWAをビルドしてGoogle PlayやApp Storeで公開できるツールがあります。 iOSは試験的に提供されている状態らしいですが、試験的とはいえ1つのコードから複数の環境向けにアプリをビルドできるのは便利ですね。

PWAのベストプラクティス

PWAは様々なブラウザや環境で実行される可能性があります。 PCのブラウザからアクセスされる場合もあれば、スマホのブラウザからアクセスされるかもしれません。ネットワークが悪い環境での利用も想定しなければなりません。ブラウザによってサポートしている機能も違います。 そのような様々な環境に向けてPWAを提供するときのベストプラクティスが公開されています。

PWAのサンプルコードを作ってみた

改善の余地はたくさんありますが、簡単なPWAのサンプルを作って動かしてみました。 (作ったと言っても、ChatGPTとCopilotの力をたくさん借りていますが)

シンプルなTodoアプリ

HTML, CSS, JavaScriptを使ったシンプルなTodoアプリです。 Flaskで静的コンテンツとして配信します。

Reactを使ったサンプル

PWAはSPAと相性がいいということなので、Reactのサンプルも作ってみました。 筋トレの記録と可視化をするアプリです。

最後に

アプリストアへの公開が不要で、バックグラウンド処理やオフラインの機能も使えるので、ちょっとした機能を公開したい場合にPWAは便利そうですね。 使われる環境が様々なので、エラー処理や代替処理の作りこみは必要ですが。

PWAなら「データはローカルだけに保存する」という割り切った選択もしやすい気がするので、 「ReactやらNext.jsで作ったアプリをGitHub PagesやVercelで公開する」というのも面白いかもしれません。

tweet Share