1. 16:52 14/10/2026
Trong các dự án monorepo chạy song song Next.js (web) và React Native (mobile), việc quản lý dữ liệu tạm thời (cache) thường bị phân mảnh: mỗi nền tảng tự triển khai SWR, React Query hay AsyncStorage riêng biệt. Điều này dẫn đến trùng lặp logic, khó đồng bộ hóa trạng thái offline và tăng dung lượng bundle.
Giải pháp là xây dựng một Cache Layer chung ở cấp package shared, sử dụng interface trừu tượng để mỗi nền tảng cung cấp implementation phù hợp (IndexedDB cho web, SQLite/AsyncStorage cho native). Dưới đây là các bước chính:
- Xác định interface CacheAdapter với các phương thức get, set, delete, clear, và subscribe để lắng nghe thay đổi.
- Viết adapter WebCacheAdapter dùng idb (IndexedDB wrapper) và NativeCacheAdapter dùng @react-native-async-storage/async-storage kết hợp với expo-sqlite cho truy vấn phức tạp.
- Đăng ký adapter tương ứng tại entry point của từng app thông qua Dependency Injection (ví dụ: dùng React Context hoặc thư viện inversify).
- Tạo hook useSharedCache(key, options) trong package shared, bên trong gọi adapter hiện tại. Hook trả về data, loading, error và hàm mutate để ghi đè cache thủ công.
- Cấu hình TTL (time‑to‑live) và chiến lược stale‑while‑revalidate ở mức shared, giúp cả hai nền tảng tuân thủ cùng chính sách hết hạn.
- Áp dụng cache cho các query phổ biến: danh sách sản phẩm, hồ sơ người dùng, cấu hình feature flag. Khi dữ liệu thay đổi trên server, gửi sự kiện realtime (WebSocket / Firebase) để gọi adapter.clear(key) trên cả hai client.
Lợi ích thực tế:
- Giảm ~30% dung lượng bundle do loại bỏ thư viện cache riêng lẻ.
- Đảm bảo trải nghiệm offline nhất quán: người dùng mở app mobile sau khi dùng web vẫn thấy dữ liệu mới nhất.
- Dễ dàng mở rộng: thêm adapter cho Electron, PWA hay server‑side rendering chỉ cần implement interface.
Mẹo triển khai: viết unit test cho từng adapter với jest (web) và @testing-library/react-native (mobile); sử dụng TypeScript strict mode để bắt lỗi mismatch sớm; giám sát hit/miss ratio qua custom event gửi đến analytics.