Intervensi terhadap document.write()

Apakah Anda baru-baru ini melihat peringatan seperti berikut di Konsol Developer di Chrome dan ingin tahu apa maksudnya?

(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.

Composability adalah salah satu kekuatan besar web, memungkinkan kami dengan mudah berintegrasi dengan layanan yang dibuat oleh pihak ketiga untuk membuat produk baru yang hebat. Salah satu kelemahan composability adalah bahwa composability menyiratkan tanggung jawab bersama atas pengalaman pengguna. Jika integrasi kurang optimal, pengalaman pengguna akan terpengaruh secara negatif.

Salah satu penyebab umum performa yang buruk adalah penggunaan document.write() di dalam halaman, terutama penggunaan yang memasukkan skrip. Meskipun terlihat tidak berbahaya, teknologi ini dapat menyebabkan masalah nyata bagi pengguna.

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

Sebelum dapat merender halaman, browser harus membuat hierarki DOM dengan mengurai markup HTML. Setiap kali parser menemukan skrip, parser harus berhenti dan mengeksekusinya sebelum dapat melanjutkan pemrosesan HTML. Jika skrip memasukkan skrip lain secara dinamis, parser terpaksa menunggu lebih lama agar resource didownload, yang dapat menyebabkan satu atau beberapa roundtrip jaringan dan menunda waktu render pertama halaman

Untuk pengguna dengan koneksi lambat, seperti 2G, skrip eksternal yang dimasukkan secara dinamis melalui document.write() dapat menunda tampilan konten halaman utama selama puluhan detik, atau menyebabkan halaman gagal dimuat atau memerlukan waktu terlalu lama sehingga pengguna menyerah. Berdasarkan instrumentasi di Chrome, kami telah mempelajari bahwa halaman yang menampilkan skrip pihak ketiga yang disisipkan melalui document.write() biasanya dua kali lipat lebih lambat untuk dimuat daripada halaman lain di 2G.

Kami mengumpulkan data dari uji coba lapangan 28 hari pada 1% pengguna stabil Chrome, yang dibatasi untuk pengguna koneksi 2G. Kami melihat bahwa 7, 6% dari semua pemuatan halaman di 2G menyertakan setidaknya satu skrip pemblokir parser lintas situs yang disisipkan melalui document.write() dalam dokumen tingkat teratas. Akibat memblokir pemuatan skrip ini, kami melihat peningkatan berikut pada pemuatan tersebut:

  • 10% lebih banyak pemuatan halaman yang mencapai first contentful paint (konfirmasi visual bagi pengguna bahwa halaman dimuat secara efektif), 25% lebih banyak pemuatan halaman yang mencapai status yang sepenuhnya diuraikan, dan 10% lebih sedikit pemuatan ulang yang menunjukkan penurunan rasa frustrasi pengguna.
  • Penurunan waktu rata-rata sebesar 21% (lebih cepat satu detik) hingga first contentful paint
  • Pengurangan 38% pada waktu rata-rata yang diperlukan untuk mengurai halaman, yang mewakili peningkatan waktu hampir enam detik, sehingga mengurangi waktu yang diperlukan untuk menampilkan hal-hal yang penting bagi pengguna secara drastis.

Dengan mempertimbangkan data ini, Chrome, mulai versi 55, mencampuri atas nama semua pengguna saat kami mendeteksi pola buruk yang diketahui ini dengan mengubah cara document.write() ditangani di Chrome (Lihat Status Chrome). Secara khusus, Chrome tidak akan mengeksekusi elemen <script> yang dimasukkan melalui document.write() jika semua kondisi berikut terpenuhi:

  1. Pengguna menggunakan koneksi lambat, terutama saat pengguna menggunakan 2G. (Pada masa mendatang, perubahan ini mungkin diperluas ke pengguna lain yang menggunakan koneksi lambat, seperti 3G lambat atau Wi-Fi lambat.)
  2. document.write() berada dalam dokumen tingkat teratas. Intervensi ini tidak berlaku untuk skrip document.written dalam iframe karena tidak memblokir rendering halaman utama.
  3. Skrip di document.write() adalah pemblokir parser. Skrip dengan atribut 'async' atau 'defer' akan tetap dijalankan.
  4. Skrip tidak dihosting di situs yang sama. Dengan kata lain, Chrome tidak akan mengintervensi skrip dengan eTLD+1 yang cocok (misalnya, skrip yang dihosting di js.example.org yang disisipkan di www.example.org).
  5. Skrip belum ada di cache HTTP browser. Skrip dalam cache tidak akan mengalami penundaan jaringan dan akan tetap dijalankan.
  6. Permintaan untuk halaman tersebut bukan pemuatan ulang. Chrome tidak akan melakukan intervensi jika pengguna memicu pemuatan ulang dan akan menjalankan halaman seperti biasa.

Cuplikan pihak ketiga terkadang menggunakan document.write() untuk memuat skrip. Untungnya, sebagian besar pihak ketiga menyediakan alternatif pemuatan asinkron, yang memungkinkan skrip pihak ketiga dimuat tanpa memblokir tampilan konten lainnya di halaman.

Bagaimana cara mengatasinya?

Jawaban sederhananya adalah jangan memasukkan skrip menggunakan document.write(). Kami mengelola serangkaian layanan yang diketahui untuk dukungan loader asinkron yang sebaiknya Anda terus periksa.

Jika penyedia Anda tidak ada dalam daftar dan mendukung pemuatan skrip asinkron, beri tahu kami dan kami dapat memperbarui halaman untuk membantu semua pengguna.

Jika penyedia Anda tidak mendukung kemampuan untuk memuat skrip secara asinkron ke halaman, sebaiknya hubungi penyedia tersebut dan beri tahu kami dan mereka bagaimana hal ini akan memengaruhi mereka.

Jika penyedia memberi Anda cuplikan yang menyertakan document.write(), Anda mungkin dapat menambahkan atribut async ke elemen skrip, atau menambahkan elemen skrip dengan DOM API seperti document.appendChild() atau parentNode.insertBefore().

Cara mendeteksi kapan situs Anda terpengaruh

Ada banyak kriteria yang menentukan apakah batasan diterapkan, jadi bagaimana Anda tahu apakah Anda terpengaruh?

Mendeteksi saat pengguna menggunakan jaringan 2G

Untuk memahami potensi dampak perubahan ini, Anda harus memahami jumlah pengguna yang akan menggunakan 2G terlebih dahulu. Anda dapat mendeteksi jenis dan kecepatan jaringan pengguna saat ini dengan menggunakan Network Information API yang tersedia di Chrome, lalu mengirimkan peringatan ke sistem Analytics atau Real User Metrics (RUM) Anda.

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.
}

