PWA とサービスワーカー
Web サイトをアプリのように使える PWA と、その心臓部である Service Worker の仕組みです。オフライン対応やプッシュ通知、プロキシとして働く役割を整理します。
- 1.PWA は Web の技術で作りながら、インストール・オフライン・プッシュ通知などネイティブアプリ的な体験を提供する仕組み。
- 2.中核は Service Worker。ページとネットワークの間に常駐し、通信を横取りしてキャッシュから返せる“プロキシ”として働く。
- 3.オフライン対応や高速化が得意な一方、HTTPS 必須・更新の罠など運用上の注意点もある。
PWA とは
**PWA(Progressive Web Apps)**は、HTML・CSS・JavaScript という普通の Web 技術で作りながら、ネイティブアプリのような体験を提供するアプローチです。アプリストアを通さず、ブラウザからそのまま使えます。
主にできることは次のとおりです。
- ホーム画面に追加:アイコンを置き、アドレスバーのないアプリのように起動できる(インストール可能)。
- オフライン動作:電波が無くても、キャッシュした内容で最低限の表示ができる。
- プッシュ通知:アプリを開いていなくても通知を送れる。
「Web の手軽さ(URL で配れる・更新が即時)」と「アプリの快適さ(起動が速い・オフラインで動く)」のいいとこ取りを狙ったのが PWA です。
そして PWA は単一の技術ではなく、いくつかの仕組みの組み合わせで成り立ちます。
| 部品 | 役割 |
|---|---|
| Web App Manifest | アプリ名・アイコン・起動時の見た目を定義する JSON。これでインストール可能になる |
| Service Worker | 通信を横取りしてキャッシュから返す。オフラインとプッシュの中核 |
| HTTPS | 通信を横取りできる強力な仕組みゆえ、安全な接続が必須 |
このうち体験を決定づけるのが Service Worker です。マニフェストは「アプリらしい見た目」を、Service Worker は「アプリらしい挙動」を担当します。
Service Worker=プロキシとして働く
Service Worker は、ページとは別にバックグラウンドで動く JavaScript です。最大の特徴は、ページとネットワークの間に割り込んで、すべての通信を横取り(インターセプト)できること。いわばブラウザ内に置く自前のプロキシです。
通常: ページ → ネットワーク → サーバ
SW あり: ページ → Service Worker → (キャッシュ or ネットワーク)→ サーバ
↑ここで横取りして応答を差し替えられる
ページが画像や API を要求すると、その要求は一度 Service Worker を経由します。Service Worker は「キャッシュにあればそれを返す」「無ければネットワークへ取りに行く」といった判断を自分で下せます。これがオフライン対応の正体です。
// fetch イベントで通信を横取りし、キャッシュ優先で応答する例
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((cached) => {
// キャッシュにあれば即返す。無ければネットワークへ
return cached || fetch(event.request);
})
);
});
Service Worker はページとは独立したスレッドで動くため、document や window に直接アクセスできません。これは制約ではなく安全のため。ページとは postMessage でやり取りします。「通信とキャッシュの管理に専念する裏方」と捉えると役割が掴めます。
ライフサイクルとキャッシュ戦略
Service Worker は登録 → インストール → 有効化という段階を経て常駐します。インストール時にあらかじめ必要なファイルをキャッシュしておく(プリキャッシュ)のが定番です。
// ページ側:Service Worker を登録する
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sw.js");
}
// sw.js 側:インストール時に主要ファイルを先読みキャッシュ
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open("v1").then((cache) =>
cache.addAll(["/", "/style.css", "/app.js", "/offline.html"])
)
);
});
どう応答するかには、いくつかの戦略があります。用途で使い分けます。
| 戦略 | 動き | 向くもの |
|---|---|---|
| キャッシュ優先 | まずキャッシュ、無ければ通信 | ロゴ・CSS など変わらない静的ファイル |
| ネットワーク優先 | まず通信、失敗したらキャッシュ | 最新性が大事な記事・API |
| 再検証つき | キャッシュを返しつつ裏で更新 | 表示は速く、次回は新しくしたい場合 |
オフラインとプッシュ通知
Service Worker が常駐することで、ページを閉じていても動ける機能が使えます。
- オフライン表示:通信が失敗したとき、キャッシュ済みのページや専用の
offline.htmlを返す。完全な機能は無理でも「圏外でも真っ白にならない」を実現できる。 - プッシュ通知:サーバからの通知を Service Worker が受け取り、
showNotificationで表示する。アプリを開いていなくても届く。 - バックグラウンド同期:オフライン中の操作を貯めておき、オンライン復帰時にまとめて送信する。
これらは「常にバックグラウンドで生きているプロキシ」があって初めて成立します。
注意点
強力な仕組みゆえ、運用には落とし穴があります。
- HTTPS が必須:通信を横取りできる能力は悪用されると危険なため、Service Worker は HTTPS(および開発用の
localhost)でしか動きません。 - キャッシュの取り扱い:戦略を誤ると、サーバを更新したのに古いファイルが表示され続ける事故になります。キャッシュ名にバージョンを付け、古い世代を確実に消す設計が要ります。
- 過信しない:オフライン対応はあくまで補助。すべての機能がネットなしで動くわけではありません。
新しい Service Worker は、既存のタブが全て閉じられるまで有効化されないのが既定の挙動です。そのため「デプロイしたのにユーザーには古いまま」が起きがち。skipWaiting で即時切り替えを行う、キャッシュ名のバージョンを上げて古いキャッシュを削除する、といった更新フローを最初から設計に入れておきましょう。
まとめ
- PWA:Web 技術で作りつつ、インストール・オフライン・プッシュなどアプリ的体験を提供する。
- Service Worker:ページとネットワークの間に常駐し、通信を横取りしてキャッシュから返せるプロキシ。PWA の心臓部。
- 三点セット:マニフェスト(見た目)+ Service Worker(挙動)+ HTTPS(前提)。
- 注意:HTTPS 必須、キャッシュ戦略と更新フローの設計が成否を分ける。
キャッシュの考え方は HTTP キャッシュ、クライアント側の保存は Web ストレージ と地続きです。表示速度の観点では Web パフォーマンス も合わせてどうぞ。
Web/フロントエンド Article
PWA とサービスワーカーを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
PWA
比較で見る軸
難易度: intermediate / カテゴリ: Web/フロントエンド / タグ数: 3
導入後に効く点
中核は Service Worker。ページとネットワークの間に常駐し、通信を横取りしてキャッシュから返せる“プロキシ”として働く。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- intermediate
- カテゴリ
- Web/フロントエンド
- タグ数
- 3
判断チェックリスト
- 自社の用途が「PWA / Service Worker」に近いか確認する。
- 強みである「PWA は Web の技術で作りながら、インストール・オフライン・プッシュ通知などネイティブアプリ的な体験を提供する仕組み。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。