Frontend realtime

LiveCrypto

Dashboard crypto dùng dữ liệu Binance trực tiếp, chart tự vẽ bằng Canvas và pipeline dữ liệu có giới hạn ở phía client.

Next.js 16React 19TypeScriptCanvasTanStack VirtualWebSocketTailwind CSS v4
LiveCrypto - Frontend realtime

Kết quả

Stream trực tiếp 8 cặp coin
Canvas engine tự viết, 60fps
Ring buffer 15k lệnh

Ý tưởng

Màn hình theo dõi thị trường realtime có mặt ở hầu hết sản phẩm fintech, và cũng là phần dễ gặp vấn đề hiệu năng nhất của frontend. Tám cặp coin đẩy về nhiều giao dịch mỗi giây; nếu cứ mỗi tick lại để React render lại thì giao diện sẽ khựng rất nhanh, mà với một bảng giá thì người dùng nhận ra độ trễ ngay lập tức. Tôi làm LiveCrypto để giải trọn bài toán này, từ kết nối socket cho tới khung hình hiển thị cuối cùng.

App gọi thẳng các endpoint công khai của Binance nên không cần xây backend riêng, chi phí vận hành gần như bằng không. Đổi lại, những phần khó nhất gồm buffer dữ liệu, gộp nến và render đều phải xử lý ngay trong trình duyệt, không có server nào hỗ trợ phía sau.

Kiến trúc

WebSocket của tám cặp USDT ghi dữ liệu vào TradeStore, một ring buffer giữ tối đa 15.000 giao dịch. Thanh thống kê, danh sách giao dịch và bộ gộp nến 3 giây đều đọc từ store này. Các khung thời gian dài hơn lấy từ Binance REST klines. Cả hai API đều công khai nên không cần market-data key.

  • Next.js 16 App Router, React 19, Tailwind CSS v4.
  • Một ring buffer 15k làm nguồn dữ liệu duy nhất cho lệnh live.
  • Deploy trên Vercel, không cần key dữ liệu ở phía server.

Tự vẽ chart thay vì dùng thư viện

Chart đường và chart nến được vẽ trực tiếp trên Canvas trong vòng lặp requestAnimationFrame. Tôi không dùng thư viện chart vì muốn kiểm soát thời điểm vẽ từng frame và khối lượng xử lý mỗi khi có giao dịch mới. Ở mỗi frame, chart đọc dữ liệu nến qua một ref, nên tick mới chỉ cập nhật hình vẽ chứ không kéo theo re-render cây React.

Giữ giao diện phản hồi nhanh

TanStack Virtual chỉ giữ những dòng đang hiển thị trong DOM, nhờ đó bảng giao dịch giữ được 60fps ngay cả khi buffer chứa hàng nghìn lệnh, còn bộ nhớ không tăng theo thời gian vì ring buffer không bao giờ vượt quá 15.000 bản ghi. Để các con số này không phải nói suông, app có sẵn trang /perf đo FPS, độ trễ tương tác, số sự kiện mỗi phút và mức dùng bộ nhớ ngay trong trình duyệt, kiểm chứng được trực tiếp khi luồng dữ liệu đang chạy.

AI copilot

Mỗi câu hỏi gửi lên đều kèm một bản chụp trạng thái thị trường tại thời điểm đó. Bản demo công khai dùng mock provider nên không cần credential; khi muốn nối provider thật chỉ cần thay ở một adapter duy nhất, API key vẫn nằm ở server.

Giới hạn và hướng phát triển

Toàn bộ ứng dụng chạy trong một tab trình duyệt và chưa có persistence: reload trang là buffer về rỗng, chỉ còn lịch sử lấy từ REST cho tới khi giao dịch live lấp đầy lại. Phần gộp nến cũng đang chạy trên main thread, ổn với laptop thông thường nhưng chưa được kiểm tra trên máy cấu hình yếu. Nếu phát triển tiếp, tôi sẽ chuyển việc gộp nến sang Web Worker và lưu buffer vào IndexedDB để dữ liệu không mất khi refresh.