Tránh những lớp vẽ không cần thiết

Giới thiệu

Việc tô màu các thành phần cho một trang web hoặc ứng dụng có thể rất tốn kém và có thể có tác động tiêu cực đến hiệu suất thời gian chạy của chúng tôi. Trong bài viết này, chúng ta sẽ tìm hiểu nhanh những yếu tố có thể kích hoạt tính năng vẽ trong trình duyệt cũng như cách bạn có thể ngăn chặn việc tô màu không cần thiết xảy ra.

Tranh vẽ: Chuyến tham quan siêu nhanh

Một trong những nhiệm vụ chính mà trình duyệt phải thực hiện là chuyển đổi DOM và CSS thành các pixel trên màn hình. Việc này được thực hiện thông qua một quy trình khá phức tạp. Trình phân tích cú pháp bắt đầu bằng cách đọc phần đánh dấu, sau đó tạo cây DOM. CSS thực hiện quy trình tương tự để tạo CSSOM. Sau đó DOM và CSSOM được kết hợp và cuối cùng, chúng ta đạt được cấu trúc mà từ đó chúng tôi có thể bắt đầu vẽ một số pixel.

Bản thân quá trình vẽ đã thú vị. Trong Chrome, cây kết hợp DOM và CSS được tạo điểm ảnh bằng một số phần mềm có tên là Skia. Nếu từng chơi với phần tử canvas, API của Skia sẽ trông cực kỳ quen thuộc với bạn; có nhiều hàm kiểu moveTolineTo cũng như nhiều hàm nâng cao hơn. Về cơ bản, tất cả các thành phần cần vẽ đều được tinh lọc thành một tập hợp các lệnh gọi Skia có thể được thực thi và dữ liệu đầu ra là một loạt các bitmap. Các bitmap này được tải lên GPU và GPU giúp ích bằng cách kết hợp chúng với nhau để cho chúng ta hình ảnh hoàn thiện trên màn hình.

Dom sang pixel

Điểm cần lưu ý là khối lượng công việc của Skia chịu ảnh hưởng trực tiếp của các kiểu mà bạn áp dụng cho các phần tử. Nếu bạn sử dụng các kiểu dữ liệu nặng theo thuật toán thì Skia sẽ phải làm nhiều việc hơn. Colt McAnlis đã viết một bài viết về cách CSS ảnh hưởng đến trọng số hiển thị trang, vì vậy bạn nên đọc bài viết đó để biết thêm thông tin chi tiết.

Như đã nói, công việc sơn cần có thời gian để thực hiện và nếu chúng ta không giảm, chúng ta sẽ vượt quá ngân sách khung hình là khoảng 16 mili giây. Người dùng sẽ nhận thấy chúng ta bỏ lỡ các khung hình và cho rằng hiện tượng giật sẽ ảnh hưởng xấu đến trải nghiệm người dùng trong ứng dụng. Chúng ta thực sự không muốn điều đó, vì vậy hãy xem nguyên nhân nào khiến hoạt động vẽ lại cần thiết và cách xử lý.

Thao tác cuộn

Bất cứ khi nào bạn cuộn lên hoặc xuống trong trình duyệt, trình duyệt cần vẽ lại nội dung trước khi xuất hiện trên màn hình. Tất cả đều ổn, đó chỉ là một khu vực nhỏ, nhưng ngay cả khi đó là trường hợp đó, các phần tử cần được vẽ có thể được áp dụng các kiểu phức tạp. Vì vậy chỉ vì bạn có một khu vực nhỏ để vẽ không có nghĩa là việc này sẽ diễn ra nhanh chóng.

Để xem khu vực nào đang được sơn lại, bạn có thể sử dụng tính năng "Hiển thị hình chữ nhật vẽ" trong Công cụ của Chrome cho nhà phát triển (chỉ cần nhấn vào bánh răng nhỏ ở góc dưới bên phải). Sau đó, khi Công cụ cho nhà phát triển mở, bạn chỉ cần tương tác với trang của mình và bạn sẽ thấy các hình chữ nhật nhấp nháy hiển thị vị trí và thời điểm Chrome vẽ một phần trên trang của bạn.

Hiển thị hình chữ nhật vẽ trong Công cụ của Chrome cho nhà phát triển
Hiển thị hình chữ nhật vẽ trong Công cụ của Chrome cho nhà phát triển

Hiệu suất cuộn rất quan trọng đối với sự thành công của trang web; người dùng thực sự nhận thấy khi trang web hoặc ứng dụng của bạn không cuộn ổn định và họ không thích điều đó. Do đó, chúng tôi quan tâm đến việc giữ cho sơn hoạt động sáng trong khi cuộn để người dùng không thấy hiện tượng giật.

