はじめに
最近PythonのみでWebアプリを作るためのライブラリが増えてますね。
普段Streamlitを利用しているのですが、今回はReflexを使って作ったアプリをPWA化する方法を教えてもらったので共有します。
※デフォルトページをPWA化したサンプル
やり方
1.assetsディレクトリに以下のファイルを格納する。
- manifest.json
- service-worker.js
- 各サイズのアイコン
※以下のサイトでmanifest.json
の生成とアイコン画像の変換ができて便利です。
補足
reflex init
コマンドを実行するとassets
というディレクトリができていると思います。これはNext.js用のディレクトリである.web
の中のpublic
にコピーされるようです。
manifest.json
{
"name": "My PWA",
"short_name": "PWA",
"start_url": ".",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#ffffff",
"description": "My awesome Progressive Web App!",
"icons": [
{
"src": "icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
service-worker.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('static-cache-v1').then(cache => {
return cache.addAll([
'/',
'/manifest.json',
'/icon-192x192.png',
'/icon-512x512.png'
// キャッシュが必要なものを追記してください
]);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});
2.rx.Appのhead_componentsを指定する。
app.py
app = rx.App(
head_components=[
rx.el.link(rel="manifest", href="/manifest.json"),
rx.script("""
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, error => {
console.log('ServiceWorker registration failed: ', error);
});
});
}
"""),
]
おわりに
Reflexはフロントエンド(Next.js)とバックエンド(FastAPI)が完全に分かれて管理しているのでこういった拡張も行いやすそうですね。
※最初headにmanifest.jsonをlinkする方法がわからず、無理やりJavaspriptで追加していたのですが、DiscussionのQAで質問してみたらものの数分でメンテナーの方が回答してくれました。活発に開発も行われているようなので今後の発展に期待です!