Main Thread của trình duyệt - Tài nguyên đắt đỏ mà ít ai để ý

01 tháng 9, 2026·4 phút đọc

Bài viết phân tích chi tiết về main thread - nơi tập trung xử lý mọi tác vụ JavaScript và render của trình duyệt - qua đó giải thích vì sao website bị giật lag dù code không hề chậm. Tác giả giới thiệu bốn chiến lược tối ưu chính: chia nhỏ (splitting), gom nhóm (batching), ưu tiên (prioritizing) và trì hoãn (deferring) cùng cách đẩy công việc sang các thread khác.

Main Thread của trình duyệt - Tài nguyên đắt đỏ mà ít ai để ý

Main Thread của trình duyệt: Tài nguyên đắt đỏ quyết định trải nghiệm web

Khi nhắc đến tối ưu hiệu năng frontend, hầu hết lập trình viên nghĩ ngay đến giảm số request mạng, tối ưu bundle JavaScript, hoặc tận dụng cache. Tuy nhiên, có một tài nguyên quan trọng hơn nhiều thường bị bỏ qua: main thread của trình duyệt. Bài viết này sẽ đi sâu vào vì sao main thread là "nút thắt" quyết định hiệu năng web, đặc biệt với các ứng dụng có nhiều tương tác trực tiếp, cùng các chiến lược tối ưu từ cơ bản đến nâng cao.

Vì sao main thread lại đắt đỏ đến vậy?

Main thread không chỉ xử lý JavaScript mà còn là nơi toàn bộ pipeline render diễn ra. Hãy tưởng tượng một buổi livestream với hàng trăm tin nhắn chat mỗi giây - việc render tất cả chúng cùng lúc sẽ khiến mọi thao tác của người dùng bị đóng băng.

Điểm mấu chốt: Main thread chỉ xử lý một tác vụ tại một thời điểm. Nếu một hàm JavaScript chạy 200ms, trình duyệt không thể vẽ khung hình mới hay nhận click chuột trong suốt khoảng thời gian đó. Trong khi ngân sách cho mỗi khung hình chỉ khoảng 10ms (với màn hình 60Hz), đây là một thảm họa về hiệu năng.

Pipeline render: Trách nhiệm nặng nề của main thread

Quá trình tạo khung hình bao gồm:

  • Chạy callback requestAnimationFrame
  • Tính toán style
  • Layout (reflow)
  • Paint

Toàn bộ quy trình này - ngoại trừ bước compositing cuối cùng được chuyển sang compositor thread riêng - đều diễn ra trên main thread. Điều này giải thích vì sao một animation CSS chạy mượt mà trong khi JavaScript animation bị giật khi main thread bị nghẽn.

Bốn chiến lược quản lý main thread hiệu quả

Chia nhỏ (Splitting): Kim chỉ nam của mọi giải pháp

Cách hiệu quả nhất để xử lý một tác vụ quá dài là cắt nó thành nhiều phần nhỏ, giải phóng main thread giữa các phần để trình duyệt kịp xử lý input và vẽ khung hình:

async function renderChats(chats) {
  let count = 0;
  for (const chat of chats) {
    appendChatNode(chat);
    if (++count % 20 === 0) {
      await new Promise((resolve) => setTimeout(resolve, 0));
    }
  }
}

Kỹ thuật này phù hợp khi xử lý danh sách tin nhắn dài, parse dữ liệu lớn từ API, hoặc cập nhật DOM theo lô.

Gom nhóm (Batching): Giảm tải cho main thread

Microtask và Microtask queue là hai khái niệm quan trọng cần nắm:

  • Microtask (Promise callback, MutationObserver) chạy ngay sau khi tác vụ hiện tại kết thúc, trước khi trình duyệt có thể render.
  • Task (setTimeout, event listener) đặt công việc vào hàng đợi riêng, cho phép trình duyệt xử lý render và input giữa các task.

Ví dụ với live stream chat: nên tách tin nhắn đến thành từng phần và render sau mỗi 50ms thay vì cập nhật DOM liên tục theo mỗi tin nhắn, giúp main thread có thời gian thở.

Ưu tiên và trì hoãn: Lựa chọn thông minh cho tác vụ

Sử dụng requestIdleCallback cho công việc không khẩn cấp (phân tích analytics, render nội dung ngoài viewport), lazy loading cho component chỉ hiển thị khi cần, và debounce để gom nhóm các event xảy ra thường xuyên như scroll hay resize.

Với tác vụ nhận dữ liệu real-time, nên ưu tiên xử lý tin nhắn hiện tại trên màn hình, trì hoãn việc hash/lưu trữ dữ liệu cũ sang thời điểm rảnh.

Đẩy công việc ra khỏi main thread

Giải pháp triệt để hơn là chuyển toàn bộ công việc nặng sang các thread khác. Các lựa chọn phổ biến:

Web Worker: Phù hợp cho xử lý computation-heavy như parse file lớn, xử lý media, học máy tại client. Cần lưu ý chi phí truyền dữ liệu giữa các thread qua postMessage, đặc biệt với dữ liệu lớn.

OffscreenCanvas: Cho phép animation và render 3D nặng chạy trên worker thay vì chặn main thread. Hữu ích cho game, dashboard real-time với nhiều biểu đồ tương tác.

Compositor thread: Tận dụng animation chỉ với transform/opacity giúp trình duyệt tự động xử lý trên compositor thread không cần thao tác JavaScript phức tạp.

Kết luận

Main thread là tài nguyên quý giá nhất của trình duyệt, và việc hiểu rõ cách hoạt động của nó cùng các chiến lược tối ưu sẽ giúp website của bạn hoạt động mượt mà hơn, đặc biệt trên các thiết bị di động vốn có cấu hình hạn chế. Hãy bắt đầu bằng việc xác định xem ứng dụng của bạn có đang giữ main thread quá lâu hay không, sau đó từng bước áp dụng các kỹ thuật chia nhỏ, gom nhóm, ưu tiên và trì hoãn tác vụ một cách hợp lý.

Đối với lập trình viên Việt Nam, việc nắm vững những kỹ thuật này không chỉ giúp cải thiện trải nghiệm người dùng trên các ứng dụng phổ biến như chat, livestream hay dashboard, mà còn là lợi thế cạnh tranh khi phát triển sản phẩm phục vụ thị trường trong nước với hạ tầng internet và thiết bị đa dạng.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