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à kế hoạch xoá 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 khi chúng tôi 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à có kế hoạch xoá chế độ hỗ trợ kể từ phiên bản 127, phiên bản này sẽ chuyển sang 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 tôi xoá các sự kiện đột biến và cung cấp đường dẫn để di chuyển trước khi các sự kiện đó 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:

  • 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 đã cũ trong thông số kỹ thuật DOM cấp 2 và đã không được dùng nữa kể từ năm 2011. Chúng đượ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.

Nhật ký sự kiện đột biến

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

  • Chi tiết và kích hoạt quá thường xuyên. Một sự kiện được kích hoạt cho mỗi nút bị xoá.
  • Các hoạt động này chậm do quá trình truyền sự kiện và vì chúng ngăn chặn nhiều hoạt động tối ưu hoá khi chạy trên UA.
  • Chúng thường gây ra sự cố. Chúng là nguồn gốc gây ra nhiều sự cố và lỗi bảo mật trong trình duyệt, 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 đã không được dùng nữa trong quy cách 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 được hơn 10 năm.

Lý do hệ thống xoá sự kiện đột biến

Khả năng hỗ trợ các sự kiện đột biến sẽ khác nhau trên các trình duyệt. Một số sự kiện, chẳng hạn như 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ể sẽ thay đổi do thiếu bất kỳ thông số kỹ thuật đã được thống nhất nào. Tuy nhiên, một câu hỏi hợp lý có thể là: tại sao không chỉ để chúng ở đó, vì chúng "đã xong" và chúng chỉ làm chậm những trang sử dụng chúng? Câu trả lời gồm hai phần.

Thứ nhất, những sự kiện này đang ngăn nền tảng web. Khi web phát triển và các API mới được thêm vào, phải tính đến sự tồn tại của các API cũ này. Đôi khi, chỉ cần hỗ trợ những sự kiện này là có thể ngăn việc đề xuất API mới. Ví dụ: đã có một yêu cầu từ lâu nhằm ngăn các phần tử <iframe> tải lại khi chúng được di chuyể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, nỗ lực đó bị cho là quá khó đạt được và yêu cầu đã được đóng lại.

Những sự kiện này tiếp tục cản trở tốc độ của trình duyệt. Ngay cả với những tối ưu hoá mà các trình duyệt có, cố gắng tránh các hình phạt về hiệu suất trên các trang không sử dụng sự kiện đột biến, mọi thứ cũng không hoàn hảo. Bạn vẫn cần thực hiện bước kiểm tra ở nhiều vị trí đối với trình nghe Sự kiện đột biến. Mã vẫn cần được viết rất phòng thủ, 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ế đã hoạt động tương tự trong hơn 10 năm qua, đã đến lúc cuối cùng phải xoá các sự kiện đột biến khỏi trình duyệt một lần và mãi mãi.

Cách di chuyển

Thay vào đó, hãy sử dụng MutationObserver

Tài liệu về MutationObserver nằm 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, nhưng cụ thể là ví dụ:

// 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 bạn có thể lưu ý rằng mã này có thể xử lý tất cả các độ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.

Vải polyfill

Có một đoạn mã polyfill cố gắng cho phép mã hiện có tiếp tục hoạt động trong khi được MutationObserver cung cấp. Tệp polyfill này 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 bản dùng thử

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*. Phiên bản này sẽ chuyển sang Bản phát hành ổn định vào ngày 23 tháng 7 năm 2024. Chúng tôi sẽ bắt đầu xoá những sự kiện này khỏi các kênh Canary, Dev và Beta trước thời điểm đó để cảnh báo sớm.

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