🦔
Remix(Reactフレームワーク)にServiceWorkerを追加してPWA化する方法
RepitanにServiceWorkerを入れたので備忘録として残します。
NuxtのときはPWAとかほぼ自動でやってくれてたのですが、Remixの場合手動でやらないといけませんでした。
どうしてPWA化するの?
Remixはデフォルトで高速ですが、インストール可能なPWAを構築したり、アプリをオフラインで動作させたり、Remixアプリケーションの負荷を可能な限り最適化したい場合はServiceWorkerがお手軽な手段になってきます。
個人的には「ホーム画面に追加」機能と、ブラウザのメニューバーなどが非表示になってくれる点がとても気に入っています。
ServiceWorkerを追加する手順
- manifest.jsonを作成
public/manifest.json
{
"name": "Repitan",
"short_name": "Repitan",
"icons":[
{
"src":"/icons/icon-72x72.png",
"sizes":"72x72",
"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_152.png",
"sizes":"152x152",
"type":"image/png"
},{
"src":"/icons/icon_192.png",
"sizes":"192x192",
"type":"image/png"
},{
"src":"/icons/icon_384.png",
"sizes":"384x384",
"type":"image/png"
},{
"src":"/icons/icon_512.png",
"sizes":"512x512",
"type":"image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone",
"scope": "/",
"start_url": "/",
"lang": "ja"
}
上記の内容は最低限なものになるので、その他にも色々設定したい場合はMDNのウェブアプリマニフェストを参考にすると良さそうです
- manifest.jsonを読み込む
app/root.tsx
import {
Links
} from "remix";
export const links = () => {
return [
{ rel: "manifest", href: '/manifest.json' },
]
}
- sw.jsを作成
public/sw.js
self.addEventListener("fetch", (event) => {
let url = new URL(event.request.url);
let method = event.request.method;
if (method.toLowerCase() !== "get") return;
if (
url.pathname.startsWith("/images/") ||
url.pathname.startsWith("/json/") ||
url.pathname.startsWith("/styles/")
) {
event.respondWith(
caches.open("assets").then(async (cache) => {
let cacheResponse = await cache.match(event.request);
if (cacheResponse) return cacheResponse;
let fetchResponse = await fetch(event.request);
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
})
);
}
return;
});
- entry.client.tsxにsw.jsを読み込ませて完了
app/entry.client.tsx
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("/sw.js");
});
}
Discussion