アクセスするとメガ単位でたくさんの画像を読み込むサービスがありまして・・。
リファクタによって、動的に必要な画像だけを読み込むように改修はしたけど、それでも回遊するとサイズがすごいことになる。
これをなんとかするならServiceWorkerしかない!というわけで。
Workbox
最初は0から手書きしようかと思ったけど、ちょっとやり始めただけであれこれ面倒なことがわかったので、先人に頼ることにした。
ご丁寧に、こういうことがやりたいんじゃろ?っていうのがガイドの中にあって、そうそうこれこれ〜って感じだった。
事前キャッシュではなく、あくまでランタイムでのキャッシュがしたかったので、これ。
import { CacheableResponsePlugin } from "workbox-cacheable-response"; import { CacheFirst } from "workbox-strategies"; import { ExpirationPlugin } from "workbox-expiration"; import { registerRoute } from "workbox-routing"; registerRoute( ({ request }) => request.destination === "image", new CacheFirst({ cacheName: "images", plugins: [ new CacheableResponsePlugin({ statuses: [0, 200], }), new ExpirationPlugin({ maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days purgeOnQuotaError: true, }), ], }), );
拡張子問わず、画像に対するリクエストをキャッシュする設定。
- ちゃんとステータスコード200で取得できたものだけ
- キャッシュできる容量を超えたら自動パージ
というコードがこれだけで書ける。
我々が欲しかったのはServiceWorkerではなく、Workboxだったのじゃよ・・。
Rollupでプラグインなしでビルド
Workboxの使い方を探すと、PWA用途にプラグインで事前キャッシュ仕込めて簡単☆みたいなのばっか出てくる。
まぁ普通にアプリのコードと同じようにRollupで設定書いて、ビルドすればいいだけなので、特筆すべきことはない・・と思ったら、ちょっとハマった。
最終的な`rollup.config.js`はこんな感じ。
const production = process.env.NODE_ENV === "production"; export default { input: "src/sw.js", output: { format: "iife", name: "sw", file: "service-worker.js" }, plugins: [ resolve(), replace({ "process.env.NODE_ENV": production ? "'production'" : "''", }), production && terser() ], }
まず最初の注意点は、`format: iife`にするところ。
次に、`process.env`にアクセスするコードがWorkbox側にあるので、それを処理しないと`process is not defined`って`register()`時にエラーになるところ・・。
(そんなコードを公開するんじゃないよという気持ち)
あとは使ってるモジュールたちをいつもどおり`npm install`すれば、ビルドできる。