こんにちは、JS2IIUです。
この記事では、Streamlitで開発したアプリをProgressive Web App (PWA) に変換する方法を、技術的な手順と具体的なコード例付きで紹介します。
PWAは、Webアプリケーションに**ネイティブアプリに近い機能(インストール、オフライン対応など)**を追加できる技術です。Streamlit単体ではPWAに未対応ですが、外部ツールとの組み合わせで実現可能です。
PWAとは?そのメリットと制限
Progressive Web App (PWA) は、Web技術(HTML/CSS/JavaScript)をベースにしつつ、ネイティブアプリのような体験を提供する手法です。
主な特徴:
- オフライン利用可能(キャッシュ機能)
- インストール可能(ホーム画面に追加)
- プッシュ通知やバックグラウンド同期(高度な設定)
メリット:
- アプリストア不要でインストール可能
- クロスプラットフォーム対応
- ネットワークに依存しにくい
デメリット:
- 一部ブラウザ(iOS Safariなど)の制限あり
- ネイティブAPIに完全アクセスできない
なぜStreamlitアプリをPWA化するのか?
Streamlitは本来、データ可視化や業務ツール向けのPython製Webアプリを簡単に作れるライブラリですが、モバイルデバイスからの使用を考慮すると、インストール可能なUI体験が求められます。
ユースケース例:
- 展示会デモアプリ:オフライン状態でも利用可能にしたい
- 営業ツール:顧客先でインターネットが不安定でも動作保証がほしい
- 教育教材:学生がスマホやタブレットからアクセス可能にしたい
StreamlitアプリをPWAにするための技術スタック
Streamlit自体はPWA非対応なので、Streamlitアプリをフロントとして表示するPWA対応HTMLページを作成します。
構成イメージ:
PWAフロント(HTML + manifest.json + service-worker.js)
│
└─ Streamlitアプリ(localhost:8501または外部URLにデプロイ)手順1:Streamlitアプリの起動と公開
まずは、既存のStreamlitアプリをローカルで起動するか、外部サービスにデプロイします。
streamlit run app.py例)ローカルで起動 → http://localhost:8501
外部デプロイ例:Streamlit Community CloudやRender.comなど
手順2:PWAフロントを作成する
Streamlitアプリを埋め込むHTMLページを作成し、そこにPWAに必要なマニフェストとサービスワーカーを追加します。
📄 index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Streamlit PWA</title>
<link rel="manifest" href="manifest.json" />
<script>
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js");
}
</script>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
iframe {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe src="http://localhost:8501" title="Streamlit App"></iframe>
</body>
</html>手順3:マニフェストファイルの作成
📄 manifest.json
{
"short_name": "StreamlitPWA",
"name": "My Streamlit PWA App",
"start_url": ".",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0f4a73",
"icons": [
{
"src": "icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}※ icon-192.png と icon-512.png は公開ディレクトリに用意してください。
手順4:サービスワーカーの実装
📄 service-worker.js
const CACHE_NAME = 'streamlit-pwa-v1';
const urlsToCache = [
'/',
'/index.html',
'/manifest.json',
'/icon-192.png',
'/icon-512.png'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});手順5:ローカルWebサーバーでPWAをホストする
HTMLと関連ファイルをpwa/ディレクトリに配置し、簡易HTTPサーバーで配信します。
cd pwa
python -m http.server 8080その後、ブラウザで http://localhost:8080 にアクセスすると、StreamlitアプリがPWAとして表示されます。
ホーム画面への追加やUXの工夫
- PWAインストールのプロンプトはChromeで自動表示されます(条件:HTTPS + manifest + service worker)。
- インストール誘導用にUIを工夫するなら、
beforeinstallpromptイベントを使います。
例: インストールボタンの実装
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
document.getElementById('install-btn').style.display = 'block';
});
document.getElementById('install-btn').addEventListener('click', () => {
deferredPrompt.prompt();
});パフォーマンスチューニングとトラブル対処法
よくある問題と対処法
| 問題 | 解決策 |
|---|---|
| キャッシュが更新されない | キャッシュ名(CACHE_NAME)にバージョン番号をつける |
| Streamlitが外部埋め込みを拒否 | st.set_page_config()でiframe対応を確認 |
| HTTPSじゃないのでPWA化不可 | ローカルでは ngrok や Localhost.run でHTTPSトンネルを活用 |
🔗 参考リンク
- Google Developers – PWA
- Streamlit Documentation
- MDN Web Docs – Service Workers
- Web.dev – Make your PWA installable
最後まで読んでいただきありがとうございました。


コメント