เมื่อเร็วๆ นี้คุณเห็นคำเตือนต่อไปนี้ในคอนโซลนักพัฒนาซอฟต์แวร์ใน 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()
อาจทําให้การแสดงเนื้อหาหลักของหน้าช้าลงหลาย 10 วินาที หรือทําให้หน้าเว็บโหลดไม่ได้หรือใช้เวลานานเกินไปจนผู้ใช้หมดความอดทน จากเครื่องมือวัดใน Chrome เราพบว่าหน้าเว็บที่มีสคริปต์ของบุคคลที่สามที่แทรกผ่าน document.write()
มักจะโหลดช้ากว่าหน้าอื่นๆ 2 เท่าในเครือข่าย 2G
เรารวบรวมข้อมูลจากการทดสอบภาคสนาม 28 วันในผู้ใช้ Chrome 1% ที่ใช้เวอร์ชันเสถียร ซึ่งจำกัดไว้สำหรับผู้ใช้ที่มีการเชื่อมต่อ 2G เท่านั้น เราพบว่าการโหลดหน้าเว็บทั้งหมด 7.6% ใน 2G ใช้สคริปต์การบล็อกโปรแกรมวิเคราะห์เว็บข้ามเว็บไซต์อย่างน้อย 1 รายการที่แทรกผ่าน document.write()
ในเอกสารระดับบนสุด การบล็อกการโหลดสคริปต์เหล่านี้ทำให้เราเห็นการปรับปรุงดังต่อไปนี้ในการโหลดสคริปต์ดังกล่าว
- การโหลดหน้าเว็บที่ไปถึงFirst Contentful Paint (การยืนยันด้วยภาพว่าหน้าเว็บโหลดได้อย่างมีประสิทธิภาพ) เพิ่มขึ้น10% การโหลดหน้าเว็บที่ไปถึงสถานะแยกวิเคราะห์อย่างสมบูรณ์เพิ่มขึ้น25% และการโหลดซ้ำลดลง10% ซึ่งบ่งชี้ว่าผู้ใช้รู้สึกหงุดหงิดน้อยลง
- เวลาเฉลี่ยลดลง 21% (เร็วขึ้นกว่า 1 วินาที) จนกว่าจะถึง First Contentful Paint
- เวลาที่ใช้ในการแยกวิเคราะห์หน้าเว็บลดลง 38% ซึ่งแสดงถึงเวลาในการปรับปรุงเกือบ 6 วินาที ซึ่งช่วยลดเวลาในการแสดงข้อมูลที่สําคัญต่อผู้ใช้ได้อย่างมาก
เมื่อพิจารณาข้อมูลนี้ Chrome ตั้งแต่เวอร์ชัน 55 เป็นต้นไปจะแทรกแซงในนามของผู้ใช้ทุกคนเมื่อตรวจพบรูปแบบที่เป็นอันตรายซึ่งเราทราบแล้ว โดยเปลี่ยนวิธีจัดการ document.write()
ใน Chrome (ดูสถานะ Chrome)
กล่าวโดยละเอียดคือ Chrome จะไม่เรียกใช้องค์ประกอบ <script>
ที่แทรกผ่าน
document.write()
เมื่อเป็นไปตามเงื่อนไขต่อไปนี้ทั้งหมด
- ผู้ใช้ใช้การเชื่อมต่อที่ช้า โดยเฉพาะอย่างยิ่งเมื่อใช้ 2G (ในอนาคต เราอาจขยายการเปลี่ยนแปลงนี้ไปยังผู้ใช้รายอื่นที่มีการเชื่อมต่อที่ช้า เช่น 3G หรือ Wi-Fi ที่ช้า)
document.write()
อยู่ในเอกสารระดับบนสุด การฝึกฝนนี้ไม่ใช้กับสคริปต์ document.write ภายใน iframe เนื่องจากไม่ได้บล็อกการแสดงหน้าหลัก- สคริปต์ใน
document.write()
บล็อกโปรแกรมวิเคราะห์ สคริปต์ที่มีแอตทริบิวต์ "async
" หรือ "defer
" จะยังคงดำเนินการอยู่ - สคริปต์ไม่ได้โฮสต์ในเว็บไซต์เดียวกัน กล่าวคือ Chrome จะไม่แทรกแซงสคริปต์ที่มี eTLD+1 ที่ตรงกัน (เช่น สคริปต์ที่โฮสต์ใน js.example.org ซึ่งแทรกไว้ใน www.example.org)
- สคริปต์ไม่ได้อยู่ในแคช HTTP ของเบราว์เซอร์แล้ว สคริปต์ในแคชจะไม่ก่อให้เกิดความล่าช้าของเครือข่ายและจะยังคงดำเนินการอยู่
- คำขอหน้าเว็บไม่ใช่การโหลดซ้ำ 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 เป็นเรื่องที่ดี แต่คุณจะตรวจหาปัญหานี้ในวงกว้างได้อย่างไร คุณสามารถตรวจสอบส่วนหัว 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
หากต้องการดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมได้ในแหล่งข้อมูลต่อไปนี้