Intervensi terhadap document.write()

Apakah baru-baru ini Anda melihat peringatan seperti berikut pada 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.

Kemudahan untuk disusun adalah salah satu kekuatan besar web, yang memungkinkan kita untuk mudah berintegrasi dengan layanan yang dibuat oleh pihak ketiga untuk membuat produk baru yang hebat. Salah satu kelemahan dari {i>composability<i} adalah bahwa hal ini menyiratkan tanggung jawab bersama atas pengalaman pengguna. Jika integrasi kurang optimal, pengalaman pengguna akan terkena dampak negatif.

Salah satu penyebab performa buruk yang diketahui adalah penggunaan document.write() di dalam halaman, terutama yang menggunakan skrip yang memasukkan skrip. Meskipun terlihat tidak berbahaya, hal 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 berhenti dan mengeksekusinya sebelum dapat melanjutkan penguraian HTML. Jika skrip memasukkan skrip lain secara dinamis, parser akan dipaksa menunggu lebih lama lagi sampai resource didownload, yang dapat mengakibatkan satu atau beberapa roundtrip jaringan dan menunda waktu rendering pertama halaman

Untuk pengguna dengan koneksi internet yang 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 memakan waktu lama sehingga pengguna menyerah. Berdasarkan instrumentasi di Chrome, kami mengetahui bahwa halaman yang menampilkan skrip pihak ketiga yang dimasukkan melalui document.write() biasanya dua kali lebih lambat untuk dimuat daripada halaman lain di jaringan 2G.

Kami mengumpulkan data dari uji coba lapangan selama 28 hari pada 1% pengguna Chrome versi stabil, yang dibatasi untuk pengguna yang menggunakan koneksi 2G. Kami mendapati bahwa 7, 6% dari semua pemuatan halaman di jaringan 2G menyertakan setidaknya satu skrip pemblokir parser lintas situs yang disisipkan melalui document.write() pada dokumen tingkat atas. Akibat pemblokiran 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 terurai sepenuhnya, dan pemuatan ulang 10% lebih sedikit yang menunjukkan penurunan frustrasi pengguna.
  • 21% penurunan waktu rata-rata (lebih dari satu detik lebih cepat) hingga first contentful paint
  • 38% mengurangi waktu rata-rata yang diperlukan untuk mengurai halaman, yang menunjukkan peningkatan hampir enam detik, sehingga secara drastis mengurangi waktu yang diperlukan untuk menampilkan hal yang penting bagi pengguna.

Dengan mempertimbangkan data ini, Chrome, mulai dari versi 55, akan mengintervensi atas nama 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. Koneksi pengguna lambat, khususnya saat pengguna menggunakan jaringan 2G. (Di masa mendatang, perubahan ini mungkin akan diperluas ke pengguna lain dengan koneksi internet lambat, seperti 3G lambat atau Wi-Fi yang lambat.)
  2. document.write() ada di 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' tetap akan dijalankan.
  4. Skrip tidak di-host 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 menyebabkan penundaan jaringan dan akan tetap dijalankan.
  6. Permintaan untuk halaman 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 memperbaikinya?

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

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

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

Jika penyedia memberi Anda cuplikan yang menyertakan document.write(), Anda 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 sejumlah besar kriteria yang menentukan apakah pembatasan ditegakkan atau tidak, jadi bagaimana Anda tahu apakah Anda terkena dampak?

Mendeteksi saat pengguna terhubung ke jaringan 2G

Untuk memahami dampak potensial dari perubahan ini, Anda harus terlebih dahulu memahami berapa banyak pengguna Anda yang akan menggunakan jaringan 2G. Anda dapat mendeteksi jenis dan kecepatan jaringan pengguna saat ini dengan menggunakan Network Information API yang tersedia di Chrome, lalu mengirimkan pemberitahuan ke sistem Analisis 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. Khususnya, jika permintaan document.write() memenuhi kriteria 2 hingga 5 (Chrome mengabaikan kriteria koneksi saat mengirim peringatan ini), peringatan akan terlihat seperti ini:

Peringatan penulisan dokumen.

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

Periksa header HTTP Anda pada resource skrip

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

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

Jika skrip yang disisipkan melalui document.write ditemukan dan dapat diblokir dalam keadaan lain, Chrome dapat mengirimkan:

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 kriteria yang terpenuhi. Kami mulai dengan hanya menampilkan peringatan di Konsol Play pada Chrome 53. (Versi Beta dirilis pada Juli 2016. Kami berharap Stabil tersedia untuk semua pengguna pada September 2016.)

Kami akan melakukan intervensi untuk memblokir skrip yang dimasukkan untuk pengguna 2G yang sementara ini dimulai di Chrome 54, yang diperkirakan akan menjadi rilis stabil untuk semua pengguna pada pertengahan Oktober 2016. Lihat entri Status Chrome untuk mengetahui update selengkapnya.

Seiring waktu, kami akan melakukan intervensi jika pengguna memiliki koneksi internet yang lambat (yaitu, 3G atau WiFi yang lambat). Ikuti entri Status Chrome ini.

Ingin mempelajari lebih lanjut?

Untuk mempelajari lebih lanjut, lihat referensi tambahan ini: