Intervensi terhadap document.write()

Pernahkah Anda melihat peringatan berikut pada Konsol Developer di Chrome baru-baru ini dan ingin tahu apa itu?

(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 komposabilitas adalah bahwa hal ini menyiratkan tanggung jawab bersama atas pengalaman pengguna. Jika integrasi kurang optimal, pengalaman pengguna akan terpengaruh secara negatif.

Salah satu penyebab performa buruk yang telah diketahui adalah penggunaan document.write() di dalam halaman, khususnya yang menggunakan skrip 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 membangun hierarki DOM dengan menguraikan markup HTML. Setiap kali parser menemukan skrip, parser harus menghentikan dan mengeksekusinya agar dapat melanjutkan penguraian HTML. Jika skrip memasukkan skrip lain secara dinamis, parser akan dipaksa untuk menunggu bahkan lebih lama sampai 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 lebih lambat 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 menggunakan 2G mencakup setidaknya satu skrip pemblokir parser lintas situs yang disisipkan melalui document.write() di dokumen tingkat atas. 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% pemuatan halaman lebih banyak yang mencapai status yang diuraikan sepenuhnya, dan pemuatan ulang halaman 10% lebih sedikit sehingga mengurangi rasa frustrasi pengguna.
  • 21% penurunan waktu rata-rata (lebih cepat satu detik) hingga first contentful paint
  • 38% pengurangan waktu rata-rata yang diperlukan untuk mengurai halaman, yang menggambarkan peningkatan hampir enam detik, yang secara drastis mengurangi waktu yang diperlukan untuk menampilkan hal yang penting bagi pengguna.

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

  1. Pengguna menggunakan koneksi yang lambat, khususnya saat pengguna menggunakan 2G. (Di masa mendatang, perubahan ini mungkin diperluas ke pengguna lain dengan koneksi internet lambat, seperti 3G lambat atau Wi-Fi lambat.)
  2. document.write() berada dalam dokumen tingkat atas. Intervensi ini tidak berlaku untuk skrip document.write dalam iframe karena tidak memblokir rendering halaman utama.
  3. Skrip di document.write() memblokir parser. Skrip dengan atribut 'async' atau 'defer' akan tetap dijalankan.
  4. Skrip tidak dihosting di situs yang sama. Dengan kata lain, Chrome tidak akan melakukan intervensi pada 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 tersebut.

Bagaimana cara memperbaikinya?

Jawaban sederhana ini adalah jangan memasukkan skrip menggunakan document.write(). Kami mengelola serangkaian layanan yang dikenal untuk dukungan loader asinkron, dan sebaiknya Anda terus memeriksanya.

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

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

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

Cara mendeteksi kapan situs Anda terpengaruh

Ada banyak kriteria yang menentukan apakah pembatasan ini diterapkan, jadi bagaimana cara mengetahui apakah Anda terpengaruh?

Mendeteksi saat pengguna menggunakan jaringan 2G

Untuk memahami potensi dampak perubahan ini, Anda harus terlebih dahulu memahami jumlah pengguna yang akan menggunakan 2G. 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.
}

Peringatan umum di Chrome DevTools

Mulai Chrome 53, DevTools mengeluarkan peringatan untuk pernyataan document.write() yang bermasalah. Khususnya, jika permintaan document.write() memenuhi kriteria 2 sampai 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 Anda 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 berbagai situasi, Chrome dapat mengirim:

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

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

Apa yang ada di masa depan?

Rencana awalnya adalah menjalankan intervensi ini saat kami mendeteksi kriteria yang terpenuhi. Kami mulai dengan hanya menampilkan peringatan di Konsol Developer pada Chrome 53. (Beta pada Juli 2016. Kami berharap Stabil akan tersedia bagi semua pengguna pada September 2016.)

Kami akan melakukan intervensi untuk memblokir skrip yang dimasukkan untuk pengguna 2G untuk sementara mulai dari Chrome 54, yang diperkirakan akan menjadi rilis stabil untuk semua pengguna pada pertengahan Oktober 2016. Lihat entri Status Chrome untuk mengetahui info terbaru lainnya.

Seiring waktu, kami ingin mengintervensi saat setiap 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: