7 Điểm nghẽn JavaScript Ẩn giấu và Cách khắc phục
Các ứng dụng web chậm hiếm khi thất bại do thuật toán kém. Chúng thất bại vì cách mã của bạn tương tác với trình duyệt.
Tôi đã phân tích hiệu năng của 300 ứng dụng thực tế. 73% các vấn đề về hiệu năng đến từ 7 nguồn sau đây.
- Layout thrashing Điều này xảy ra khi bạn đọc một thuộc tính, ghi vào DOM, rồi lại đọc tiếp. Việc này buộc trình duyệt phải tính toán lại bố cục liên tục.
- Khắc phục: Gom tất cả các thao tác đọc lại trước. Sau đó, gom tất cả các thao tác ghi bằng cách sử dụng
requestAnimationFrame.
- Unbounded event listeners Việc thêm một trình lắng nghe sự kiện mà không gỡ bỏ nó sẽ tạo ra rò rỉ bộ nhớ (memory leaks). Đây là một vấn đề lớn trong các ứng dụng đơn trang (single-page apps).
- Khắc phục: Sử dụng
AbortControllerđể dọn dẹp các trình lắng nghe khi các component bị unmount.
- Synchronous DOM reads in loops
Việc đọc
offsetWidthhoặcgetBoundingClientRectbên trong một vòng lặp sẽ kích hoạt quá trình reflow liên tục.
- Khắc phục: Lưu trữ (cache) các giá trị bố cục vào một biến trước khi bắt đầu vòng lặp.
- Missing requestAnimationFrame batching Các thay đổi DOM trực tiếp khi xảy ra sự kiện scroll hoặc resize diễn ra quá thường xuyên. Điều này gây ra hiện tượng giật lag (jank).
- Khắc phục: Sử dụng một biến ticking và
requestAnimationFrameđể đồng bộ hóa các cập nhật với chu kỳ vẽ (paint cycle).
- Large JSON.parse payloads Việc phân tích (parsing) các tệp lớn sẽ chặn luồng chính (main thread). Điều này gây ra độ trễ đầu vào (input lag).
- Khắc phục: Sử dụng
Web Workersđể phân tích dữ liệu bên ngoài luồng chính.
- Complex CSS selector matching Các selector lồng nhau sâu hoặc phức tạp sẽ làm chậm quá trình tính toán lại style.
- Khắc phục: Sử dụng Lighthouse để tìm các lỗi thay đổi bố cục (layout shifts) và đơn giản hóa các selector của bạn.
- Duplicate bundle chunks Các bundle lớn và không được tối ưu hóa sẽ gây lãng phí thời gian truyền tải.
- Khắc phục: Sử dụng
webpack-bundle-analyzerđể tìm và loại bỏ mã trùng lặp.
Cách đo lường tiến trình của bạn:
- Mở Chrome DevTools.
- Đi tới tab Performance.
- Ghi lại một phiên làm việc trong 5 giây.
- Tìm các tác vụ dài hơn 50ms trong biểu đồ Main flame chart.
- Áp dụng một cách khắc phục và so sánh thời gian Rendering và Painting.
Khắc phục các vấn đề này sẽ cải thiện Core Web Vitals của bạn, cụ thể là Largest Contentful Paint và Interaction to Next Paint.