「pwa 作り方」と検索しているあなたは、きっとWebサイトをもっと便利に、もっとユーザーにとって使いやすく進化させたいとお考えなのではないでしょうか。
「アプリのように動くWebサイトを作ってみたいけれど、難しそう…」「iOSやAndroid向けにアプリを作るにはコストがかかりすぎる…」そんなお悩みをお持ちの方も多いはずです。
そこで注目されているのが「PWA(プログレッシブウェブアプリ)」です。PWAを導入すれば、あなたのWebサイトはホーム画面から起動できるアプリのような存在になり、オフラインでも閲覧できるようになります。しかも、通常のWeb技術(HTML、CSS、JavaScript)をベースに構築できるため、比較的手軽に導入できるのも大きな魅力です。
この記事では、PWAの基本的な仕組みから、実際にPWA化するための具体的な手順まで、初心者の方でも理解できるようにやさしく丁寧に解説しています。

PWAとは?特徴と仕組みを簡単に解説
PWA(プログレッシブウェブアプリ)とは何か
PWA、Progressive Web Apps(プログレッシブウェブアプリ)とは、その名の通り「プログレッシブ(段階的)」に「ウェブ(Web)」サイトを「アプリ(App)」のように進化させる技術の総称です。単なるWebサイトでありながら、あたかもスマートフォンやPCにインストールされたネイティブアプリのように振る舞うことができるのが最大の特徴です。この「プログレッシブ」という言葉は、「プログレッシブエンハンスメント」という考え方に基づいています。これは、まず基本的な機能を提供し、利用環境(ブラウザやデバイスの機能)に応じて段階的に高度な機能を追加していくという開発手法です。つまり、PWAはどんな環境でも動くWebサイトとしての基盤を持ちつつ、対応するブラウザやOSであれば、さらにアプリのような体験を提供できるということです。
PWAは、特定のOSに依存しないため、iOSでもAndroidでもWindowsでも動作します。一度開発すれば、異なるプラットフォームに対応するネイティブアプリをそれぞれ開発する必要がなく、開発コストと時間を大幅に削減できる可能性があります。ユーザーはアプリストアからダウンロードする手間なく、Webブラウザからアクセスするだけで、Webサイトをホーム画面に追加し、素早くアクセスできるようになります。
PWAの主な特徴とできること
PWAが「アプリのように」振る舞うことを可能にする、具体的な特徴とできることは以下の通りです。
オフライン対応・高速性:
PWAはService Workerという技術を用いることで、一度アクセスしたコンテンツをキャッシュし、オフライン環境でも閲覧可能にしたり、再訪問時の読み込み速度を劇的に向上させたりすることができます。ネットワーク接続が不安定な場所でもコンテンツにアクセスできるため、ユーザー体験が向上します。
インストール可能(ホーム画面追加):
ユーザーはWebサイトをスマートフォンのホーム画面やPCのデスクトップにアイコンとして追加できます。これにより、まるでネイティブアプリのようにワンタップでPWAにアクセスできるようになり、ユーザーの再訪率を高める効果が期待できます。
プッシュ通知:
ユーザーの許可を得ることで、PWAから直接プッシュ通知を送信できます。新着情報やセール情報、重要なアップデートなどをリアルタイムでユーザーに通知できるため、ユーザーエンゲージメントの向上に大きく貢献します。これは、ニュースサイトやECサイトなどで特に有効な機能です。
レスポンシブデザイン:
PWAは、スマートフォン、タブレット、デスクトップなど、あらゆるデバイスの画面サイズや向きに合わせて最適に表示されるように設計されています。これにより、どんなデバイスからアクセスしても快適なユーザー体験を提供できます。
安全な通信(HTTPS必須):
PWAは、すべての通信がHTTPS(Hypertext Transfer Protocol Secure)で保護されている必要があります。これにより、データの盗聴や改ざんを防ぎ、ユーザーに安全なWeb体験を提供します。これは、Service WorkerがHTTPS環境下でしか動作しないため、PWAの必須要件となっています。
バックグラウンド同期:
ネットワークが利用可能になった際に、バックグラウンドでデータの同期を行うことができます。これにより、オフライン中にユーザーが入力したデータなどを、ネットワーク接続が回復した時点で自動的にサーバーと同期させることが可能になります。
デバイスのハードウェア連携(一部):
カメラやGPSなどのデバイスの機能にアクセスすることも可能です。ただし、ネイティブアプリほど自由度が高いわけではなく、ブラウザのセキュリティモデルに準拠します。
これらの特徴により、PWAはWebサイトの利便性を高め、ユーザーエンゲージメントを向上させる強力なツールとなります。
従来のWebアプリとの違いとは
従来のWebアプリとPWA、そしてネイティブアプリの違いを理解することで、PWAの立ち位置と優位性が明確になります。
特徴 | ネイティブアプリ | PWA | 従来のWebアプリ(レスポンシブ対応) |
---|---|---|---|
開発コスト | 高い(OSごとに開発が必要) | 低い(Web技術で共通開発) | 低い(Web技術で共通開発) |
配布方法 | アプリストアからのダウンロード | ブラウザ経由、ホーム画面追加(インストール不要) | ブラウザ経由アクセス |
オフライン | 可能 | 可能(Service Workerによるキャッシュ) | 基本的に不可能 |
プッシュ通知 | 可能 | 可能 | 不可能 |
高速性 | 高速 | 高速(キャッシュにより初回以降) | ネットワーク環境に依存 |
セキュリティ | アプリストア審査、OSによる権限管理 | HTTPS必須、ブラウザのセキュリティモデルに準拠 | HTTPSが望ましいが必須ではない |
デバイス連携 | 高度なハードウェア連携が可能 | 一部のハードウェア連携が可能 | ほとんど不可能 |
更新頻度 | アプリストア経由での承認、ユーザーの更新が必要 | Webサイト更新と同時に反映 | Webサイト更新と同時に反映 |
ストレージ | デバイスストレージを使用 | ブラウザのキャッシュストレージを使用 | ブラウザのキャッシュストレージを限定的に使用 |
この表からもわかるように、PWAはネイティブアプリと従来のWebアプリの良い部分を兼ね備えています。ネイティブアプリのような高いユーザー体験を提供しつつ、Webサイトならではの開発コストの低さや更新の手軽さを享受できます。特に、アプリストアの審査が不要で、ユーザーがダウンロードする手間が少ない点は、アプリの利用ハードルを下げる上で非常に大きなメリットとなります。一方で、ネイティブアプリのようにデバイスの全ての機能に自由にアクセスできるわけではない点や、まだ全てのブラウザで完全に同等の機能が提供されているわけではない点には注意が必要です。