Menangkap peringatan di Chrome DevTools

Sejak Chrome 53, DevTools mengeluarkan peringatan untuk pernyataan document.write() yang bermasalah. Secara khusus, jika permintaan document.write() memenuhi kriteria 2 hingga 5 (Chrome mengabaikan kriteria koneksi saat mengirim peringatan ini), peringatan akan terlihat seperti:

Peringatan penulisan dokumen.

Melihat peringatan di Chrome DevTools bagus, tetapi bagaimana Anda mendeteksinya dalam skala besar? Anda dapat memeriksa header HTTP yang dikirim ke server saat intervensi terjadi.

Periksa header HTTP Anda di resource skrip

Jika skrip yang disisipkan melalui document.write telah diblokir, Chrome akan mengirim header berikut ke resource yang diminta:

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

Jika skrip yang disisipkan melalui document.write ditemukan dan dapat diblokir dalam situasi yang berbeda, Chrome mungkin mengirim:

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

Header intervensi akan dikirim sebagai bagian dari permintaan GET untuk skrip (secara asinkron jika terjadi intervensi yang sebenarnya).

Apa yang ada di masa depan?

Rencana awal adalah menjalankan intervensi ini saat kami mendeteksi bahwa kriteria telah terpenuhi. Kami memulai dengan hanya menampilkan peringatan di Konsol Play di Chrome 53. (Versi Beta dirilis pada Juli 2016. Kami memperkirakan Versi Stabil akan tersedia untuk semua pengguna pada September 2016.)

Kami akan melakukan intervensi untuk memblokir skrip yang dimasukkan untuk pengguna 2G, yang diperkirakan akan dirilis dalam versi stabil untuk semua pengguna pada pertengahan Oktober 2016. Lihat entri Status Chrome untuk mengetahui info terbaru lainnya.

Seiring waktu, kami ingin melakukan intervensi saat pengguna memiliki koneksi yang lambat (yaitu, 3G atau Wi-Fi yang lambat). Ikuti entri Status Chrome ini.

Ingin mempelajari lebih lanjut?

Untuk mempelajari lebih lanjut, lihat referensi tambahan berikut: