Thông báo realtime là phần không thể thiếu trong hầu hết các ứng dụng hiện đại: chat, cập nhật đơn hàng, cảnh báo hệ thống, v.v. Khi phát triển đồng thời cho web và mobile, việc tái sử dụng logic và giao diện thông báo giúp giảm thiểu trùng lặp mã nguồn và đảm bảo trải nghiệm nhất quán. 1. Chọn giải pháp truyền tải - WebSocket: phù hợp cho kết nối hai chiều, độ trễ thấp. Thư viện phổ biến là socket.io (hỗ trợ fallback tự động) hoặc ws kết hợp với adapter tùy chỉnh. - Server‑Sent Events (SSE): đơn giản hơn cho luồng một chiều (server → client), hoạt động tốt trên HTTP/2 và ít gặp vấn đề tường lửa. - GraphQL Subscriptions: nếu dự án đã dùng GraphQL, subscriptions cho phép tích hợp liền mạch với schema hiện có. 2. Kiến trúc chia sẻ trong Monorepo - Tạo package `shared-notifications` chứa: kiểu dữ liệu (TypeScript interfaces), custom hook `useNotificationStream`, và component UI `NotificationBell`/`NotificationList` viết bằng React Native Web (hoặc dùng `react-native-web` để render trên web). - Cấu hình `metro` và `webpack`/`vite` để alias trỏ đến package chung, đảm bảo cùng một bản build cho cả hai nền tảng. 3. Xử lý xác thực và phân quyền - Gắn JWT hoặc session token vào handshake WebSocket (header `Authorization` hoặc query param). - Trên server, middleware kiểm tra quyền trước khi cho phép subscribe vào các room/kênh riêng biệt (ví dụ: `user:{id}`, `role:admin`). 4. Quản lý trạng thái cục bộ và hiển thị - Sử dụng Zustand hoặc Redux Toolkit trong `shared-notifications` để lưu danh sách thông báo chưa đọc, số lượng badge. - Hook `useNotificationStream` trả về `{ notifications, unreadCount, markAsRead }`; component UI chỉ cần consume hook mà không quan tâm nền tảng. 5. Xử lý ngoại tuyến và đồng bộ - Khi mất kết nối, client lưu các sự kiện vào IndexedDB (web) hoặc AsyncStorage (native). - Sau khi reconnect, gửi danh sách `lastSeenEventId` lên server để kéo nạp thông báo bị miss. 6. Triển khai và giám sát - Đóng gói server WebSocket vào Docker, chạy behind Nginx/Traefik với TLS. - Theo dõi metric: kết nối đồng thời, tỷ lệ reconnect, độ trễ trung bình qua Prometheus + Grafana. Lời khuyên thực tế: bắt đầu với SSE cho các luồng đơn giản (thông báo hệ thống), sau đó nâng cấp lên WebSocket khi cần tính năng chat hai chiều. Việc tách biệt logic truyền tải khỏi UI trong package chung giúp team web và mobile phát triển song song mà không bị chồng chéo.