PWAの作り方・基本構成と必要ファイル
「pwa 作り方」の具体的なステップに入る前に、PWAを構成する上で不可欠な要素と、それぞれの役割を理解しておくことが重要です。PWAは、従来のWebサイトにいくつかの特定のファイルと設定を追加することで実現されます。

PWAに必要なファイルと役割(manifest・service worker)
PWAを構築するために最低限必要となる主要なファイルは、「Web App Manifest」と「Service Worker」の2つです。これらが連携することで、PWAならではの機能を実現します。
これら2つのファイルがPWAの「骨格」となり、Webサイトをアプリへと変貌させるための重要な役割を担っています。


HTML・JavaScriptを使った基本構造の作成
PWAはあくまでWebサイトの延長線上にあるため、基本的なWeb技術であるHTML、CSS、JavaScriptで構築されます。PWA化に必要な最低限の構成は以下のようになります。
HTMLファイルの準備:
Webサイトの基本的な構造を定義するHTMLファイルが必要です。このHTMLファイルから、先述のManifestファイルとService Workerファイルを読み込むための記述を追加します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>私のPWAサイト</title>
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="私のPWA">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon.png" sizes="180x180">
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>ようこそ、PWAの世界へ!</h1>
<p>これはPWAのデモサイトです。</p>
<button id="installButton" style="display: none;">アプリとしてインストール</button>
<script src="app.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.log('Service Worker registration failed:', error);
});
});
}
</script>
</body>
</html>
<link rel="manifest" href="/manifest.json">
: この行でmanifest.json
ファイルをWebサイトに紐付けます。href
属性には、manifest.json
ファイルのパスを指定します。if ('serviceWorker' in navigator) { ... }
: このJavaScriptコードは、ブラウザがService Workerをサポートしているかどうかを確認し、サポートしていればservice-worker.js
ファイルを登録します。通常、Service Workerの登録はload
イベントが発火した後に行うことで、ページの読み込みに影響を与えないようにします。
CSSファイルの準備:
見た目を整えるためのCSSファイルを用意します。PWAはレスポンシブデザインが推奨されるため、様々なデバイスサイズに対応したスタイルを記述します。
/* style.css の例 */
body {
font-family: sans-serif;
margin: 20px;
text-align: center;
}
h1 {
color: #333;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
JavaScriptファイルの準備:
Webサイトのインタラクティブな機能や、Service Workerの登録ロジックなどを記述するJavaScriptファイルを用意します。上記のHTML例では、app.js
とService Workerの登録コードを直接HTMLに記述していますが、通常は外部ファイルとして管理します。
// app.js の例 (任意)
document.addEventListener('DOMContentLoaded', () => {
const installButton = document.getElementById('installButton');
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
installButton.style.display = 'block'; // インストールボタンを表示
});
installButton.addEventListener('click', () => {
if (deferredPrompt) {
deferredPrompt.prompt();
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('ユーザーはPWAをインストールしました');
} else {
console.log('ユーザーはPWAのインストールをキャンセルしました');
}
deferredPrompt = null;
installButton.style.display = 'none'; // インストールボタンを非表示
});
}
});
});
このapp.js
の例は、PWAをホーム画面に追加するための「インストールボタン」を表示し、ユーザーにPWAのインストールを促す一般的なパターンです。beforeinstallprompt
イベントは、ブラウザがPWAとして認識し、インストールプロンプトを表示できる準備ができたときに発火します。
これらのファイルが連携することで、WebサイトはPWAとしての機能を持つようになります。
HTTPS環境とキャッシュ戦略のポイント
PWAを動作させる上で、HTTPS環境の確立と適切なキャッシュ戦略は必須要件であり、PWAのパフォーマンスとセキュリティを左右する重要なポイントです。
HTTPS環境の必須性
PWAの主要な技術要素であるService Workerは、セキュリティ上の理由からHTTPS環境下でしか動作しません。これは、Service Workerがネットワークリクエストを傍受し、コンテンツを改変する可能性があるため、悪意のある攻撃からユーザーを保護するために厳格なセキュリティが求められるためです。
なぜHTTPSが必要か:
- データの暗号化: ユーザーとサーバー間の通信を暗号化し、個人情報や機密データの盗聴・改ざんを防ぎます。
- 認証: サーバーの身元を証明し、フィッシング詐欺などを防ぎます。
- 信頼性: HTTPS化されたサイトは、ユーザーやブラウザからの信頼性が高まります。特にGoogle Chromeなどのブラウザは、HTTPサイトに対して「安全でない」警告を表示することがあります。
- Service Workerの動作要件: Service Workerは、その強力な機能ゆえに、信頼できる安全な通信路(HTTPS)でのみ動作が許可されています。
キャッシュ戦略のポイント
Service Workerを導入する最大の理由の一つは、オフライン対応と高速化のためのキャッシュ戦略です。Service Workerは、install
、activate
、fetch
といった主要なイベントハンドラを通じて、どのリソースをいつ、どのようにキャッシュし、どのように提供するかを細かく制御できます。
代表的なキャッシュ戦略には以下のものがあります。
Cache First (キャッシュ優先):
- 戦略: まずキャッシュにリソースがあるかを確認し、あればそれを返します。キャッシュになければネットワークから取得し、キャッシュに追加します。
- 利点: オフライン環境でもコンテンツを提供でき、リソースの読み込みが非常に高速になります。
- 適しているコンテンツ: 静的なアセット(CSS, JavaScript, 画像など)、頻繁に更新されないコンテンツ。
実装例(Service Worker内):
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
return response || fetch(event.request);
})
);
});
Network First (ネットワーク優先):
- 戦略: まずネットワークからリソースを取得しようと試みます。ネットワークが利用できない場合や、タイムアウトした場合には、キャッシュからリソースを返します。
- 利点: 常に最新のコンテンツを提供できます。
- 適しているコンテンツ: 頻繁に更新されるコンテンツ(ニュース記事、SNSのタイムラインなど)。
実装例(Service Worker内):
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request)
.catch(() => {
return caches.match(event.request);
})
);
});
Stale-While-Revalidate (キャッシュを返しつつ、裏で更新):
- 戦略: まずキャッシュからリソースを即座に返し、同時にバックグラウンドでネットワークから最新のリソースを取得し、キャッシュを更新します。次回のアクセス時には、更新されたキャッシュが使われます。
- 利点: 高速性と常に最新のコンテンツ提供を両立できます。ユーザーは古いコンテンツを瞬時に見れるが、すぐに最新版に切り替わる。
- 適しているコンテンツ: 常に最新情報が必要だが、初回表示は高速にしたいコンテンツ(ニュース、ブログ記事など)。
実装例(Service Worker内):
self.addEventListener('fetch', event => {
event.respondWith(
caches.open('my-cache').then(cache => {
return cache.match(event.request).then(response => {
const fetchPromise = fetch(event.request).then(networkResponse => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return response || fetchPromise;
});
})
);
});
これらの戦略は、Webサイトの目的やコンテンツの特性に合わせて適切に選択し、組み合わせることが重要です。また、キャッシュの管理(古いキャッシュの削除など)もService Workerのactivate
イベントで行うことが推奨されます。
Workboxの活用:
Googleが提供する「Workbox」は、これらのService Workerのキャッシュ戦略の実装を大幅に簡素化するためのライブラリです。複雑なコードを書かずに、設定ファイルや簡単なAPIコールだけで高度なキャッシュ戦略を実装できます。特に、大規模なPWAや、特定のフレームワーク(React, Vue.jsなど)を使用している場合には、Workboxの導入を強く検討することをおすすめします。Workboxは、webpackなどのビルドツールと連携して、キャッシュすべきファイルを自動的に生成することも可能です。
適切なHTTPS化とキャッシュ戦略は、PWAの性能と信頼性を決定づけるため、丁寧な実装とテストが求められます。

PWAの作り方:具体的なステップバイステップガイド
さあ、「pwa 作り方」の核心に迫りましょう。ここでは、実際にWebサイトをPWA化するための具体的なステップを、コード例を交えながら詳しく解説します。このガイドに従えば、あなたのWebサイトもアプリのように変貌を遂げるはずです。

PWA化するWebサイトの準備と要件定義
PWA化に着手する前に、まずは対象となるWebサイトの現状を把握し、PWA化の目的と要件を明確にすることが重要です。この準備段階を怠ると、後々の開発で手戻りが発生したり、期待通りの効果が得られなかったりする可能性があります。
1.PWA化の目的を明確にする:
- なぜPWA化したいのか?(例:ユーザーエンゲージメント向上、オフライン対応、高速化、アプリ開発コスト削減、SEO強化など)
- PWA化によってどのような成果を期待するのか?(例:再訪率の向上、コンバージョン率の改善、アプリのダウンロード数の増加など)
これらの目的が明確であれば、どの機能をPWAで優先的に実装すべきか、どのようなデザインが適しているかが見えてきます。
2.ターゲットユーザーの分析:
- PWAを利用するユーザーは誰か?
- 彼らはどのような環境でWebサイトを利用するか?(例:モバイルユーザーが多いか、オフラインでの利用ニーズがあるか)
- ユーザーがPWAに期待する機能は何か?
ユーザーのニーズを深く理解することで、提供すべきPWAの機能や体験を最適化できます。
3.既存Webサイトの現状把握と改善点:
- Webサイトの基本的なSEO対策は十分か?(PWAは既存のWebサイトを強化するものであり、SEOの基礎ができていないと効果が薄れる可能性があります。)
- レスポンシブデザインに対応しているか?
- 既存のコードベースはPWA化に適しているか?(JavaScriptフレームワークの有無、モジュール化の状況など)
- パフォーマンスはどうか?(Lighthouseなどで現状のスコアを確認し、改善点を見つける。)
既存サイトの弱点を洗い出し、PWA化と並行して改善していくことで、より高い効果が期待できます。
4.必要な機能の洗い出し:
- オフライン機能はどの程度必要か?(全ページオフライン対応、一部コンテンツのみ、など)
- プッシュ通知は必要か?必要であればどのような情報を通知するか?
- ホーム画面への追加機能は必須か?
- バックグラウンド同期などの高度な機能は必要か?
これらの要件に基づいて、PWAの機能セットを決定します。最小限の機能から始めて、段階的に機能を追加していく「プログレッシブエンハンスメント」の考え方も有効です。
5.技術スタックの検討:
- 特定のJavaScriptフレームワーク(React, Vue.js, Angularなど)を使用するか?
- Service Workerのヘルパーライブラリ(Workboxなど)を使用するか?
- ビルドツール(Webpack, Parcelなど)の導入は必要か?
プロジェクトの規模や開発チームのスキルセットに応じて、最適な技術スタックを選定します。
この準備と要件定義のステップを丁寧に行うことで、効果的かつ効率的なPWA開発を進めることができます。
Web App Manifestの作成と設定
manifest.json
ファイルは、ユーザーがホーム画面にPWAを追加した際の名前、アイコン、表示形式などを定義します。
まず、Webサイトのルートディレクトリにmanifest.json
という名前でファイルを作成し、以下の内容を記述します。
{
"name": "私のPWAサイト",
"short_name": "私のPWA",
"description": "PWAの作り方を解説するデモサイトです。",
"start_url": "/index.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#007bff",
"icons": [
{
"src": "/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"orientation": "portrait",
"scope": "/",
"lang": "ja-JP"
}
各プロパティの意味と設定方法は以下の通りです。
name
: PWAの正式名称です。アプリの起動画面や、アプリの切り替え画面に表示されます。short_name
:name
が長すぎる場合に、ホーム画面や限られたスペースに表示される短い名前です。name
と異なる場合は設定します。description
: アプリストアのアプリ説明文のように、PWAの概要を記述します。start_url
: PWAを起動したときに最初に表示されるページのURLを指定します。通常は/
や/index.html
など、サイトのトップページを指定します。display
: PWAの表示モードを定義します。fullscreen
: デバイスの画面全体を占める。ブラウザのUI(アドレスバー、ツールバーなど)は表示されない。ゲームなどに適している。standalone
: ブラウザのUIなしで、ネイティブアプリのように表示される。一般的なPWAで最もよく使われるモード。minimal-ui
:standalone
に似ているが、戻るボタンや更新ボタンなど、最小限のブラウザUIが表示される。browser
: 通常のWebブラウザタブとして表示される。
background_color
: アプリの起動画面(スプラッシュスクリーン)の背景色を指定します。ユーザーがアプリを起動するまでの間、この色が表示されます。theme_color
: アプリのテーマカラーです。OSのタスクバーや、ブラウザのタイトルバーの色に影響を与えることがあります。icons
: PWAのアイコンを設定します。様々なデバイスや画面サイズに対応できるよう、複数のサイズのアイコンを用意することが重要です。src
: アイコンファイルのパス。sizes
: アイコンのサイズ(例: “192×192″)。複数のサイズを用意することで、OSやデバイスに応じて最適なアイコンが表示されます。type
: アイコンのMIMEタイプ(例: “image/png”)。- OSごとのアイコンサイズと設定の注意点:
- pwa 作り方 ios: iOSでは、Web App Manifestだけでなく、HTMLの
<head>
内にapple-touch-icon
のメタタグを追加することが推奨されます。これにより、Safariで「ホーム画面に追加」した際のアイコンがより綺麗に表示されます。apple-touch-icon
は通常、180×180ピクセルを用意すれば十分です。 - pwa 作り方 windows: WindowsのEdgeブラウザでは、Web App Manifestの
icons
に設定されたアイコンが利用されます。特別なメタタグは不要です。 - pwa 作り方 android: AndroidのChromeブラウザでは、
icons
プロパティに設定されたアイコンが自動的に認識され、ホーム画面に追加されます。特に192x192pxと512x512pxのアイコンは重要です。
- pwa 作り方 ios: iOSでは、Web App Manifestだけでなく、HTMLの
orientation
: PWAの表示方向を指定します(例:portrait
(縦向き)、landscape
(横向き))。scope
: Service Workerが制御できる範囲を定義します。通常は/
を設定し、サイト全体を対象とします。lang
: アプリの主要な言語を指定します(例:ja-JP
)。
manifest.json
ファイルを作成したら、HTMLファイルの<head>
セクションで読み込むことを忘れないでください。
<link rel="manifest" href="/manifest.json">
これで、WebサイトはPWAとして認識され、ユーザーにホーム画面への追加を促すプロンプトが表示される準備が整います。
Service Workerの登録とキャッシュ戦略の実装
Service Workerはオフライン機能や高速化、プッシュ通知などを司ります。Service Workerの登録とキャッシュ戦略の実装は、PWA化の最も技術的な核となる部分です。
まず、Service WorkerのJavaScriptファイルを作成します。ここでは、service-worker.js
という名前でルートディレクトリに配置することを想定します。
1.Service Workerの登録(HTML/JavaScript)
HTMLファイル、またはメインのJavaScriptファイル(例: app.js
)で、Service Workerを登録するコードを記述します。これは、ブラウザがService Workerを認識し、インストールプロセスを開始するための指示です。
// service-worker.jsを登録するJavaScriptコード
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js', { scope: '/' })
.then(registration => {
console.log('Service Worker registration successful with scope:', registration.scope);
})
.catch(error => {
console.log('Service Worker registration failed:', error);
});
});
}
'serviceWorker' in navigator
: ブラウザがService Worker APIをサポートしているかを確認します。window.addEventListener('load', ...)
: ページが完全に読み込まれた後にService Workerの登録を行うことで、ページの初期表示パフォーマンスへの影響を最小限に抑えます。navigator.serviceWorker.register('/service-worker.js', { scope: '/' })
: Service Workerファイルを登録します。scope
オプションは、Service Workerが制御できる範囲を定義します。/
を指定すると、サイト全体を制御できます。
2.Service Workerのイベントハンドラ(service-worker.js
)登録
service-worker.js
ファイル内で、PWAの機能を実現するための主要なイベントハンドラを記述します。
install
イベント: キャッシュの初期化
Service Workerがブラウザにインストールされる際に一度だけ発火します。ここで、PWAの動作に必要な静的アセット(HTML, CSS, JavaScript, 画像など)を事前にキャッシュします。
const CACHE_NAME = 'my-pwa-cache-v1'; // キャッシュ名。バージョン管理に便利
const urlsToCache = [
'/',
'/index.html',
'/style.css',
'/app.js',
'/icons/icon-192x192.png', // manifest.jsonで指定したアイコン
// 他にもオフラインで利用したいアセットを追加
];
self.addEventListener('install', event => {
console.log('Service Worker installing...');
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Opened cache');
return cache.addAll(urlsToCache); // 指定したリソースをキャッシュに追加
})
);
});
activate
イベント: 古いキャッシュのクリーンアップ
Service Workerが有効化された際に発火します。主に、古いバージョンのService Workerによって作成されたキャッシュを削除し、キャッシュのクリーンアップを行います。
self.addEventListener('activate', event => {
console.log('Service Worker activating...');
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) { // 現在のキャッシュ名と異なる場合
console.log('Deleting old cache:', cacheName);
return caches.delete(cacheName); // 古いキャッシュを削除
}
return Promise.resolve();
})
);
})
);
return self.clients.claim(); // Service Workerがすぐに制御を開始するようにする
});
fetch
イベント: ネットワークリクエストの傍受とキャッシュ戦略
Service Workerが制御するスコープ内のあらゆるネットワークリクエストがこのイベントで傍受されます。ここで、上で解説したキャッシュ戦略(Cache First, Network Firstなど)を実装します。
self.addEventListener('fetch', event => {
// 例: Cache First戦略
event.respondWith(
caches.match(event.request)
.then(response => {
// キャッシュにリソースがあれば、それを返す
if (response) {
return response;
}
// キャッシュになければ、ネットワークから取得し、キャッシュに追加してから返す
return fetch(event.request).then(
networkResponse => {
// レスポンスが不正な場合はキャッシュしない
if (!networkResponse || networkResponse.status !== 200 || networkResponse.type !== 'basic') {
return networkResponse;
}
const responseToCache = networkResponse.clone(); // レスポンスは一度しか消費できないためクローンする
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache);
});
return networkResponse;
}
);
})
.catch(error => {
// オフラインでキャッシュもなかった場合のフォールバック(例: オフラインページを表示)
console.error('Fetch failed:', error);
// return caches.match('/offline.html'); // 必要に応じてオフラインページを表示
})
);
});
この例は基本的なCache First戦略ですが、Webサイトの要件に応じて、Network FirstやStale-While-Revalidateなど、複数の戦略を組み合わせることも可能です。例えば、HTMLはNetwork First、画像やCSSはCache Firstといった具合に使い分けることができます。
Workboxの活用:
手動でService Workerを記述するのは複雑でバグも発生しやすいため、Googleが提供するWorkboxライブラリの利用を強く推奨します。Workboxを使えば、数行の設定コードを書くだけで、高度なキャッシュ戦略を実装できます。
Workbox CLIを使った基本的な導入例:
1.インストール:
npm install workbox-cli -g
2.設定ファイルの生成:
プロジェクトのルートで以下のコマンドを実行し、workbox-config.js
を生成します。
このコマンドは、Service Workerファイルを自動生成するための設定ファイルを作成します。設定ファイルには、キャッシュしたいファイルのパターンや、使用したいキャッシュ戦略などを記述します。
workbox generateSW
3.Service Workerの生成:
設定ファイルに基づいてService Workerファイルを生成します。
生成されたService Workerファイル(例: sw.js
)をHTMLから登録します。
workbox injectManifest # または workbox generateSW
Workboxは、プリキャッシュ(ビルド時に静的アセットをキャッシュ)、ランタイムキャッシュ(実行時に動的コンテンツをキャッシュ)、ルーティング、戦略など、Service Worker開発に必要なほとんどの機能を提供します。これにより、「pwa 作り方」のキャッシュ部分の実装が劇的に簡素化され、開発者はよりアプリケーションロジックに集中できるようになります。
HTTPS化とセキュリティ対策
PWAを実装する上で、HTTPS化はService Workerを動作させるための必須条件であり、ユーザーに安全なWeb体験を提供するための基礎となります。
SSL/TLS証明書の取得と設定:
WebサイトをHTTPS化するためには、SSL/TLS証明書が必要です。
無料のSSL証明書:
Let’s Encrypt: 非常に人気があり、無料でSSL証明書を発行できる認証局です。多くのWebホスティングサービスやサーバー管理ツール(Certbotなど)がLet’s Encryptとの連携をサポートしています。自動更新も可能で、手軽に導入できます。
導入方法の概要(Certbot利用の場合):
- Certbotをサーバーにインストールします。
sudo certbot --apache
(Apacheの場合) またはsudo certbot --nginx
(Nginxの場合) を実行します。- 指示に従ってドメイン名を入力し、証明書を取得・設定します。
- 自動更新設定も行います。
CDNサービス: CloudflareなどのCDNサービスも無料SSLを提供しており、DNS設定を変更するだけで手軽にHTTPS化できる場合があります。
有料のSSL証明書:
より高度な信頼性やサポートが必要な場合は、各種認証局から発行される有料の証明書(EV証明書など)も選択肢となります。
Webサーバーの設定:
取得したSSL証明書をWebサーバー(Apache, Nginxなど)に設定し、すべてのHTTPリクエストをHTTPSにリダイレクトする設定を行います。
Apacheの例 (.htaccessまたはhttpd.conf):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Nginxの例 (nginx.conf):
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /path/to/your_domain.crt;
ssl_certificate_key /path/to/your_domain.key;
# その他のSSL設定
...
}
Mixed Contentの解消:
HTTPS化しても、Webサイト内にHTTPで読み込まれるリソース(画像、CSS、JavaScriptなど)が残っていると、「Mixed Content(混在コンテンツ)」警告が表示され、セキュリティ上の問題となります。開発者ツールなどでMixed Contentを検出し、すべてHTTPSで読み込まれるように修正する必要があります。
- 相対パス(例:
/images/logo.png
)を使用するか、すべてのURLをhttps://
で始めるように修正します。
セキュリティヘッダーの導入:
HTTP Strict Transport Security (HSTS) などのセキュリティヘッダーを設定することで、Webサイトのセキュリティをさらに強化できます。HSTSは、一度HTTPSでアクセスしたユーザーに対して、次回以降も必ずHTTPSで接続するようブラウザに指示します。
Apacheの例 (.htaccessまたはhttpd.conf):
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Nginxの例 (nginx.conf):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
preload
ディレクティブを含めることで、ブラウザにHSTSリストへの追加を申請でき、初回アクセスからHTTPSを強制できます。
これらの対策を講じることで、PWAは安全な環境で提供され、Service Workerが期待通りに動作するようになります。ユーザーの信頼を得るためにも、HTTPS化は最優先で実施すべき事項です。
プッシュ通知の実装とユーザーエンゲージメント向上
プッシュ通知は、PWAがネイティブアプリに匹敵するユーザーエンゲージメントを実現するための強力な機能です。ユーザーがブラウザを閉じていても、新着情報や重要なアラートを直接送信し、再訪問を促すことができます。
プッシュ通知の実装には、主に以下の要素が必要です。
1.通知許可の取得:
ユーザーに通知を許可してもらう必要があります。これは通常、WebサイトのUIからボタンなどで許可を促し、JavaScriptのNotification.requestPermission()
を使って行います。
// プッシュ通知の許可を求める関数
function askNotificationPermission() {
if ('Notification' in window) {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
console.log('通知の許可が与えられました。');
subscribeUserToPush(); // 許可されたら購読処理へ
} else {
console.warn('通知が拒否されました。');
}
});
} else {
console.warn('このブラウザは通知に対応していません。');
}
}
// ユーザーに許可を促すボタンの例
document.getElementById('enable-notifications').addEventListener('click', askNotificationPermission);
2.プッシュ通知の購読(Service Worker側):
ユーザーが通知を許可すると、ブラウザはService Workerを通じてプッシュサービス(例: GoogleのFCM、MozillaのWebPushなど)に登録し、PushSubscription
オブジェクトを取得します。このオブジェクトには、プッシュ通知を送信するためのエンドポイントURLや認証情報が含まれます。この情報をサーバーに保存します。
// Service Worker側 (service-worker.js)
self.addEventListener('push', event => {
const data = event.data.json(); // サーバーから送られてきたデータ
console.log('Push received:', data);
const title = data.title || '新しい通知';
const options = {
body: data.body || '新しい情報があります。',
icon: data.icon || '/icons/icon-192x192.png',
badge: '/icons/badge-72x72.png', // Androidで表示されるバッジアイコン
data: {
url: data.url || '/' // 通知クリック時に開くURL
}
};
event.waitUntil(
self.registration.showNotification(title, options)
);
});
self.addEventListener('notificationclick', event => {
console.log('Notification clicked.');
event.notification.close(); // 通知を閉じる
// 通知クリック時に特定のURLを開く
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
// クライアント側 (app.jsなど) - プッシュ通知の購読処理
function subscribeUserToPush() {
navigator.serviceWorker.ready.then(registration => {
const applicationServerKey = 'YOUR_PUBLIC_VAPID_KEY_HERE'; // サーバーで生成したVAPID公開鍵
registration.pushManager.subscribe({
userVisibleOnly: true, // ユーザーに常に通知が表示されるようにする
applicationServerKey: urlBase64ToUint8Array(applicationServerKey)
})
.then(subscription => {
console.log('Push subscription:', subscription);
// 購読情報をサーバーに送信(エンドポイントURLなどを保存)
sendSubscriptionToServer(subscription);
})
.catch(error => {
console.error('Failed to subscribe the user:', error);
});
});
}
// VAPID公開鍵をUint8Arrayに変換するヘルパー関数
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
// 購読情報をサーバーに送信するダミー関数
function sendSubscriptionToServer(subscription) {
// ここで、subscriptionオブジェクト(JSON形式)をサーバーのエンドポイントにPOSTなどで送信します。
// サーバーは、この購読情報を保存し、後でプッシュ通知を送信する際に利用します。
console.log('Subscription sent to server:', JSON.stringify(subscription));
}
applicationServerKey
は、サーバーサイドで生成するVAPID(Voluntary Application Server Identification)キーペアの公開鍵です。これは、プッシュ通知を送信するサーバーが正当であることをプッシュサービスに証明するために使用されます。
3.サーバーサイドでのプッシュ通知送信:
サーバーサイドでは、保存したPushSubscription
情報(エンドポイントURL、認証情報)とVAPID秘密鍵を使用して、Webプッシュプロトコルに従ってプッシュサービスに通知を送信します。Node.js, PHP, Pythonなどの様々な言語でWebプッシュライブラリが提供されています。
Node.jsの例(web-push
ライブラリを使用):
const webpush = require('web-push');
// VAPIDキーを設定 (環境変数などから取得)
webpush.setVapidDetails(
'<mailto:your-email@example.com>', // 連絡先メールアドレス
'YOUR_PUBLIC_VAPID_KEY_HERE', // VAPID公開鍵
'YOUR_PRIVATE_VAPID_KEY_HERE' // VAPID秘密鍵
);
// クライアントから受け取った購読情報
const pushSubscription = {
endpoint: '...',
keys: {
p256dh: '...',
auth: '...'
}
};
const payload = JSON.stringify({
title: '新着記事のお知らせ!',
body: 'PWAの作り方に関する新しい記事が公開されました!',
icon: '<https://yourdomain.com/icons/icon-192x192.png>',
url: '<https://yourdomain.com/new-article.html>'
});
webpush.sendNotification(pushSubscription, payload)
.then(() => console.log('Push notification sent.'))
.catch(error => console.error('Failed to send push notification:', error));
プッシュ通知を実装することで、ユーザーとの継続的な接点を持つことができ、サイトへの再訪率やエンゲージメントを大幅に向上させることが可能です。ただし、通知の送りすぎはユーザーに不快感を与え、ブロックされる原因となるため、適切な頻度と内容で通知を送るよう心がけましょう。

PWAの動作確認とデバッグ、改善
PWAを開発する上で、正しく機能しているかを確認し、問題があればデバッグし、継続的に改善していくプロセスは非常に重要です。
1.Google Chrome DevTools (Lighthouse)
PWAのデバッグと評価に最も役立つツールの一つが、Google Chromeに内蔵されているDevToolsのLighthouseタブです。Lighthouseは、Webサイトのパフォーマンス、アクセシビリティ、SEO、そしてPWAの基準にどれだけ適合しているかを自動的に監査し、スコアと改善提案を表示してくれます。
PWAスコアの測定:
- ChromeでPWA化したいWebサイトを開きます。
- DevTools (F12または右クリック→「検証」) を開きます。
- 「Lighthouse」タブをクリックします。
- 「Categories」で「Progressive Web App」にチェックを入れ、必要に応じて他のカテゴリも選択します。
- 「Generate report」ボタンをクリックします。
- レポートが生成され、PWAの適合度合いがスコア(0-100点)で表示されます。特に「Fast and reliable」「Installable」「PWA Optimized」の項目が重要です。
改善提案の確認:
Lighthouseレポートには、スコアが低い項目について具体的な改善提案が表示されます。例えば、Service Workerが登録されていない、Manifestファイルが見つからない、HTTPS化されていない、オフラインで動作しない、といった問題点が指摘されます。これらの提案に従って修正を行うことで、PWAの品質を向上させることができます。
2.Service Workerのデバッグ
DevToolsの「Application」タブ内にある「Service Workers」セクションは、Service Workerの状態を確認し、デバッグするための強力なツールです。
- 状態の確認: Service Workerが登録されているか、アクティブになっているか、更新があるかなどを確認できます。
- 強制更新: 「Update on reload」にチェックを入れると、ページをリロードするたびにService Workerが更新されるため、開発中に新しいService Workerの変更をすぐにテストできます。
- アンレジスター: 「Unregister」ボタンをクリックすると、Service Workerを完全に解除できます。キャッシュをクリアして最初からテストしたい場合に便利です。
- エラーログ: Service Worker内で発生したエラーは、Consoleタブに表示されます。
3.キャッシュストレージの確認
DevToolsの「Application」タブ内にある「Cache Storage」セクションで、Service Workerによってキャッシュされたコンテンツを確認できます。
- キャッシュ名と、その中に保存されているリソースの一覧が表示されます。
- 個々のリソースをクリックすると、その詳細(URL、サイズなど)を確認できます。
- キャッシュの内容を削除することも可能です。
4.オフラインテスト
PWAのオフライン機能は、Service Workerが正しく動作しているかを確認する上で不可欠です。
- DevToolsの「Network」タブを開き、「Offline」チェックボックスにチェックを入れるか、またはネットワークスロットリングを「Offline」に設定します。
- この状態でページをリロードし、オフラインでもコンテンツが表示されるかを確認します。
5.各OSでのテスト方法
iOS (Safari):
- iPhone/iPadの実機でSafariを開き、PWA化したいWebサイトにアクセスします。
- 下部の共有ボタン(四角から上向きの矢印)をタップし、「ホーム画面に追加」を選択します。
- ホーム画面に追加されたアイコンをタップして起動し、フルスクリーン表示されるか、オフラインで動作するかなどを確認します。
- iOSでは、Service WorkerのデバッグはmacOSのSafariの開発メニューから行うことができます。
Android (Chrome):
- Android端末でChromeを開き、PWA化したいWebサイトにアクセスします。
- ChromeがPWAとして認識すると、アドレスバーにインストールアイコンが表示されるか、下部にインストールを促すバナーが表示されます。
- 「ホーム画面に追加」を選択し、インストールします。
- インストールされたPWAを起動し、オフライン動作、プッシュ通知、テーマカラーなどが正しく適用されているかを確認します。
- Android Chromeのデバッグは、USBデバッグを有効にしたAndroid端末をPCに接続し、PCのChrome DevToolsからリモートデバッグを行うことができます。
Windows (Edge/Chrome):
- EdgeまたはChromeでPWA化したいWebサイトにアクセスします。
- アドレスバーにインストールアイコン(プラスボタン)が表示されるので、クリックしてインストールします。
- スタートメニューやデスクトップに追加されたPWAを起動し、独立したウィンドウで表示されるか、オフライン動作などを確認します。
- デバッグはChrome DevToolsと同様に行えます。
これらのツールと手順を活用することで、PWAの動作を確実に検証し、高品質なPWAを構築・提供することができます。

よくある質問(FAQ)
-
PWAはSEOに有利ですか?
-
PWA自体が直接的なSEOランキング要因になるわけではありませんが、間接的にSEOに非常に有利に働きます。Googleはユーザー体験を重視しており、PWAが提供する以下の特徴はSEOに好影響を与えます。
- ページの高速化: PWAのキャッシュ機能により、ページの読み込み速度が向上します。ページの表示速度はGoogleのランキング要因の一つです。
- モバイルフレンドリー: レスポンシブデザインにより、様々なデバイスで最適に表示されます。モバイルフレンドリーなサイトはモバイル検索での評価が高まります。
- オフラインアクセス: ネットワーク接続が不安定な場所でもコンテンツにアクセスできるため、ユーザー体験が向上し、離脱率の低下に貢献します。
- エンゲージメントの向上: ホーム画面への追加やプッシュ通知により、ユーザーの再訪率やサイト滞在時間が増加します。これらのユーザー行動はGoogleの評価に影響を与える可能性があります。
- HTTPS化: PWAはHTTPSが必須であり、HTTPSはGoogleのランキング要因の一つです。
これらの要素は、結果としてユーザー満足度を高め、検索エンジンからの評価を向上させるため、PWAはSEO戦略の重要な一部となり得ます。
-
PWAはすべてのブラウザで動きますか?
-
PWAの主要な機能は、主要なモダンブラウザで広くサポートされています。
- Google Chrome: Android、Windows、macOS、Linux版のChromeでPWAのほぼ全ての機能がサポートされています。
- Mozilla Firefox: Service Worker、Web App Manifestなどの主要機能はサポートされています。プッシュ通知も利用可能です。
- Microsoft Edge: Chromiumベースになってからは、Chromeと同様にPWAの強力なサポートが提供されています。
- Apple Safari (iOS/macOS): Service WorkerとWeb App Manifestの基本的な機能はサポートされていますが、プッシュ通知など一部の機能には制限があります。iOSでは、ホーム画面に追加すると全画面表示になるものの、プッシュ通知は現在のところSafari自体がサポートしておらず、Web Push APIを通じた通知はできません(ただし、サードパーティのSDKを利用する方法は存在します)。また、iOSではネイティブアプリのようにアプリスイッチャーに表示されるわけではありません。
したがって、PWAは「プログレッシブエンハンスメント」の概念に基づいており、ブラウザのサポート状況に応じて機能が段階的に提供されます。完全にすべてのブラウザで全く同じ体験が得られるわけではありませんが、主要なブラウザでは多くのPWA機能を利用できます。
-
PWAはネイティブアプリの代わりになりますか?
-
すべてのケースでネイティブアプリの代わりになるわけではありませんが、多くのユースケースで非常に有効な代替手段となり得ます。
PWAが適しているケース:
- コンテンツ閲覧が中心のサイト(ニュース、ブログ、ECサイトの一部)
- 高速な初期表示が求められるサイト
- オフラインでの利用ニーズがあるサイト
- 開発コストと時間を抑えたい場合
- アプリストアの審査なしでリリースしたい場合
- マルチプラットフォーム(iOS/Android/Windows)で統一された体験を提供したい場合
ネイティブアプリが適しているケース:
- 高度なグラフィック処理や複雑なアニメーションを必要とするゲーム
- Bluetoothなど、デバイスの全てのハードウェア機能に密接に連携する必要があるアプリ
- App Store / Google Playでのマーケティングや収益化がビジネスモデルの核となる場合
- 非常に大規模で複雑なデータ処理やローカルデータベースとの連携が必要な場合
- 特定のOSのUI/UXに完全に準拠した体験を提供したい場合
PWAは、Webのリーチとネイティブアプリの体験を融合させることで、多くのWebサイトにとって「アプリのような」体験を提供するための最適なソリューションとなります。ゼロからネイティブアプリを開発する前に、PWAでユーザーのニーズを満たせないか検討する価値は十分にあります。
-
既存のWebサイトをPWA化できますか?
-
はい、ほとんどの既存のWebサイトをPWA化することが可能です。 既にHTML、CSS、JavaScriptで構築されているWebサイトであれば、以下のステップでPWA化を進めることができます。
- HTTPS化: 既存サイトがHTTPであれば、まずHTTPSに移行します。これがPWAの必須要件です。
- Web App Manifestの追加:
manifest.json
ファイルを作成し、HTMLの<head>
に追加します。 - Service Workerの追加と登録:
service-worker.js
ファイルを作成し、キャッシュ戦略を実装します。HTML/JavaScriptでService Workerを登録するコードを追加します。 - レスポンシブデザインの確認: 様々なデバイスで快適に表示されるよう、既存のCSSやレイアウトを調整します。
- パフォーマンス改善: 画像の最適化、コードの圧縮、レンダリングブロックの排除など、Webサイトのパフォーマンスをさらに向上させます。
これらのステップを踏むことで、既存のWebサイトにPWAの機能を追加し、ユーザー体験を向上させることができます。
-
ReactやVue.jsなどのフレームワークでのPWA実装方法は?
-
ReactやVue.js、AngularなどのモダンなJavaScriptフレームワークは、PWAとの相性が非常に良く、PWA化を容易にするツールや機能が提供されています。
Create React App (CRA):
create-react-app
でプロジェクトを新規作成する際、Service WorkerとManifestがデフォルトで組み込まれます(src/serviceWorkerRegistration.js
とpublic/manifest.json
)。特に何も設定しなくても、初期状態でPWAとして機能するテンプレートが提供されます。本番環境でService Workerを有効にするには、src/index.js
でserviceWorkerRegistration.unregister()
をserviceWorkerRegistration.register()
に変更するだけです。Vue CLI:
Vue CLIでプロジェクトを新規作成する際、「PWA support」オプションを選択することで、Workboxを使ったService WorkerとManifestファイルが自動的に生成されます。設定ファイル(vue.config.js
)でWorkboxの設定をカスタマイズすることも可能です。Next.js / Nuxt.js:
これらのサーバーサイドレンダリング(SSR)や静的サイトジェネレーション(SSG)をサポートするフレームワークでもPWA化は可能です。Next.js:
next-pwa
のようなライブラリを利用することで、Service WorkerやManifestの自動生成と設定を簡単に行えます。Nuxt.js:
@nuxtjs/pwa
モジュールを利用することで、Service Worker、Manifest、アイコン生成、プッシュ通知などのPWA関連機能を一元的に管理・設定できます。Workboxの統合: 多くのフレームワークでは、上記のようにWorkboxが内部的に利用されています。Workboxは、これらのフレームワークで生成されるJavaScriptバンドルやその他のアセットを効率的にキャッシュするための設定をサポートしており、複雑なService Workerの記述を不要にします。
これらのフレームワークを利用することで、「pwaアプリ 作り方」の大部分が自動化され、開発者はPWAの主要な機能実装に集中できます。既存のWebサイトがこれらのフレームワークで構築されている場合も、PWA化の導入は比較的スムーズに進められるでしょう。

まとめ
本記事では「pwa 作り方」というキーワードに対し、初めての方でも実装できるように、基本概念から具体的な構築手順までを丁寧に解説してきました。
Webサイトをアプリのように使えるようにするPWAは、ユーザー体験の向上や開発・運用コストの削減、さらにSEOにも間接的に良い影響を与える可能性があります。この記事で解説した内容を実践することで、今あるWebサイトをより価値あるものに進化させることができるでしょう。
「難しそう」と感じていたPWAも、ポイントを押さえて実装すれば意外とスムーズに構築できます。ユーザーと検索エンジンの両方に評価されるWebサイトを目指すなら、PWAの導入は非常に効果的な一手と言えるでしょう。


