「自分のWEBサイトをアプリ化してみたい。でも、App StoreやAndroidなどスマホアプリ専用で開発するのは学習コストが高すぎる…」と思う人もいるかもしれません。
その悩みを解決し、Webサイトの快適性を劇的に向上させるのが、PWA(プログレッシブウェブアプリ)という技術です。
この技術を使えば、お気に入りのWebサイトをホーム画面に追加し、一瞬で起動でき、さらにインターネットがない場所でもサクサクと表示させることが可能になります。
本記事では、PWAとは何かをネイティブアプリとの違いを交えながらわかりやすく解説しています。
また、WebサイトをPWA化するために必要な具体的な設定やコードを実例付きでご紹介します。これで、あなたのサイトも「消えないアプリ」へと生まれ変わります。
PWAとは?
PWA(ピーダブルエー)とは、WebサイトをiOSアプリやAndroidアプリのように使えるようにする技術のことです。
簡単に言うと、WEBサイトを、PCやタブレット、スマホで使える「アプリ」のようにすることができます。
本来、iPhoneやAndroidでアプリとしてダウンロードできるようにするには、App StoreやGoogle Playの要件を満たした開発をして承認される必要があります。
PWAはそれらの承認をすることなく、より簡単にアプリのようにすることができます。
PWAは「Progressive Web Apps」の略で、プログレッシブウェブアプリと呼びます。意味は「段階的なウェブアプリ」です。
PWAの特徴
PWAは、Webサイトとネイティブアプリ(iOSやAndroidのアプリストアからインストールするアプリ)の両方の利点を組み合わせたものです。
PWAの主な特徴は以下の通りです。
プログレッシブ(段階的強化)
PWAは「Progressive(段階的)」という名前の通り、どんなブラウザでもまずは基本的なWebサイトとして機能します。
そして、対応するブラウザであれば、ホーム画面に追加、オフライン利用、プッシュ通知といった便利な機能が段階的に利用できるようになります。
オフラインでの動作
オフラインで動作することは、PWAは「Service Worker」という技術を使って、一度アクセスしたWebページの情報をキャッシュ(一時保存)します。
これにより、インターネット接続がないオフライン状態でも、キャッシュされたコンテンツ(画像やテキスト)を閲覧することができます。
キャッシュしたデータは、PCやスマホなど、PWAでアクセスしたデバイスに保存されます。
ホーム画面への追加
ネイティブアプリのように、スマートフォンのホーム画面にアイコンとして追加することができます。
ユーザーは、アプリストアからのインストールなしに、ワンタップでWebサイトにアクセスできるようになります。
PCであれば、デスクトップにアイコンを追加することができます。
PC、スマホともに、ホーム画面やデスクトップに保存したときに表示するアイコンを指定することができます。
プッシュ通知
ネイティブアプリと同様に、新しい情報や更新をプッシュ通知でユーザーに知らせることができます。
これにより、再訪問を促し、ユーザーとのエンゲージメントを高めることができます。
高速な表示と優れたパフォーマンス
キャッシュ機能により、初回アクセス以降のページの読み込みが非常に速くなります。
ブラウザのUI(アドレスバーやツールバー)が表示されず、全画面表示になるため、ネイティブアプリに近い、スムーズで没入感のあるユーザー体験を提供します。
検索エンジンからの発見
ネイティブアプリとは異なり、Webサイトであるため、Googleなどの検索エンジンにインデックスされます。これにより、新しいユーザーが検索を通じてサービスを発見しやすくなります。
逆に言うと、通常のWEBサイトをPWAにすることができます。
開発・運用の効率性
プラットフォームごとに異なるアプリを開発する必要がなく、一つのWebサイトを開発するだけで、iOSとAndroidの両方のユーザーにアプリのような体験を提供できます。これにより、開発コストやメンテナンスの手間を大幅に削減できます。
ネイティブアプリの場合、iOSとAndroidごとに別々に開発する必要があります。
(補足)ネイティブアプリとは何か?
ネイティブアプリとは、「特定のOS(オペレーティングシステム)向けに作られた専用のアプリ」のことです。
私たちが普段、App Store(iPhone用)やGoogle Playストア(Android用)からダウンロードして使っているアプリのほとんどが、このネイティブアプリにあたります。
- iOS用: AppleのiPhoneやiPad向けに、SwiftやObjective-Cなどの言語で開発されます。
- Android用: GoogleのAndroidスマートフォン向けに、JavaやKotlinなどの言語で開発されます。
これらのアプリは、それぞれのOSの機能や設計に最適化されているため、以下のような特徴を持っています。
- 高速でスムーズな動作: デバイスの性能を最大限に引き出すため、アニメーションが滑らかで、動作が軽快です。
- デバイスの機能をフル活用: カメラ、GPS、プッシュ通知、マイク、指紋認証(Face IDやTouch ID)など、スマートフォンのあらゆる機能をアプリ内で自由に使うことができます。
- オフラインでの利用: 一度インストールすれば、インターネットに接続していなくても多くの機能が使えます。(もちろん、オンライン接続が必要な機能は使えません)
なぜ「ネイティブ」がつくのか?
「ネイティブ」という言葉には、「その土地固有の、生まれつきの」という意味があります。
アプリに「ネイティブ」がつくのは、特定のOS(iOSやAndroid)に「生まれつき備わっている」機能や環境を最大限に活用して作られているためです。
ネイティブアプリが作られる以前は、「ウェブアプリ」という、Webブラウザ上で動くアプリが主流でした。しかし、ウェブアプリはWebブラウザの機能に依存するため、デバイスの機能をフルに活用したり、高速な動作を実現したりすることが難しいという制約がありました。
そこで、iOSとAndroidというそれぞれのOSに特化した開発手法が登場し、これらのアプリは「ネイティブ(そのOS固有の)」なアプリと呼ばれるようになりました。
PWAとネイティブアプリの特徴比較
| 項目 | PWA | ネイティブアプリ |
|---|---|---|
| 入手方法 | アプリストアは不要。Webサイトにアクセスして、ホーム画面に追加するだけ。 | アプリストアからダウンロード・インストールが必要。 |
| 開発コスト | 1つのWebサイトを作るだけでOK。 | iOS用とAndroid用、それぞれ別々に開発する必要がある。 |
| 容量 | 非常に軽い。ほとんど容量を使わない。 | 容量が大きい。スマホのストレージを圧迫することがある。 |
| オフライン | 一部の情報(一度見たページなど)は、オフラインでも見られる。 | オフラインでもほぼ全ての機能が使える。 |
| プッシュ通知 | 通知を受け取ることができる。 | 通知を受け取ることができる。 |
| できること | Webブラウザでできることに限られる。カメラやGPSなど、一部の機能は使える。 | スマホのあらゆる機能(AR、センサーなど)をフル活用できる。 |
PWAの作り方
PWAは特別なプログラミング言語ではなく、既存のWeb技術を拡張して作ります。PWA作成のために必要なのは以下の4つです。
- Webサイト
- HTTPSの利用
- Service Workerの実装(sw.js)
- マニフェストファイルの作成(manifest.json)
Webサイト
HTML、CSS、JavaScriptを使って、通常のWebサイトを構築します。これが、PWAの基礎となる部分です。
HTTPSの利用
PWAの多くの機能(特にService Worker)は、セキュリティ上の理由からHTTPS(SSL/TLS暗号化)接続が必須です。
Service Workerの実装(sw.js)
PWAの最も重要な要素が「Service Worker」です。 これは、ブラウザとサーバーの間で動作するスクリプトで、主に以下の役割を担います。
- キャッシュ管理
一度アクセスしたページのデータ(HTML、CSS、画像など)をブラウザに保存(キャッシュ)し、オフラインでも表示できるようにします。 - オフライン対応
ネットワーク接続がない場合でも、キャッシュしたデータを使ってユーザーにコンテンツを提供します。 - プッシュ通知
サーバーからの通知をユーザーに送信します。
このService Workerのファイル(sw.js)を作成し、Webページから登録するコードを記述します。
Service Workerについての詳しい解説は下記をご参考ください。
マニフェストファイルの作成(manifest.json)
Web App ManifestというJSON形式のファイル(manifest.json)を作成します。このファイルには、PWAがアプリのように振る舞うための設定情報が含まれています。
- アプリ名: ホーム画面に表示される名前。
- アイコン: ホーム画面に表示されるアイコンの画像。
- 起動時のURL: PWAを起動したときに開く最初のページ。
- 表示モード: ブラウザのUI(アドレスバーなど)を非表示にして全画面表示にする設定。
このマニフェストファイルをHTMLのheadタグ内でリンクします。
manifest.jsonについての詳しい解説は下記をご参考ください。
> manifest.jsonとは何か?用途や使えるプロパティの一覧,メタデータやマニフェストについて実例でわかりやすく解説!
以上の4つのステップを踏むことで、既存のWebサイトをPWAとして機能させることができます。開発者向けのツール(Lighthouseなど)を使えば、PWAの要件が満たされているかを確認できます。
マニフェストファイルのファイル名には「manifest.json」、サービスワーカーのファイル名には「sw.js」が使われることが多いですが、HTMLでのlinkタグやscriptタグ内での読込名を変更すれば、別のファイル名も使用できます。
PWAの具体例(WordPressサイトをPWA化してみよう!)
PWAの具体例として、WordPressサイトをPWA化する事例を紹介します。
プラグインでもPWA化できますが、ここではコードで紹介します。
なお、既にサイトはありhttps://なっていることが前提です。
マニフェストファイルの作成(manifest.json)
まずは、manifest.jsonを作り、WordPress のテーマディレクトリ直下や /wp-content/themes/your-theme/ に保存します。
{
"name": "Prograshi PWA App",
"short_name": "Prograshi APP",
"start_url": "/",
"display": "standalone",
"background_color": "#9025C3",
"theme_color": "#ffffff",
"orientation": "portrait",
"icons": [
{
"src": "/wp-content/uploads/2021/06/cropped-7ae63ebcd302897cd8cbf97b5f2a73b2.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/wp-content/uploads/2021/06/cropped-7ae63ebcd302897cd8cbf97b5f2a73b2.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
なぜ、iconsが2つ記述してあるのか?については下記記事をご参考ください。
manifest.jsonについての詳しい解説は下記をご参考ください。
> manifest.jsonとは何か?用途や使えるプロパティの一覧,メタデータやマニフェストについて実例でわかりやすく解説!
Service Worker(sw.js)の作成
続いて、Service Worker用のsw.jsを作成しルート直下に配置します。
const CACHE_NAME = "pwa-cache-v1";
const urlsToCache = [
"/",
"/wp-content/themes/cocoon-my-child/style.css",
];
// インストール時にキャッシュ
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(urlsToCache);
})
);
});
// リクエストをキャッシュから返す
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
if (response) {
return response; // キャッシュにあればそれを返す
}
return fetch(event.request).then((res) => {
// レスポンスをキャッシュに追加
return caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, res.clone());
return res;
});
});
})
);
});
// 古いキャッシュを削除
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((name) => {
if (name !== CACHE_NAME) {
return caches.delete(name);
}
})
);
})
);
});
Service Workerをサイト全体に適用させたい場合、sw.js を ドメイン直下(/sw.js) に置きます。
WordPress のテーマフォルダだと /wp-content/themes/…/sw.js になり、スコープがそのフォルダ配下に限定されてしまいます(sw.jsを置いたフォルダ以下のみ制御可能)。
ブラウザのセキュリティ仕様 でJS 側から勝手にスコープを広げることはできません。
※mafifest.jsonの設置場所は自由です
ランタイムキャッシュ
上記の場合、変数urlsToCacheで指定したファイルのみがインストール時にキャッシュされます(プリキャッシュ)。ここで指定するのはよく使う静的ファイル(CSS、JS、ロゴ画像など)が一般的です。
その他のページはアクセスしたときにキャッシュする仕様(ランタイムキャッシュ)にしています。
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
if (response) {
return response; // キャッシュにあればそれを返す
}
return fetch(event.request).then((res) => {
// レスポンスをキャッシュに追加
return caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, res.clone());
return res;
});
});
})
);
});他のページはキャッシュさせない
記事ページもオフラインで読めるようにしたい場合は上記のランタイムキャッシュにする必要があります。
ですが、最低限の CSS/JS をキャッシュして、オンライン前提で高速化するという用途であれば、インストール時に指定したファイルのみをキャッシュさせる方法も有効です。
その場合は、fetchの処理を以下のように変更します。
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});manifest.jsonの読み込み
作成したmanifest.jsonを読み込ませます。通常headタグ内でlinkタグで指定します。
SPAではないので、どのページからアクセスしてもmanifest.jsonを読み込めるよう全ページで読み込みます。
functions.phpに以下を記述します。
function add_pwa_manifest() {
echo '<link rel="manifest" href="' . get_stylesheet_directory_uri() . '/manifest.json">';
echo '<meta name="theme-color" content="#ffffff">';
}
add_action('wp_head', 'add_pwa_manifest');manifest.jsonを子テーマに配置した場合は、get_stylesheet_directory_uri関数を使います。
(※get_template_directory_uri関数は、子テーマ使用中に親テーマのURIを取得するものです)
meta name=”theme-color”はオプション
なお、<meta name="theme-color">は、ブラウザでWebサイトを普通に開いているときのツールバーやアドレスバーの色を指定するもので、必須ではありません。
PWAで起動したときの見た目と、ブラウザでアクセスしたときの見た目を統一するために使います。
文字色(アイコンやステータスバーのテキスト色)は、ブラウザや OS が背景色に応じて自動的に白/黒を切り替える仕組みになっています。
- theme-color: #000000(黒背景)なら → OS が自動で白文字にする
- theme-color: #ffffff(白背景)なら → OS が自動で黒文字にする
これはユーザーの視認性(アクセシビリティ)を確保するために固定されています。
Service Worker(sw.js)の読み込み
Service Workerのsw.jsファイルは、通常フッターのscriptタグで読み込みます。
ですが、WordPressでルート直下に配置した場合は以下のように読み込みます。
// ルート直下に配置したsw.jsを登録
function register_service_worker() {
?>
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", function() {
navigator.serviceWorker.register("<?php echo home_url('/sw.js'); ?>")
.then(function(registration) {
console.log("Service Worker 登録完了: ", registration.scope);
})
.catch(function(err) {
console.error("Service Worker 登録失敗: ", err);
});
});
}
</script>
<?php
}
add_action('wp_footer', 'register_service_worker');補足|フッターにscriptタグで読み込む場合
sw.jsをWordPressのテーマフォルダ内に配置した場合は、wp_footerフックで読み込みます。
function register_service_worker() {
?>
<script>
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("<?php echo get_template_directory_uri(); ?>/sw.js")
.then(function(reg) {
console.log("Service Worker 登録完了", reg);
})
.catch(function(err) {
console.error("Service Worker 失敗", err);
});
}
</script>
<?php
}
add_action('wp_footer', 'register_service_worker');
以上でWordPressサイトのPWA化は完了です。
PWAのインストール
作成したPWAを早速、インストールしてみます。
PCでChromeを開き、サイトを開きます。PWA化に成功している場合、アドレスバーにインストールアイコンが表示されます。

クリックすると「アプリのインストール」が表示されます。

デスクトップ上に指定したアイコンがショートカットとして自動で保存されます。

機能しているか確認する
Chromeの開発ツールを使うことで、manifest.jsonとsw.jsが共に正しく機能しているか確認することができます。
manifest.json
「Application → manifest」と進みます。
すると詳細が表示されます。

manifest.jsonはPWAが上手く機能していなくても、manifest.jsonファイルさえ読み込めていれば表示されます。
sw.js
「Application → Service workers」と進みます。
PWAが機能していれば、ここに表示されます。

オフラインで動作しているか?
PWAの最も重要な点といえるオフラインでもWebサイトが見れるか確認してみます。
PWAをデスクトップに登録してすぐはオフラインにすると、指定した背景色の画面のみになってしまい、コンテンツを表示することができませんでした。
ですが、少し時間を置くと無事にオフラインでもコンテンツを読み込めるようになりました。

ここで紹介したService Workerのキャッシュ戦略は、ランタイムキャッシュです。
このため、ページにアクセスするという動きをすることで初めてキャッシュされるようになります。
キャッシュが上手く行っているかどうかは開発ツールの「Application → Storage」で確認できます。

大量のブログサイトを全ページキャッシュする仕様にすると、キャッシュを大量に消費するので、不要な場合はやめておきましょう。


