การขัดขวาง document.write()

เมื่อเร็วๆ นี้คุณเห็นคำเตือนที่มีลักษณะดังต่อไปนี้ใน Developer Console ใน Chrome คืออะไร

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

ความสามารถในการเขียนเป็นหนึ่งในพลังที่ยอดเยี่ยมของเว็บ ช่วยให้เรา ผสานรวมกับบริการที่สร้างโดยบุคคลที่สามเพื่อสร้างผลิตภัณฑ์ใหม่ๆ ที่ยอดเยี่ยม หนึ่ง ของข้อเสียของความสามารถในการเขียน คือการแสดงออกถึงความรับผิดชอบร่วมกัน มากกว่าประสบการณ์ของผู้ใช้ หากการผสานรวมทำงานได้ไม่ดี ประสบการณ์ของผู้ใช้ จะได้รับผลกระทบเชิงลบ

หนึ่งในสาเหตุที่ทราบว่าให้ประสิทธิภาพไม่ดีคือการใช้ document.write() หน้าเว็บภายใน โดยเฉพาะอย่างยิ่งผู้ที่ใช้สคริปต์แทรก ดังเช่นเรื่องราวต่อไปนี้ อาจสร้างปัญหาที่แท้จริงให้กับผู้ใช้

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

ก่อนที่เบราว์เซอร์จะแสดงผลหน้าเว็บได้ เบราว์เซอร์จะต้องสร้างแผนผัง DOM โดยการแยกวิเคราะห์มาร์กอัป HTML เมื่อใดก็ตามที่โปรแกรมแยกวิเคราะห์พบสคริปต์ โปรแกรมแยกวิเคราะห์จะต้องหยุดและดำเนินการก่อนจึงจะดำเนินการต่อได้ การแยกวิเคราะห์ HTML หากสคริปต์แทรกสคริปต์อื่นแบบไดนามิก โปรแกรมแยกวิเคราะห์จะบังคับให้รอ ทรัพยากรในการดาวน์โหลดนานขึ้นไปอีก ซึ่งอาจส่งผลให้เกิดการรับส่งข้อมูลไปกลับของเครือข่ายอย่างน้อย 1 ครั้งและ เลื่อนเวลาในการแสดงผลหน้าเว็บครั้งแรก

สำหรับผู้ใช้ที่การเชื่อมต่อช้า เช่น 2G สคริปต์ภายนอกแบบไดนามิก ที่แทรกผ่าน document.write() อาจทำให้การแสดงเนื้อหาหลักของหน้าล่าช้าสำหรับ หลายสิบวินาที หรือทำให้หน้าเว็บโหลดไม่สำเร็จหรือใช้เวลานานจน ผู้ใช้ยอมแพ้ เมื่อพิจารณาจากการใช้เครื่องมือใน Chrome เราได้ทราบว่า หน้าเว็บที่แสดงสคริปต์ของบุคคลที่สามที่แทรกผ่าน document.write() โดยปกติจะโหลดช้ากว่าหน้าอื่นๆ ในเครือข่าย 2G ถึง 2 เท่า

เรารวบรวมข้อมูลจากช่วงทดลองใช้ 28 วันเกี่ยวกับ 1% ของ Chrome ผู้ใช้แบบคงที่ ซึ่งจำกัดไว้สำหรับผู้ใช้ที่ใช้การเชื่อมต่อ 2G เราพบว่า 7.6% ของการโหลดหน้าเว็บทั้งหมด ในเครือข่าย 2G มีสคริปต์บล็อกโปรแกรมแยกวิเคราะห์แบบข้ามเว็บไซต์อย่างน้อย 1 สคริปต์ แทรกผ่าน document.write() ในเอกสารระดับบนสุด เป็นผลมาจากการบล็อก การโหลดสคริปต์เหล่านี้ เราได้เห็นการปรับปรุงต่อไปนี้ในการโหลดเหล่านั้น:

  • มีการโหลดหน้าเว็บเพิ่มขึ้นจนถึง 10% First Contentful Paint (ภาพยืนยันแก่ผู้ใช้ว่าหน้าเว็บกำลังโหลดอย่างมีประสิทธิภาพ) การโหลดหน้าเว็บเพิ่มขึ้น 25% ถึงสถานะการแยกวิเคราะห์เสร็จสมบูรณ์ และการโหลดซ้ำลดลง 10% แสดงถึงความไม่พอใจของผู้ใช้ที่ลดลง
  • เวลาเฉลี่ยลดลง 21% (เร็วกว่า 1 วินาที) จนถึง First Contentful Paint
  • เวลาเฉลี่ยในการแยกวิเคราะห์หน้าเว็บลดลง 38% โดยจะแสดงถึง ระยะเวลาที่ดีขึ้นเกือบ 6 วินาที ซึ่งช่วยลดเวลาได้อย่างมาก ที่ใช้เพื่อแสดงสิ่งที่สำคัญต่อผู้ใช้

จากข้อมูลนี้ Chrome ตั้งแต่เวอร์ชัน 55 เป็นต้นไป แทรกแซงในนามของทุกคน เมื่อตรวจพบรูปแบบไม่ดีที่รู้จักนี้โดยเปลี่ยนวิธีที่ document.write() จัดการใน Chrome (ดูสถานะ Chrome) โดยเฉพาะอย่างยิ่ง Chrome จะไม่เรียกใช้เอลิเมนต์ <script> ที่แทรกผ่าน document.write() เมื่อเป็นไปตามเงื่อนไขทั้งหมดต่อไปนี้

  1. ผู้ใช้อยู่ในการเชื่อมต่อที่ช้า โดยเฉพาะเมื่อผู้ใช้ใช้ 2G (ใน ในอนาคต การเปลี่ยนแปลงอาจมีผลกับผู้ใช้คนอื่นๆ ที่การเชื่อมต่อช้า เช่น 3G หรือ WiFi ช้า)
  2. document.write() อยู่ในเอกสารระดับบนสุด การฝึกฝนจะไม่ ใช้กับสคริปต์ document.write ภายใน iframe เนื่องจากไม่บล็อก ในการแสดงภาพหน้าหลัก
  3. สคริปต์ใน document.write() กำลังบล็อกโปรแกรมแยกวิเคราะห์ เขียนสคริปต์ด้วย "async" หรือ "defer" จะยังคงดำเนินการอยู่
  4. สคริปต์ไม่ได้โฮสต์อยู่ในเว็บไซต์เดียวกัน กล่าวคือ Chrome จะ แทรกแซงสคริปต์ที่มี eTLD+1 ตรงกัน (เช่น สคริปต์ที่โฮสต์ js.example.org ที่แทรกใน www.example.org)
  5. สคริปต์ไม่ได้อยู่ในแคช HTTP ของเบราว์เซอร์แล้ว สคริปต์ในแคช จะไม่ก่อให้เกิดความล่าช้าของเครือข่ายและจะยังคงดำเนินการอยู่
  6. คำขอสำหรับหน้านี้ไม่ใช่การโหลดซ้ำ Chrome จะไม่แทรกแซงหาก ผู้ใช้ ได้ทริกเกอร์การโหลดซ้ำและจะดำเนินการหน้าเว็บตามปกติ

บางครั้งข้อมูลโค้ดของบุคคลที่สามจะใช้ document.write() เพื่อโหลดสคริปต์ โชคดีที่บุคคลที่สามส่วนใหญ่ ทางเลือกการโหลดแบบอะซิงโครนัส อนุญาตให้สคริปต์ของบุคคลที่สามโหลดโดยไม่บล็อกการแสดงส่วนที่เหลือ เนื้อหาบนหน้าเว็บนั้นๆ

ฉันจะแก้ไขปัญหานี้ได้อย่างไร

คำตอบง่ายๆ นี้คือไม่แทรกสคริปต์โดยใช้ document.write() พ ดูแลรักษาชุดบริการที่รู้จักสำหรับการรองรับตัวโหลดแบบอะซิงโครนัส เราขอแนะนำให้คุณคอยตรวจสอบอยู่เสมอ

หากผู้ให้บริการของคุณไม่อยู่ในรายชื่อและรองรับการโหลดสคริปต์แบบไม่พร้อมกัน โปรดแจ้งให้เราทราบ เพื่อที่เราจะได้อัปเดตหน้านี้เพื่อช่วยเหลือผู้ใช้ทุกคน

หากผู้ให้บริการของคุณไม่รองรับความสามารถในการโหลดสคริปต์แบบอะซิงโครนัส ในหน้าเว็บของคุณ เราขอแนะนำให้คุณติดต่อพวกเขา และ แจ้งให้เราและพวกเขาทราบ จะได้รับผลกระทบอย่างไร

