Các sự kiện đột biến sẽ bị xoá khỏi Chrome

Thông báo về việc ngừng sử dụng và lên kế hoạch loại bỏ các sự kiện đột biến, đồng thời chia sẻ cách bạn có thể di chuyển mã của mình trước thời điểm xoá vào tháng 7 năm 2024.

Mason Freed
Mason Freed

Chromium đã chính thức ngừng sử dụng các sự kiện đột biến và dự định ngừng hỗ trợ phiên bản 127. Phiên bản này sẽ trở thành bản phát hành ổn định vào ngày 23 tháng 7 năm 2024. Bài đăng này giải thích lý do chúng ta xoá các sự kiện đột biến và cung cấp lộ trình di chuyển trước khi những sự kiện này bị xoá khỏi trình duyệt.

Sự kiện đột biến là gì?

Sự kiện đột biến là tên của tập hợp các sự kiện sau đây:

  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMSubtreeModified
  • DOMCharacterDataModified
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemovedFromDocument
  • (Không được bất kỳ trình duyệt hiện đại nào hỗ trợ) DOMAttrModified
  • (Không được bất kỳ trình duyệt hiện đại nào hỗ trợ) DOMAttributeNameChanged
  • (Không được bất kỳ trình duyệt hiện đại nào hỗ trợ) DOMElementNameChanged

Các sự kiện này là một phần rất cũ của thông số kỹ thuật DOM cấp 2 và đã không được dùng nữa kể từ năm 2011. Các giao diện này được thay thế bằng giao diện MutationObserver. Giao diện này được hỗ trợ trong tất cả các trình duyệt hiện đại kể từ năm 2013.

Lịch sử về các sự kiện đột biến

Cách đây lâu, các sự kiện đột biến có vẻ là một ý hay, nhưng hoá ra lại có một số lỗi nghiêm trọng:

  • Chúng dài dòng và kích hoạt quá thường xuyên. Một sự kiện sẽ được kích hoạt cho mỗi nút bị xoá.
  • Các chiến dịch này chậm do việc truyền sự kiện và do chúng ngăn chặn nhiều hoạt động tối ưu hoá khi chạy UA.
  • Chúng thường gây ra sự cố. Chúng là nguyên nhân của nhiều sự cố và lỗi bảo mật trong trình duyệt, bởi vì trình nghe sự kiện có thể thay đổi toàn bộ DOM bên dưới một thao tác DOM đang chạy.

Do những lỗi này, các sự kiện này đã không còn được dùng trong thông số kỹ thuật vào năm 2011 và một API thay thế (MutationObserver) đã được xây dựng vào năm 2012. Tính đến thời điểm này, API mới đã được triển khai và hoạt động trong hơn 10 năm.

Lý do xoá sự kiện đột biến

Khả năng hỗ trợ các sự kiện đột biến sẽ khác nhau tuỳ theo trình duyệt. Một số sự kiện (ví dụ: DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument) không được hỗ trợ trong một số trình duyệt. Đối với các sự kiện khác, hành vi cụ thể thay đổi do thiếu thông số kỹ thuật nào được thống nhất. Tuy nhiên, một câu hỏi hợp lý có thể là: tại sao không để chúng ở đó, vì chúng "đã xong" và chúng chỉ làm chậm các trang sử dụng chúng? Câu trả lời có hai phần.

Thứ nhất, những sự kiện này đang cản trở nền tảng web. Khi web phát triển và các API mới được thêm vào, sự tồn tại của các API cũ này phải được xem xét. Đôi khi, chỉ cần hỗ trợ các sự kiện này cũng có thể khiến các API mới không được đề xuất. Ví dụ: có một yêu cầu từ lâu ngăn chặn các phần tử <iframe> tải lại khi chúng được di chuyển bên trong DOM. Tuy nhiên, một phần là do sự tồn tại của các sự kiện đột biến, do nỗ lực đó quá khó đạt được nên yêu cầu đã bị đóng.

Những sự kiện này tiếp tục góp phần giúp trình duyệt hoạt động nhanh hơn. Ngay cả với những tính năng tối ưu hoá mà trình duyệt có nhằm tránh các hình phạt về hiệu suất trên những trang không sử dụng sự kiện đột biến, mọi thứ vẫn không hoàn hảo. Bạn vẫn cần kiểm tra ở nhiều nơi cho trình nghe Sự kiện đột biến. Mã vẫn cần được viết rất phòng vệ, vì những sự kiện này có thể thay đổi DOM theo những cách đáng ngạc nhiên.

Vì đã hơn 10 năm kể từ khi các sự kiện này chính thức không được dùng nữa, và API thay thế cũng đã có mặt trong hơn 10 năm, nên cuối cùng đã đến lúc phải loại bỏ các sự kiện đột biến khỏi trình duyệt.

Cách di chuyển

Sử dụng MutationObserver

Tài liệu về MutationObserver có trên MDN và khá đầy đủ. Việc thay thế cơ sở mã phụ thuộc vào cách sử dụng những sự kiện này. Hãy xem ví dụ dưới đây:

// Old mutation event usage:  
target.addEventListener('DOMNodeInserted',event => doSomething(event.target));

// Replacement mutation observer code:  
const observer = new MutationObserver(mutationList =>  
  mutationList.filter(m => m.type === 'childList').forEach(m => {  
    m.addedNodes.forEach(doSomething);  
  }));  
observer.observe(target,{childList: true, subtree: true});  

Mặc dù mã MutationObserver có vẻ lớn hơn mã trình nghe sự kiện DOMNodeInserted ban đầu, nhưng lưu ý rằng mã này có thể xử lý mọi trường hợp đột biến xảy ra trên toàn bộ cây trong một lệnh gọi, thay vì yêu cầu nhiều lệnh gọi đến trình xử lý sự kiện.

Ống polyfill

Có một tệp polyfill tìm cách cho phép mã hiện có tiếp tục hoạt động trong khi vẫn được MutationObserver cung cấp. Polyfill nằm trên GitHub hoặc dưới dạng gói npm.

Thông tin về tiến trình và việc ngừng sử dụng

Các sự kiện đột biến sẽ bị xoá khỏi Chrome 127 đối với tất cả người dùng* và sẽ có trong Bản phát hành chính thức vào ngày 23 tháng 7 năm 2024. Trước ngày này, chúng tôi sẽ bắt đầu xoá các sự kiện khỏi các kênh Canary, Dev và Beta để cảnh báo sớm.

  • Nếu cần thêm thời gian (ngoài tháng 7 năm 2024) để di chuyển mã, bạn có thể tham khảo Bản dùng thử ngừng hoạt động để tạm thời bật lại những sự kiện đó trên những trang web được chỉ định. Ngoài ra, chúng tôi còn có một Chính sách doanh nghiệp tên là MutationEventsEnabled. Chính sách này hoạt động theo cách tương tự dành cho người dùng doanh nghiệp. Một trong hai phương án này sẽ cho bạn thêm khoảng 9 tháng để di chuyển (nếu cần).