Tìm hiểu về độ trễ đầu vào và tìm hiểu các kỹ thuật để giảm độ trễ này nhằm tăng tính tương tác.
Các hoạt động tương tác trên web là những hoạt động phức tạp, vớ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ả những thành phần này là chúng đều gây ra một số độ trễ đầu vào trước khi các 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 bạn 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ẽ diễn ra nhanh hơn.
Độ trễ khi nhập thông tin 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 bằng chuột hoặc nhấn một 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.
Không thể tránh khỏi một phần độ trễ đầu vào: hệ điều hành luôn mất một khoảng thời gian nhất định để 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 kể, và có những việc khác xảy ra trên chính trang có thể khiến độ trễ đầu vào đủ lâu để gây ra vấn đề.
Cách suy nghĩ về độ trễ đầu vào
Nói chung, bạn nên rút ngắn mọi phần của một lượt tương tác càng nhiều càng tốt để trang web của bạn có nhiều khả năng đá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ể người dùng sử dụng thiết bị nào. 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 cố gắng đạt được độ 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 quá nhiều hoạt động trên luồng chính trong khi người dùng đang cố gắng tương tác với trang của bạn, độ trễ đầu vào sẽ đủ thấp để tránh các vấn đề.
Cách giảm thiểu độ trễ đầu vào
Như đã nói trước đó, bạn không thể tránh khỏi một số độ trễ đầu vào, nhưng mặt khác, bạn có thể tránh được một số độ trễ đầu vào. Dưới đây là một số điều cần cân nhắc nếu bạn gặp phải tình trạng trễ đầu vào kéo dài.
Tránh các bộ hẹn giờ định kỳ khởi động quá nhiều thao tác trên luồng chính
Có 2 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. Điểm khác biệt giữa hai phương thức này là setTimeout lên lịch một lệnh gọi lại để chạy sau một khoảng thời gian cụ thể. 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.
setTimeout không phải là vấn đề tự thân. Trên thực tế, nó có thể hữu ích trong việc tránh các tác vụ dài. Tuy nhiên, điều này còn tuỳ thuộc vào thời điểm xảy ra 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 thời gian chờ chạy hay không.
Ngoài ra, setTimeout có thể chạy trong một vòng lặp hoặc đệ quy, trong đó nó hoạt động giống như setInterval, mặc dù tốt nhất là không lên lịch cho lần lặp lại tiếp theo cho đến khi lần lặp lại trước đó hoàn tất. Mặc dù điều này có nghĩa là vòng lặp sẽ nhường chỗ cho luồng chính mỗi khi setTimeout được gọi, nhưng bạn nên cẩn thậ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 thao tác.
setInterval chạy một lệnh gọi lại theo một khoảng thời gian nhất định, do đó, nhiều khả năng sẽ 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 lệnh gọi setTimeout duy nhất (là một lệnh gọi lại một lần mà 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 sẽ cản trở hoạt động tương tác, do đó làm tăng độ trễ đầu vào của hoạt động tương tác.
setInterval trước đó đăng ký, góp phần gây ra độ trễ đầu vào như 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ộ hẹn giờ xuất hiện trong mã của bên thứ nhất, thì bạn có thể kiểm soát chúng. Đánh giá xem bạn có cần chúng hay không, hoặc cố gắng giảm thiểu công việc trong chúng càng nhiều càng tốt. Tuy nhiên, bộ hẹn giờ trong tập lệnh của bên thứ ba lại là một chuyện khác. Bạn thường không kiểm soát được những gì mà một tập lệnh bên thứ ba thực hiện, đồng thời việc khắc phục các vấn đề về hiệu suất trong mã 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 cụ thể có cần thiết hay không. Nếu cần thiết, 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 cá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ụ dài
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 việc cần làm trên luồng chính khiến luồng chính bị chặn trong quá trình tương tác, điều đó sẽ làm tăng độ trễ đầu vào cho người dùng trước khi các tác vụ dài có cơ hội hoàn thành.
Ngoài việc giảm thiểu lượng công việc bạn thực hiện trong một tác 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 đối vớ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 trường hợp tương tác trùng lặp
Một phần đặc biệt khó khăn trong việc tối ưu hoá INP có thể là khi bạn có các lượt tương tác trùng lặp. Tương tác chồng chéo 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 tương tác khác với trang trước khi tương tác ban đầu có cơ hội hiển thị khung hình tiếp theo.
Các nguồn tương tác trùng lặp có thể đơn giản như việc 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 có thể xảy ra nhiều lượt tương tác với bàn phím trong một khoảng thời gian rất ngắn. Nếu việc thực hiện một sự kiện chính tốn nhiều tài nguyên (chẳng hạn như trong trường hợp phổ biến của các trường tự động hoàn thành, nơi các yêu cầu mạng được gửi đến một phần phụ trợ), bạn có thể chọn một trong hai cách sau:
- Hãy cân nhắc việc loại bỏ các thao tác trùng lặp để 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ầufetchđi, nhờ đó 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ỷ các sự kiện.
Một nguồn khác gây ra tình trạng tăng độ trễ đầu vào do các hoạt động tương tác chồng chéo có thể là các ả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ở các lượt tương tác của người dùng. Để khắc phục vấn đề này, hãy sử dụng ảnh động CSS bất cứ khi nào có thể để tránh xếp hàng các khung hình ảnh động có khả năng tốn kém – nhưng nếu bạn làm điều này, hãy đảm bảo rằng bạn tránh ảnh động không được ghép để ảnh động chủ yếu chạy trên các luồng GPU và 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ác hoạt động tương tác của bạn, nhưng điều quan trọng là bạn phải hiểu rằng mọi phần của một hoạt động 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ó thể giảm độ trễ này. 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 tương tác chồng chéo đều có thể giúp bạn giảm độ trễ đầu vào, dẫn đến khả năng tương tác nhanh hơn cho người dùng trang web của bạn.
Hình ảnh chính trên Unsplash, của Erik Mclean.