หากผู้ให้บริการให้ข้อมูลโค้ดที่มี document.write() แก่คุณ อาจให้คุณเพิ่มแอตทริบิวต์ async ลงในองค์ประกอบของสคริปต์ หรือ เพื่อให้คุณเพิ่มองค์ประกอบของสคริปต์ด้วย DOM API เช่น document.appendChild() หรือ parentNode.insertBefore()

วิธีตรวจหาเมื่อเว็บไซต์ของคุณได้รับผลกระทบ

มีเกณฑ์จำนวนมากที่กำหนดว่าจะมีการบังคับใช้ข้อจำกัดหรือไม่ แล้วจะรู้ได้อย่างไรว่าได้รับผลกระทบ

ตรวจจับเมื่อผู้ใช้ใช้งาน 2G

คุณต้องทําความเข้าใจผลกระทบที่อาจเกิดขึ้นจากการเปลี่ยนแปลงนี้ก่อน จำนวนผู้ใช้ที่จะใช้ 2G คุณสามารถตรวจหาประเภทเครือข่ายปัจจุบันของผู้ใช้ได้ และเพิ่มความเร็วได้โดยใช้ Network Information API ที่ มีอยู่ใน Chrome แล้วส่งคำเตือนไปยังการวิเคราะห์หรือเมตริกผู้ใช้จริง (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.
}

ตรวจจับคำเตือนในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

ตั้งแต่ Chrome 53 เครื่องมือสำหรับนักพัฒนาเว็บออกคำเตือนสำหรับ document.write() ที่เป็นปัญหา ข้อความ กล่าวอย่างเจาะจงคือ หากคำขอ document.write() ตรงตามเกณฑ์ 2 ถึง 5 (Chrome จะไม่สนใจเกณฑ์การเชื่อมต่อเมื่อส่งคำเตือนนี้) คำเตือนจะ มีลักษณะดังนี้

คำเตือนในการเขียนเอกสาร

การเห็นคำเตือนใน Chrome DevTools เป็นเรื่องดี แต่คุณจะตรวจพบได้อย่างไรที่ หรือไม่ คุณสามารถตรวจสอบส่วนหัว HTTP ที่ส่งไปยังเซิร์ฟเวอร์ของคุณเมื่อ ให้สำเร็จได้

ตรวจสอบส่วนหัว HTTP ในทรัพยากรของสคริปต์

เมื่อสคริปต์ที่แทรกผ่าน document.write ถูกบล็อก Chrome จะส่ง ส่วนหัวต่อไปนี้ไปยังทรัพยากรที่ขอ:

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

เมื่อพบสคริปต์ที่แทรกผ่าน document.write และอาจถูกบล็อกใน ในสถานการณ์ต่างๆ Chrome อาจส่งข้อมูลต่อไปนี้

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

ระบบจะส่งส่วนหัวของการฝึกฝนเป็นส่วนหนึ่งของคำขอ GET สำหรับสคริปต์ (ไม่พร้อมกันในกรณีที่เป็นการฝึกฝนจริงๆ)

มีอะไรรอเราอยู่บ้างในอนาคต

แผนเริ่มต้นคือการฝึกฝนนี้เมื่อตรวจพบเกณฑ์ ได้พบกัน เราเริ่มจากการแสดงเพียงคำเตือนใน Developer Console ใน Chrome 53 (รุ่นเบต้าอยู่ในเดือนกรกฎาคม 2016 เราคาดหวังให้เวอร์ชันเสถียรพร้อมใช้งานสำหรับผู้ใช้ทุกคนใน กันยายน 2016)

เราจะเข้าไปช่วยบล็อกสคริปต์ที่แทรกเข้ามาสำหรับผู้ใช้ 2G ในอีกไม่ช้า Chrome 54 ซึ่งคาดว่าจะเป็นเวอร์ชันเสถียรสำหรับผู้ใช้ทั้งหมดใน กลางเดือนตุลาคม 2016 โปรดดู รายการสถานะ Chrome เพื่อดูข้อมูลอัปเดตเพิ่มเติม

เมื่อเวลาผ่านไป เราต้องการเข้าไปแทรกแซงในกรณีที่การเชื่อมต่อของผู้ใช้ช้า (เช่น 3G หรือ Wi-Fi ที่ช้า) ทำตามรายการสถานะของ Chrome

หากต้องการดูข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมได้จากแหล่งข้อมูลต่อไปนี้