التدخل ضد document.write()

هل ظهر لك مؤخرًا تحذير مثل ما يلي في وحدة تحكم مطوّري البرامج في 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. إذا أدخل النص البرمجي نصًا برمجيًا آخر ديناميكيًا، فسيضطر المحلل إلى الانتظار لمدة أطول حتى يتم تنزيل المورد، مما قد ينتج عنه رحلة ذهاب وعودة واحدة أو أكثر في الشبكة ويؤخر عرض الصفحة لأول مرة

بالنسبة إلى المستخدمين الذين لديهم اتصالات بطيئة، مثل شبكة الجيل الثاني، يمكن أن تؤدي النصوص البرمجية الخارجية التي يتم إدخالها ديناميكيًا من خلال document.write() إلى تأخير عرض محتوى الصفحة الرئيسية لعشرات الثواني أو يمكن أن تتسبب في تعذُّر تحميل الصفحات أو إلى استغراق وقت طويل بحيث يتوقف المستخدم عن المشاهدة. استنادًا إلى الأدوات المستخدمة في Chrome، توصّلنا إلى أنّ الصفحات التي تعرض نصوصًا برمجية تابعة لجهات خارجية تم إدراجها عبر document.write() تكون بطئًا في التحميل عادةً بمقدار ضعف مقارنةً بالصفحات الأخرى على شبكة الجيل الثاني.

لقد جمعنا البيانات من فترة تجريبية ميدانية مدتها 28 يومًا على 1% من مستخدمي Chrome المستقرين، مقتصرة على مستخدمي اتصالات شبكة الجيل الثاني. لقد لاحظنا أنّ% 7.6 من جميع عمليات تحميل الصفحات على شبكة الجيل الثاني تضمّنت نصًا برمجيًا واحدًا على الأقل لحظر المحلِّل اللغوي من مواقع إلكترونية متعددة، وتم إدراجه من خلال document.write() في مستند المستوى الأعلى. نتيجةً لحظر تحميل هذه النصوص البرمجية، لاحظنا التحسينات التالية على هذه النصوص:

  • زيادة بنسبة 10% في عدد عمليات تحميل الصفحات التي تصل إلى سرعة عرض المحتوى على الصفحة (تأكيد مرئي للمستخدم بأنّ الصفحة يتم تحميلها بشكل فعّال)، وارتفاع بنسبة 25% في عمليات تحميل الصفحات التي تصل إلى الحالة التحليلية بالكامل، و%10 من عمليات إعادة التحميل، ما يشير إلى انخفاض مستوى شعور المستخدم بعدم الرضا.
  • انخفاض بنسبة 21% في الوقت المتوسط (أسرع بمقدار ثانية واحدة) حتى يتم عرض سرعة عرض أول محتوى مرئي
  • خفض متوسط الوقت المستغرَق في تحليل الصفحة بنسبة 38%، ما يعني تحسُّنًا بمقدار ست ثوانٍ تقريبًا، ما يقلّل بشكل كبير من الوقت اللازم لعرض المعلومات التي تهم المستخدم

ومع وضع هذه البيانات في الاعتبار، فإنّ Chrome، بدايةً من الإصدار 55، يتدخل نيابةً عن جميع المستخدمين عند اكتشاف هذا النمط السيئ المعروف من خلال تغيير كيفية التعامل مع document.write() في Chrome (يمكنك الاطّلاع على حالة Chrome). وعلى وجه التحديد، لن ينفِّذ Chrome عناصر <script> التي يتم إدخالها من خلال document.write() عند استيفاء جميع الشروط التالية:

  1. اتصال المستخدم بطيء، خاصة عندما يكون اتصاله بشبكة الجيل الثاني. (في المستقبل، قد يمتد التغيير إلى المستخدمين الآخرين الذين لديهم اتصالات بطيئة، مثل شبكة الجيل الثالث البطيئة أو شبكة 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. يمكنك اكتشاف نوع الشبكة الحالية للمستخدم وسرعتها باستخدام واجهة برمجة تطبيقات معلومات الشبكة المتاحة في 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"

تصدر "أدوات مطوري البرامج" تحذيرات لعبارات document.write() التي تتضمّن مشاكل، وذلك اعتبارًا من الإصدار 53 من Chrome. على وجه التحديد، إذا استوفى طلب 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 للنص البرمجي (بشكل غير متزامن في حالة حدوث تدخل فعلي).

ما الذي يحمله المستقبل في جعبته؟

الخطة الأولية هي تنفيذ هذا التدخل عندما نكتشف المعايير التي يتم الوفاء بها. لقد بدأنا بعرض تحذير فقط في Play Console في الإصدار 53 من Chrome. (تم إصدار الإصدار التجريبي في تموز (يوليو) 2016. ونتوقع إتاحة القناة الثابتة لجميع المستخدمين في أيلول (سبتمبر) 2016.)

سنتدخل مبدئيًا لحظر النصوص البرمجية التي تم إدخالها لمستخدمي شبكة الجيل الثاني بدءًا من Chrome 54، والذي من المتوقع أن يتوفر في إصدار مستقر لجميع المستخدمين في منتصف تشرين الأول (أكتوبر) 2016. تحقق من إدخال حالة Chrome لمزيد من التحديثات.

وبمرور الوقت، نسعى إلى التدخل عندما يكون اتصال أي مستخدم بطيئًا (أي بطء اتصال شبكة الجيل الثالث أو شبكة WiFi). اتّبِع إدخال حالة Chrome هذا.

هل يهمّك معرفة المزيد من المعلومات؟

لمعرفة المزيد من المعلومات، اطّلِع على هذه المراجع الإضافية: