Khi phát triển ứng dụng chạy song song trên Web (Next.js) và Mobile (React Native/Expo) trong một monorepo, việc đảm bảo trải nghiệm người dùng khi mất kết nối mạng là thách thức lớn. Dưới đây là quy trình thực tế đã áp dụng thành công trong nhiều dự án sản phẩm. 1. Xác định dữ liệu cần offline - Phân loại API thành "critical" (danh sách sản phẩm, giỏ hàng, thông tin người dùng) và "non‑critical" (báo cáo, lịch sử tìm kiếm). - Chỉ cache dữ liệu critical bằng IndexedDB (Web) hoặc AsyncStorage/MMkv (Mobile). 2. Triển khai Service Worker cho Web - Sử dụng Workbox để precache shell ứng dụng và runtime cache các request GET đến API critical. - Cấu hình strategy "stale‑while‑revalidate" để hiển thị dữ liệu cũ ngay lập tức, sau đó cập nhật khi có mạng. 3. Quản lý hàng đợi thay đổi (mutation queue) - Mọi hành động ghi (thêm giỏ hàng, cập nhật hồ sơ) được đẩy vào một queue lưu trữ cục bộ. - Queue lưu trữ: {action, payload, timestamp, retryCount}. - Khi online, một background sync (Web) hoặc NetInfo listener (Mobile) sẽ flush queue theo thứ tự FIFO, xử lý conflict bằng version vector hoặc server‑side timestamp. 4. Đồng bộ hai chiều với TanStack Query + Persist Query Client - Cấu hình queryClient.persistQueryClient để tự động hydrate cache khi khởi động. - Sử dụng mutation.onMutate để optimistic update, onError để rollback, onSettled để invalidate queries liên quan. 5. Xử lý xung đột và hợp nhất - Server trả về ETag/Last‑Modified; client so sánh với bản local trước khi ghi đè. - Nếu xung đột, hiển thị dialog cho người dùng chọn "Giữ bản cục bộ", "Ghi đè bởi server" hoặc "Hợp nhất thủ công". 6. Kiểm thử tự động - Viết test tích hợp với MSW (Mock Service Worker) mô phỏng offline/online. - Trên mobile dùng Detox để bật/tắt chế độ máy bay và kiểm tra queue flush. 7. Giám sát và logging - Gửi sự kiện "offline_action_queued", "sync_success", "sync_failed" đến hệ thống logging thống nhất (ví dụ Sentry). - Dashboard hiển thị tỷ lệ hành động offline thành công/thất bại để cải thiện UX. Lời khuyên áp dụng ngay: - Bắt đầu từ một feature nhỏ (giỏ hàng) để kiểm chứng pipeline offline trước khi mở rộng. - Đặt TTL cho cache (ví dụ 7 ngày) để tránh dữ liệu lỗi thời. - Luôn version hóa schema queue để migration dễ dàng khi thay đổi cấu trúc dữ liệu. Với cách tiếp cận này, ứng dụng giữ được khả năng phản hồi tức thì, giảm tỷ lệ bỏ đơn hàng khi mạng yếu và đơn giản hóa bảo trì nhờ chia sẻ logic giữa Web và Mobile trong cùng monorepo.