Trước đây, tôi đã từng viết một bài viết về hiệu suất cuộn, nên hãy xem bài viết đó nếu bạn muốn biết thêm thông tin cụ thể về hiệu suất cuộn.

Số lượt tương tác

Tương tác là một nguyên nhân khác gây ra việc tô màu: di chuột, nhấp, chạm, kéo. Bất cứ khi nào người dùng thực hiện một trong các hoạt động tương tác đó, chẳng hạn như di chuột, thì Chrome sẽ phải vẽ lại phần tử bị ảnh hưởng. Tương tự như thao tác cuộn, nếu cần một lớp sơn lớn và phức tạp, bạn sẽ thấy tốc độ khung hình giảm.

Ai cũng muốn ảnh động tương tác đẹp, mượt mà, vì vậy một lần nữa, chúng ta sẽ cần xem liệu các kiểu thay đổi trong ảnh động có tốn quá nhiều thời gian hay không.

Sự kết hợp không may

Bản minh hoạ với những loại sơn đắt tiền
Bản minh hoạ với các loại sơn đắt tiền

Điều gì xảy ra nếu tôi cuộn và tôi di chuyển chuột cùng lúc? Tôi hoàn toàn có thể vô tình "tương tác" với một phần tử khi cuộn qua phần tử đó, kích hoạt một lớp sơn tốn kém. Đổi lại, điều đó có thể đẩy tôi vượt qua ngân sách khung hình của mình là ~ 16, 7 mili giây (thời gian chúng tôi cần duy trì dưới mức đó để đạt 60 khung hình mỗi giây). Tôi đã tạo một bản minh hoạ để cho bạn biết chính xác điều tôi muốn nói. Hy vọng khi bạn cuộn và di chuyển chuột, bạn sẽ thấy các hiệu ứng di chuột xuất hiện, nhưng hãy xem Công cụ của Chrome tạo ra những gì:

Công cụ cho nhà phát triển của Chrome hiển thị các khung hình đắt tiền
Công cụ cho nhà phát triển của Chrome cho thấy các khung hình tốn kém

Trong hình ảnh ở trên, bạn có thể thấy Công cụ cho nhà phát triển đang đăng ký công việc sơn khi tôi di chuột vào một trong các khối. Tôi đã dùng một số kiểu cực kỳ nặng trong bản minh hoạ của mình để tạo ra vấn đề và vì vậy, tôi thường xuyên tăng ngân sách khung hình của mình. Điều cuối cùng tôi muốn là phải thực hiện việc tô màu này một cách không cần thiết, đặc biệt là trong quá trình cuộn khi có việc khác cần làm!

Vậy làm cách nào để chúng ta ngăn chặn điều này xảy ra? Khi xảy ra, việc triển khai bản sửa lỗi khá đơn giản. Bí quyết ở đây là đính kèm một trình xử lý scroll có chức năng tắt các hiệu ứng di chuột và hẹn giờ để bật lại các hiệu ứng đó. Điều đó có nghĩa là chúng tôi đảm bảo rằng khi bạn cuộn, chúng tôi sẽ không cần thực hiện bất kỳ thao tác tương tác tốn kém nào. Khi bạn đã dừng đủ lâu, chúng tôi cho rằng đã an toàn để bật lại các tính năng này.

Đây là mã:

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

Như bạn có thể thấy, chúng ta sử dụng một lớp trên phần nội dung để theo dõi xem hiệu ứng di chuột có được "cho phép" hay không và các kiểu cơ bản sẽ dựa vào lớp này:

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 …
}

Đó là tất cả những gì bạn cần làm!

Kết luận

Hiệu suất kết xuất là yếu tố rất quan trọng đối với việc người dùng thích ứng dụng của bạn và bạn nên luôn cố gắng giữ cho khối lượng công việc vẽ tranh dưới 16 mili giây. Để giúp bạn làm được điều đó, bạn nên tích hợp bằng cách sử dụng Công cụ cho nhà phát triển trong suốt quá trình phát triển của bạn để xác định và khắc phục nút thắt cổ chai khi chúng phát sinh.

Việc vô tình tương tác, đặc biệt là trên các thành phần có nhiều sơn, có thể rất tốn kém và làm giảm hiệu suất kết xuất. Như bạn đã thấy, chúng ta có thể sử dụng một đoạn mã nhỏ để khắc phục vấn đề đó.

Hãy xem các trang web và ứng dụng của bạn, chúng có thể làm giảm độ phân giải của sơn không?