Tìm hiểu về độ trễ đầu vào và các kỹ thuật giúp giảm độ trễ đầu vào để tăng tốc độ tương tác.
Các hoạt động tương tác trên web rất phức tạp, với mọi loại hoạt động diễn ra trong trình duyệt để thúc đẩy các hoạt động đó. Tuy nhiên, điểm chung của tất cả các phương thức này là đều gây ra một số độ trễ đầu vào trước khi lệnh gọi lại sự kiện bắt đầu chạy. Trong hướng dẫn này, bạn sẽ tìm hiểu về độ trễ đầu vào và những việc có thể làm để giảm thiểu độ trễ này, nhờ đó các hoạt động tương tác trên trang web của bạn sẽ chạy nhanh hơn.
Độ trễ đầu vào là gì?
Độ trễ đầu vào là khoảng thời gian bắt đầu từ khi người dùng tương tác lần đầu với một trang (chẳng hạn như nhấn vào màn hình, nhấp chuột hoặc nhấn phím) cho đến khi lệnh gọi lại sự kiện cho hoạt động tương tác bắt đầu chạy. Mọi lượt tương tác đều bắt đầu bằng một khoảng thời gian trễ đầu vào nhất định.
Một phần độ trễ đầu vào là không thể tránh khỏi: hệ điều hành luôn mất một khoảng thời gian để nhận dạng sự kiện đầu vào và chuyển sự kiện đó đến trình duyệt. Tuy nhiên, phần độ trễ đầu vào đó thường không đáng chú ý và có những điều khác xảy ra trên chính trang có thể khiến độ trễ đầu vào đủ dài để gây ra sự cố.
Cách xem xét độ trễ đầu vào
Nói chung, bạn nên giữ cho mọi phần của lượt tương tác ngắn nhất có thể để trang web của bạn có cơ hội tốt nhất đáp ứng ngưỡng "tốt" của chỉ số Lượt tương tác đến nội dung hiển thị tiếp theo (INP), bất kể thiết bị của người dùng là gì. Việc kiểm soát độ trễ đầu vào chỉ là một phần trong việc đáp ứng ngưỡng đó.
Do đó, bạn nên đặt mục tiêu là độ trễ đầu vào ngắn nhất có thể để đáp ứng ngưỡng "tốt" của INP. Tuy nhiên, bạn cần lưu ý rằng bạn không thể loại bỏ hoàn toàn độ trễ đầu vào. Miễn là bạn tránh được việc thực hiện quá nhiều công việc trên luồng chính trong khi người dùng đang cố gắng tương tác với trang, thì độ trễ đầu vào của bạn sẽ đủ thấp để tránh các vấn đề.
Cách giảm thiểu độ trễ đầu vào
Như đã nói ở trên, một số độ trễ đầu vào là không thể tránh khỏi, nhưng mặt khác, một số độ trễ đầu vào có thể tránh được. Dưới đây là một số điều cần cân nhắc nếu bạn đang gặp phải tình trạng độ trễ đầu vào kéo dài.
Tránh các bộ tính giờ định kỳ khởi động quá nhiều công việc trên luồng chính
Có hai hàm hẹn giờ thường dùng trong JavaScript có thể góp phần gây ra độ trễ đầu vào: setTimeout và setInterval. Sự khác biệt giữa hai phương thức này là setTimeout lên lịch cho một lệnh gọi lại để chạy sau một thời gian chỉ định. Mặt khác, setInterval lên lịch cho một lệnh gọi lại chạy mỗi n mili giây vĩnh viễn hoặc cho đến khi bộ hẹn giờ dừng bằng clearInterval.
Bản thân setTimeout không có vấn đề gì, trên thực tế, việc này có thể giúp tránh các tác vụ cần nhiều thời gian. Tuy nhiên, điều này phụ thuộc vào thời điểm hết thời gian chờ và liệu người dùng có cố gắng tương tác với trang khi lệnh gọi lại hết thời gian chờ chạy hay không.
Ngoài ra, bạn có thể chạy setTimeout trong một vòng lặp hoặc đệ quy, trong đó hàm này hoạt động giống như setInterval hơn, mặc dù tốt nhất là không nên lên lịch cho lần lặp tiếp theo cho đến khi lần lặp trước đó hoàn tất. Mặc dù điều này có nghĩa là vòng lặp sẽ nhường quyền cho luồng chính mỗi khi setTimeout được gọi, nhưng bạn nên đảm bảo lệnh gọi lại của vòng lặp không thực hiện quá nhiều công việc.
setInterval chạy lệnh gọi lại theo khoảng thời gian, do đó có nhiều khả năng cản trở các hoạt động tương tác. Điều này là do (không giống như một thực thể duy nhất của lệnh gọi setTimeout, vốn là một lệnh gọi lại một lần có thể cản trở hoạt động tương tác của người dùng) bản chất định kỳ của setInterval khiến lệnh gọi này có nhiều khả năng cản trở hoạt động tương tác, từ đó làm tăng độ trễ đầu vào của hoạt động tương tác.
setInterval trước đó góp phần gây ra độ trễ đầu vào như được mô tả trong bảng điều khiển hiệu suất của Chrome DevTools. Độ trễ đầu vào được thêm vào khiến các lệnh gọi lại sự kiện cho hoạt động tương tác chạy muộn hơn so với bình thường.
Nếu bộ tính giờ đang xảy ra trong mã của bên thứ nhất, thì bạn có quyền kiểm soát chúng. Hãy đánh giá xem bạn có cần các lệnh gọi này hay không, hoặc cố gắng giảm thiểu công việc trong các lệnh gọi này nhiều nhất có thể. Tuy nhiên, bộ hẹn giờ trong tập lệnh của bên thứ ba lại là một câu chuyện khác. Bạn thường không kiểm soát được hoạt động của tập lệnh bên thứ ba và việc khắc phục vấn đề về hiệu suất trong mã của bên thứ ba thường liên quan đến việc làm việc với các bên liên quan để xác định xem một tập lệnh bên thứ ba nhất định có cần thiết hay không. Nếu có, hãy liên hệ với nhà cung cấp tập lệnh bên thứ ba để xác định những việc có thể làm để khắc phục vấn đề về hiệu suất mà họ có thể gây ra trên trang web của bạn.
Tránh các tác vụ cần nhiều thời gian
Một cách để giảm thiểu độ trễ đầu vào dài là tránh các tác vụ dài. Khi bạn có quá nhiều công việc trên luồng chính khiến luồng chính bị chặn trong các lượt tương tác, thì độ trễ đầu vào của các lượt tương tác đó sẽ tăng lên trước khi các tác vụ cần nhiều thời gian có cơ hội hoàn tất.
Ngoài việc giảm thiểu khối lượng công việc bạn thực hiện trong một tác vụ (và bạn luôn phải cố gắng thực hiện ít công việc nhất có thể trên luồng chính), bạn có thể cải thiện khả năng phản hồi hoạt động đầu vào của người dùng bằng cách chia nhỏ các tác vụ dài.
Lưu ý đến sự trùng lặp về tương tác
Một phần đặc biệt khó khăn trong việc tối ưu hoá INP có thể là nếu bạn có các lượt tương tác trùng lặp. Sự trùng lặp lượt tương tác có nghĩa là sau khi tương tác với một phần tử, bạn thực hiện một lượt tương tác khác với trang trước khi lượt tương tác ban đầu có cơ hội hiển thị khung hình tiếp theo.
Nguồn gốc của sự trùng lặp lượt tương tác có thể đơn giản là do người dùng thực hiện nhiều lượt tương tác trong một khoảng thời gian ngắn. Điều này có thể xảy ra khi người dùng nhập vào các trường biểu mẫu, nơi nhiều lượt tương tác bằng bàn phím có thể xảy ra trong một khoảng thời gian rất ngắn. Nếu công việc liên quan đến một sự kiện chính đặc biệt tốn kém (chẳng hạn như trong trường hợp phổ biến là các trường tự động hoàn thành, nơi các yêu cầu mạng được gửi đến phần phụ trợ), thì bạn có một số lựa chọn:
- Hãy cân nhắc việc loại bỏ dữ liệu đầu vào để giới hạn số lần thực thi lệnh gọi lại sự kiện trong một khoảng thời gian nhất định.
- Sử dụng
AbortControllerđể huỷ các yêu cầufetchgửi đi để luồng chính không bị tắc nghẽn khi xử lý các lệnh gọi lạifetch. Lưu ý: Bạn cũng có thể dùng thuộc tínhsignalcủa một thực thểAbortControllerđể huỷ sự kiện.
Một nguồn khác làm tăng độ trễ đầu vào do các lượt tương tác chồng chéo có thể là ảnh động tốn kém. Cụ thể, ảnh động trong JavaScript có thể kích hoạt nhiều lệnh gọi requestAnimationFrame, điều này có thể cản trở hoạt động tương tác của người dùng. Để giải quyết vấn đề này, hãy sử dụng ảnh động CSS bất cứ khi nào có thể để tránh đưa các khung ảnh động có thể tốn kém vào hàng đợi. Tuy nhiên, nếu làm việc này, hãy đảm bảo bạn tránh ảnh động không kết hợp để ảnh động chạy chủ yếu trên GPU và luồng trình kết hợp, chứ không phải trên luồng chính.
Kết luận
Mặc dù độ trễ đầu vào có thể không chiếm phần lớn thời gian chạy của các lượt tương tác, nhưng bạn cần hiểu rằng mọi phần của một lượt tương tác đều chiếm một khoảng thời gian mà bạn có thể giảm bớt. Nếu nhận thấy độ trễ đầu vào dài, thì bạn có cơ hội giảm độ trễ đó. Việc tránh các lệnh gọi lại bộ hẹn giờ định kỳ, chia nhỏ các tác vụ dài và nhận biết khả năng trùng lặp tương tác đều có thể giúp bạn giảm độ trễ đầu vào, từ đó giúp người dùng trang web tương tác nhanh hơn.