PWA Mandiri (Workbox) & Mesin Ekspor Multi-Format
Kombinasi Service Worker yang di-bundle secara lokal untuk ketahanan akses offline dan generator laporan keuangan server-side dalam format CSV, JSON Backup, serta HTML-PDF siap cetak.
Membaca sekitar 2 menit
Kombinasi Service Worker yang di-bundle secara lokal untuk ketahanan akses offline dan generator laporan keuangan server-side dalam format CSV, JSON Backup, serta HTML-PDF siap cetak.
Script build-sw.js membungkus service worker dengan 4 strategi caching Workbox sebelum next build berjalan, sementara endpoint ekspor menyatukan pemasukan dan pengeluaran menjadi file unduhan atau halaman cetak berdesain khusus.
Alih-alih membebani server dengan headless browser untuk membuat PDF, fitur ekspor menghasilkan dokumen HTML mandiri lengkap dengan aturan CSS @media print dan print-color-adjust yang ringan serta presisi saat dicetak.
Masalahnya dulu
Pengguna sering membuka aplikasi pencatat keuangan di ponsel saat sedang di kasir atau perjalanan dengan sinyal internet yang tidak stabil. Di sisi lain, pada akhir bulan atau akhir tahun, mereka membutuhkan laporan keuangan resmi yang bisa diolah di spreadsheet (CSV), disimpan sebagai cadangan data utuh (JSON Backup), atau dicetak sebagai dokumen PDF yang rapi.
Bundling Service Worker Lokal & Generator Laporan Server-Side
Untuk kebutuhan PWA, MyPocket tidak memuat Workbox dari CDN luar, melainkan mem-bundle sw.src.js secara lokal ke dalam public/sw.js menggunakan script build-sw.js (workbox-build injectManifest) yang otomatis berjalan sebelum next build. Service worker ini membagi strategi cache menjadi empat jalur: CacheFirst untuk gambar/font (30 hari), StaleWhileRevalidate untuk chunk statis Next.js (7 hari), serta NetworkFirst dengan batas timeout untuk API (10 detik) dan navigasi halaman HTML (5 detik). Sementara itu, kebutuhan laporan ditangani oleh satu endpoint terpadu yang melayani tiga format sekaligus: CSV, JSON, dan laporan HTML-PDF siap cetak.
Aplikasi keuangan yang matang harus tetap responsif saat jaringan goyah dan selalu siap menyerahkan data milik pengguna dalam format apa pun saat diminta.
Implementasi di ngodingan ini
Berikut adalah konfigurasi strategi caching pada service worker serta potongan logika pembuatan CSV di endpoint ekspor:
// 1. Service Worker: NetworkFirst dengan fallback cache untuk API
registerRoute(
({ url }) => url.pathname.startsWith("/api/"),
new NetworkFirst({
cacheName: "mypocket-api-v1",
networkTimeoutSeconds: 10,
plugins: [new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 5 * 60 })],
})
);
// 2. Export Endpoint: pembentukan CSV dengan escaping tanda kutip
if (format === "csv") {
const header = "Type,Category,Amount,Date,Notes\n";
const rows = all.map((r) =>
`${r.kind},"${r.category}",${r.amount},${new Date(r.date).toLocaleDateString("en-GB")},"${(r.note || "").replace(/"/g, '""')}"`
).join("\n");
return new NextResponse(header + rows, {
headers: {
"Content-Type": "text/csv; charset=utf-8",
"Content-Disposition": `attachment; filename="mypocket-${bankName}-export.csv"`,
},
});
}Jebakan dan detail yang harus dijaga
- Menjaga pipeline build tetap tahan banting di build-sw.js: jika proses injectManifest mengalami kegagalan di environment tertentu, script menangkap error dan keluar dengan process.exit(0) agar tidak menggagalkan keseluruhan proses next build.
- Melakukan escaping tanda kutip ganda pada ekspor CSV (.replace(/"/g, '""')) agar catatan transaksi yang mengandung tanda kutip atau koma tidak merusak struktur kolom saat dibuka di Microsoft Excel atau Google Sheets.