PWA berbagi codebase yang sama dengan ERP web, sehingga biaya pengembangan dan pemeliharaannya jauh lebih rendah dibanding membangun aplikasi iOS dan Android secara terpisah. Pembaruan langsung tersedia saat pengguna membuka aplikasi tanpa proses persetujuan toko aplikasi. Untuk bisnis Indonesia yang tidak memiliki tim atau anggaran pengembangan mobile tersendiri, PWA adalah jawaban praktisnya.
Kemampuan offline mengandalkan dua API browser: Service Worker yang mencegat permintaan jaringan dan melayani respons dari cache saat jaringan tidak tersedia, serta IndexedDB, database sisi klien tempat pekerja lapangan dapat membaca dan menulis catatan meski tanpa koneksi. Ketika konektivitas pulih, service worker menyinkronkan data IndexedDB lokal kembali ke server.
Strategi sinkronisasi bergantung pada sensitivitas data. Pendekatan 'last write wins' dapat diterima untuk data rendah risiko seperti pembaruan lokasi GPS atau catatan waktu. Untuk data transaksional seperti konfirmasi pengiriman atau bukti pembayaran, operasi harus dimasukkan ke antrean secara berurutan agar konflik tidak terjadi karena dua pengguna mengubah catatan yang sama saat offline.
Dataset offline harus sekecil mungkin — hanya yang dibutuhkan untuk pekerjaan hari itu. Seorang teknisi lapangan membutuhkan perintah kerja yang ditugaskan hari itu, informasi alamat dan kontak pelanggan yang relevan, serta katalog produk atau layanan untuk domain mereka. Mereka tidak memerlukan seluruh database pelanggan atau semua faktur historis. Membatasi dataset menjaga IndexedDB tetap terkelola dan mengurangi kompleksitas sinkronisasi.
PWA kesulitan dengan integrasi hardware seperti pemindai Bluetooth, pembaca NFC, dan printer khusus — skenario tersebut memerlukan aplikasi native atau React Native. Antarmuka yang sangat kompleks yang diharapkan terasa sepenuhnya native juga tidak cocok. Untuk pekerja lapangan Indonesia yang kebutuhan utamanya adalah mencatat pekerjaan, mengirimkan formulir, dan mengakses data referensi, PWA mencakup sekitar 95% kasus penggunaan dengan biaya jauh lebih rendah dari aplikasi native.
Pekerja lapangan — teknisi, pengemudi pengiriman, staf gudang di lokasi terpencil, tenaga penjual yang mengunjungi pelanggan — selalu menjadi mil terakhir adopsi ERP. Mereka perlu mencatat perintah kerja, merekam pengiriman, memeriksa inventaris, dan mengirimkan formulir dari lapangan. Tetapi pekerja lapangan Indonesia sering beroperasi di area dengan konektivitas yang buruk atau terputus-putus. Progressive Web Apps (PWA) memecahkan ini dengan elegan.
Untuk alat pekerja lapangan internal, PWA menawarkan keseimbangan kemampuan dan biaya yang tepat. PWA adalah aplikasi web yang berperilaku seperti aplikasi native: dapat ditambahkan ke layar beranda, menerima notifikasi push, bekerja offline, dan berjalan layar penuh. Biaya pengembangan dan pemeliharaan adalah sebagian kecil dari pengembangan aplikasi native karena menggunakan codebase yang sama dengan ERP web.
Kemampuan offline dalam PWA dibangun di atas dua API browser. Service Workers: file JavaScript yang berjalan independen dari halaman, mencegat permintaan jaringan, dan melayani respons yang di-cache saat jaringan tidak tersedia. IndexedDB: database sisi klien yang menyimpan data terstruktur di browser. Pekerja lapangan dapat membaca catatan dan menulis catatan baru bahkan saat offline.
Sinkronisasi data offline menciptakan konflik ketika catatan yang sama dimodifikasi baik secara offline maupun di server sebelum sinkronisasi. Strategi sinkronisasi Anda harus mendefinisikan cara konflik diselesaikan. Untuk sebagian besar kasus penggunaan ERP lapangan, strategi 'last write wins' dapat diterima untuk data rendah risiko. Untuk data transaksional, sinkronisasi harus mengantrekan operasi secara berurutan.
PWA Field ERP Architecture — Offline-First
ONLINE MODE: OFFLINE MODE:
┌──────────────────────────┐ ┌──────────────────────────┐
│ Field Worker Device │ │ Field Worker Device │
│ │ │ │
│ PWA App Shell (cached) │ │ PWA App Shell (from cache)│
│ │ │ │ │ │
│ Service Worker │ │ Service Worker │
│ ├─ fetch interceptor │ │ ├─ serves from cache │
│ ├─ cache strategy │ │ ├─ queues writes │
│ └─ sync queue │ │ └─ Background Sync API │
│ │ │ │ │ │
│ IndexedDB (local) ◄────┐│ │ IndexedDB (local) │
│ ├─ today's work orders ││ │ ├─ reads: all available │
│ ├─ customer data ││ │ └─ writes: queued sync │
│ └─ pending sync queue ││ │ │
└───────────┬──────────────┘│ └──────────┬────────────────┘
│ (sync) │ │ (reconnect)
▼ │ ▼
┌──────────────────────────┐│ ┌──────────────────────────┐
│ ERP Backend (NestJS) ││ │ Background Sync fires │
│ POST /api/work-orders ││ │ Service Worker processes │
│ GET /api/sync/today ││ │ queued operations in order│
│ PATCH /api/deliveries │└────────│ Conflict resolution runs │
└──────────────────────────┘ └──────────────────────────┘
Offline data set per field worker (downloaded each morning):
• Assigned work orders for today
• Customer address + contact data for those work orders
• Product/service catalog for their service category
• Reference data (fault codes, resolution types)
Size estimate: ~500KB per worker — fast sync on any connectionDari pengalaman saya sebagai konsultan ERP lepas: rancang dataset offline sesekecil mungkin. Teknisi lapangan membutuhkan perintah kerja yang ditugaskan kepada mereka hari ini, informasi alamat dan kontak pelanggan, dan katalog produk/layanan untuk domain mereka. Mereka tidak memerlukan seluruh database pelanggan. Batasi dataset offline ke apa yang dibutuhkan untuk pekerjaan hari itu.
PWA memerlukan tiga hal agar dapat diinstal: Web App Manifest (file JSON yang mendefinisikan nama aplikasi, ikon, mode tampilan, dan URL awal), Service Worker terdaftar, dan HTTPS (diperlukan agar service worker berfungsi). Di Android, browser secara otomatis akan meminta 'Tambahkan ke Layar Beranda'. Di iOS, pengguna harus menggunakan menu Share secara manual.
// service-worker.ts — ERP Field PWA
const CACHE_VERSION = 'erp-field-v1';
const APP_SHELL = ['/offline.html', '/manifest.webmanifest'];
// Cache app shell on install
self.addEventListener('install', (event: ExtendableEvent) => {
event.waitUntil(
caches.open(CACHE_VERSION).then(cache => cache.addAll(APP_SHELL))
);
});
// Network-first for API calls; cache-first for static assets
self.addEventListener('fetch', (event: FetchEvent) => {
const { request } = event;
if (request.url.includes('/api/')) {
// API: try network, fallback to IndexedDB data
event.respondWith(
fetch(request).catch(() => {
// Network unavailable — queue the write for later
if (request.method !== 'GET') {
queueOfflineAction(request.clone());
return new Response(
JSON.stringify({ queued: true, message: 'Saved offline, will sync when connected' }),
{ headers: { 'Content-Type': 'application/json' } }
);
}
// For GETs, try cached data
return caches.match(request) ?? Response.error();
})
);
} else {
// Static assets: cache-first
event.respondWith(
caches.match(request).then(cached => cached ?? fetch(request))
);
}
});
// Background sync — fires when connection is restored
self.addEventListener('sync', (event: SyncEvent) => {
if (event.tag === 'erp-sync-queue') {
event.waitUntil(processOfflineQueue());
}
});
async function processOfflineQueue() {
const db = await openIndexedDB('erp-offline', 1);
const queue = await db.getAll('sync-queue');
for (const item of queue) {
try {
await fetch(item.url, { method: item.method, body: item.body });
await db.delete('sync-queue', item.id);
} catch {
break; // Still offline — stop processing, retry next sync
}
}
}
// Web App Manifest (public/manifest.webmanifest)
const manifest = {
name: "Commsult Field ERP",
short_name: "Field ERP",
display: "standalone",
background_color: "#0f172a",
theme_color: "#3b82f6",
start_url: "/field",
icons: [
{ src: "/icons/icon-192.png", sizes: "192x192", type: "image/png" },
{ src: "/icons/icon-512.png", sizes: "512x512", type: "image/png" }
]
};Notifikasi push PWA memungkinkan ERP berkomunikasi dengan pekerja lapangan tanpa mengharuskan mereka membiarkan aplikasi tetap terbuka. Kasus penggunaan: perintah kerja baru telah ditugaskan, rute pengiriman telah berubah, pelanggan telah dihubungi untuk mengonfirmasi janji temu, inventaris di lokasi pengambilan telah diperbarui.
PWA offline menyimpan data di perangkat. Jika perangkat pekerja lapangan hilang atau dicuri, data yang di-cache — termasuk informasi pelanggan, harga, detail perintah kerja — berpotensi dapat diakses. Terapkan persyaratan enkripsi tingkat perangkat dan kemampuan penghapusan jarak jauh sebelum men-deploy PWA lapangan yang berkemampuan offline.
Jaringan seluler Indonesia sangat bervariasi berdasarkan lokasi. PWA lapangan Anda harus berkinerja pada koneksi 3G di area pedesaan. Optimalkan untuk kinerja jaringan: kompres semua gambar (format WebP), lazy-load sumber daya yang tidak kritis, gunakan HTTP/2 atau HTTP/3 di server, dan terapkan antrean permintaan dalam service worker yang mem-batch operasi sinkronisasi.
PWA sangat baik untuk alur kerja lapangan berbasis formulir. Ini berjuang dengan integrasi hardware (pemindai Bluetooth, pembaca NFC, printer khusus) — ini memerlukan aplikasi native atau React Native. Untuk pekerja lapangan Indonesia yang kebutuhan utamanya adalah mencatat pekerjaan, mengirimkan formulir, dan mengakses data referensi, PWA mencakup 95% kasus penggunaan dengan sebagian kecil biaya aplikasi native.