Can thiệp vào document.write()

Gần đây, bạn có thấy cảnh báo như sau trong Bảng điều khiển dành cho nhà phát triển của mình trong Chrome và thắc mắc về trình duyệt này?

(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.

Khả năng tương thích là một trong những sức mạnh to lớn của web, cho phép chúng tôi dễ dàng tích hợp với các dịch vụ do bên thứ ba phát triển để tạo ra các sản phẩm mới tuyệt vời! Một nhược điểm của tính dễ kết hợp là nó ngụ ý trách nhiệm chung trải nghiệm người dùng. Nếu quá trình tích hợp chưa đạt hiệu quả tối ưu, thì trải nghiệm người dùng sẽ bị ảnh hưởng tiêu cực.

Một nguyên nhân đã biết dẫn đến hiệu suất kém là việc sử dụng document.write() bên trong các trang, cụ thể là những cách sử dụng chèn tập lệnh. Vô hại như sau có thể gây ra vấn đề thực sự cho người dùng.

document.write('<script src="https://example.com/ad-inject.js"></script>');

Trước khi trình duyệt có thể hiển thị một trang, trình duyệt phải xây dựng cây DOM bằng cách phân tích cú pháp đánh dấu HTML. Bất cứ khi nào trình phân tích cú pháp gặp một tập lệnh, trình phân tích cú pháp sẽ phải dừng và thực thi tập lệnh đó trước khi có thể tiếp tục phân tích cú pháp HTML. Nếu tập lệnh tự động chèn một tập lệnh khác, trình phân tích cú pháp buộc phải đợi lâu hơn để tải xuống tài nguyên, điều này có thể phải chịu một hoặc nhiều lần truyền vòng mạng và trì hoãn thời gian hiển thị trang lần đầu

Đối với những người dùng có kết nối chậm, chẳng hạn như 2G, các tập lệnh bên ngoài sẽ linh động được chèn qua document.write() có thể làm chậm việc hiển thị nội dung trang chính trong hàng chục giây hoặc khiến trang không tải được hoặc mất quá nhiều thời gian để bỏ cuộc. Dựa trên khả năng đo lường trong Chrome, chúng tôi đã nhận thấy rằng các trang có tập lệnh của bên thứ ba được chèn qua document.write() đang thường tải chậm gấp hai lần so với các trang khác trên mạng 2G.

Chúng tôi đã thu thập dữ liệu từ giai đoạn thử nghiệm thực địa trong 28 ngày trên 1% Chrome người dùng ổn định, chỉ dành cho người dùng sử dụng kết nối 2G. Chúng tôi nhận thấy có 7,6% tổng số lượt tải trang trên 2G có ít nhất một tập lệnh chặn trình phân tích cú pháp, trên nhiều trang web được chèn qua document.write() trong tài liệu cấp cao nhất. Kết quả của việc chặn khi tải các tập lệnh này, chúng tôi đã thấy các điểm cải tiến sau đây đối với các lượt tải đó:

  • Tăng 10% lượt tải trang đạt được nội dung đầu tiên hiển thị (thông báo xác nhận bằng hình ảnh để người dùng biết rằng trang đang tải hiệu quả), Thêm 25% lượt tải trang đạt đến trạng thái được phân tích cú pháp đầy đủ và giảm 10% số lần tải lại gợi ý làm giảm sự thất vọng của người dùng.
  • giảm 21% thời gian trung bình (nhanh hơn 1 giây) cho đến khi nội dung đầu tiên hiển thị
  • giảm 38% thời gian trung bình cần thiết để phân tích cú pháp một trang, giúp giảm cải thiện gần 6 giây, giúp giảm đáng kể thời gian cần để hiển thị những thông tin quan trọng đối với người dùng.

Với dữ liệu này, Chrome, kể từ phiên bản 55, can thiệp thay mặt cho tất cả mọi người người dùng khi chúng tôi phát hiện mẫu hình ảnh không hợp lệ này bằng cách thay đổi cách document.write() đã xử lý trong Chrome (Xem Trạng thái Chrome). Cụ thể, Chrome sẽ không thực thi các phần tử <script> được chèn qua document.write() khi tất cả điều kiện sau được đáp ứng:

  1. Người dùng đang sử dụng kết nối chậm, đặc biệt là khi người dùng sử dụng 2G. (Trong thì trong tương lai, thay đổi này có thể được áp dụng cho những người dùng khác trên các kết nối chậm, chẳng hạn như 3G chậm hoặc Wi-Fi chậm.)
  2. document.write() nằm trong một tài liệu cấp cao nhất. Biện pháp can thiệp này không áp dụng cho các tập lệnh document.writer trong iframe vì chúng không chặn hiển thị trang chính.
  3. Tập lệnh trong document.write() đang chặn trình phân tích cú pháp. Tập lệnh có "async" hoặc "defer" thì các thuộc tính vẫn sẽ thực thi.
  4. Tập lệnh không được lưu trữ trên cùng một trang web. Nói cách khác, Chrome sẽ không được can thiệp vào các tập lệnh có eTLD+1 phù hợp (ví dụ: tập lệnh được lưu trữ trên js.example.org được chèn trên www.example.org).
  5. Tập lệnh chưa có trong bộ nhớ đệm HTTP của trình duyệt. Các tập lệnh trong bộ nhớ đệm sẽ không bị trễ mạng và vẫn thực thi.
  6. Yêu cầu cho trang không phải là tải lại. Chrome sẽ không can thiệp nếu người dùng đã kích hoạt tải lại và sẽ thực thi trang như bình thường.

Đôi khi, đoạn mã của bên thứ ba sử dụng document.write() để tải tập lệnh. May mắn là hầu hết các bên thứ ba đều cung cấp phương án tải không đồng bộ cho phép các tập lệnh bên thứ ba tải mà không chặn việc hiển thị phần còn lại nội dung trên trang.

Làm cách nào để khắc phục lỗi này?

Câu trả lời đơn giản này là không chèn tập lệnh bằng document.write(). T4 duy trì một tập hợp các dịch vụ đã biết để hỗ trợ trình tải không đồng bộ mà bạn nên tiếp tục kiểm tra.

Nếu nhà cung cấp của bạn không có trong danh sách và có hỗ trợ tải tập lệnh không đồng bộ thì vui lòng cho chúng tôi biết để chúng tôi có thể cập nhật trang này để trợ giúp tất cả người dùng.

Nếu nhà cung cấp của bạn không hỗ trợ khả năng tải không đồng bộ tập lệnh vào trang của bạn, thì bạn nên liên hệ với họ và cho chúng tôi và họ biết chúng sẽ bị ảnh hưởng như thế nào.

Nếu nhà cung cấp cung cấp cho bạn một đoạn mã bao gồm document.write(), bạn có thể thêm thuộc tính async vào phần tử của tập lệnh hoặc bạn có thể thêm các thành phần của tập lệnh bằng các API DOM như document.appendChild() hoặc parentNode.insertBefore().

Cách phát hiện khi nào trang web của bạn bị ảnh hưởng

Có một số lượng lớn tiêu chí để xác định liệu quy định hạn chế này có được thực thi hay không, thì làm cách nào để biết liệu bạn có bị ảnh hưởng hay không?

Phát hiện khi người dùng đang sử dụng 2G

Để hiểu tác động tiềm năng của thay đổi này, trước tiên, bạn cần hiểu bao nhiêu người dùng của bạn sẽ sử dụng mạng 2G. Bạn có thể phát hiện loại mạng hiện tại của người dùng và tốc độ bằng cách sử dụng Network Information API có trong Chrome, sau đó gửi thông báo số liệu phân tích hoặc Chỉ số người dùng thực (RUM).

if(navigator.connection &&
    navigator.connection.type === 'cellular' &&
    navigator.connection.downlinkMax <= 0.115) {
    // Notify your service to indicate that you might be affected by this restriction.
}

Phát hiện cảnh báo trong Công cụ của Chrome cho nhà phát triển

Kể từ Chrome 53, Công cụ cho nhà phát triển sẽ đưa ra cảnh báo cho document.write() có vấn đề tuyên bố. Cụ thể, nếu một yêu cầu document.write() đáp ứng tiêu chí từ 2 đến 5 (Chrome bỏ qua các tiêu chí kết nối khi gửi cảnh báo này), cảnh báo này sẽ sẽ có dạng như sau:

Cảnh báo ghi tài liệu.

Việc nhìn thấy cảnh báo trong Công cụ của Chrome cho nhà phát triển là rất hữu ích, nhưng làm cách nào để bạn phát hiện điều này tại quy mô không? Bạn có thể kiểm tra tiêu đề HTTP được gửi tới máy chủ của mình khi can thiệp.

Kiểm tra tiêu đề HTTP trên tài nguyên tập lệnh

Khi một tập lệnh được chèn qua document.write bị chặn, Chrome sẽ gửi sau tiêu đề vào tài nguyên được yêu cầu:

Intervention: <https://shorturl/relevant/spec>;

Khi tìm thấy một tập lệnh được chèn qua document.write và có thể bị chặn trong trường hợp khác, Chrome có thể gửi:

Intervention: <https://shorturl/relevant/spec>; level="warning"

Tiêu đề can thiệp sẽ được gửi như một phần của yêu cầu GET cho tập lệnh (không đồng bộ trong trường hợp có sự can thiệp thực tế).

Tương lai nắm giữ điều gì?

Kế hoạch ban đầu là thực hiện biện pháp can thiệp này khi chúng tôi phát hiện thấy các tiêu chí được đáp ứng. Chúng tôi bắt đầu với việc chỉ hiển thị một cảnh báo trong Developer Console trong Chrome 53. (Phiên bản thử nghiệm beta diễn ra vào tháng 7 năm 2016. Chúng tôi dự kiến phiên bản ổn định sẽ được cung cấp cho tất cả người dùng tại Tháng 9 năm 2016.)

Chúng tôi sẽ can thiệp để chặn các tập lệnh được chèn vào cho người dùng 2G ở thời điểm hiện tại Chrome 54, được ước tính là sẽ có bản phát hành ổn định cho tất cả người dùng ở giữa tháng 10 năm 2016. Xem Mục Trạng thái của Chrome để biết thêm nội dung cập nhật.

Theo thời gian, chúng tôi sẽ tìm cách can thiệp khi bất kỳ người dùng nào có kết nối chậm (ví dụ: 3G hoặc Wi-Fi chậm). Làm theo mục Trạng thái Chrome này.

Bạn muốn tìm hiểu thêm?

Để tìm hiểu thêm, hãy xem các tài nguyên bổ sung sau: