התערבות ב-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. אם הסקריפט מחדיר סקריפט אחר באופן דינמי, המנתח נאלץ להמתין עוד יותר זמן עד להורדת המשאב, דבר שעלול להוביל לנתיב הלוך ושוב אחד או יותר ברשת ולעכב את זמן העיבוד הראשון של הדף

אצל משתמשים בחיבורים איטיים, כמו רשת 2G, סקריפטים חיצוניים שמוחדרים באופן דינמי דרך document.write() יכולים לעכב את ההצגה של תוכן ראשי בדף למשך עשרות שניות, או לגרום לכך שטעינת הדפים לא תיכשל או שתימשך כל כך הרבה זמן עד שהמשתמש מוותר. על סמך אינסטרומנטציה ב-Chrome, גילינו שטעינה של דפים עם סקריפטים של צד שלישי שנוספו דרך document.write() היא בדרך כלל איטית פי 2 מאשר דפים אחרים ברשת 2G.

אספנו נתונים מניסוי שטח שנמשך 28 ימים על 1% מהמשתמשים היציבים ב-Chrome, שמוגבלים למשתמשים בחיבורי 2G. ראינו ש-7.6% מכל טעינות הדפים ב-2G כללו לפחות סקריפט אחד חוצה-אתרים וחוסם את הניתוח, שנוסף דרך document.write() למסמך ברמה העליונה. בעקבות חסימת הטעינה של הסקריפטים האלה, ראינו את השיפורים הבאים בטעינות האלה:

  • 10% יותר טעינת דפים שמגיעים אל הצגת תוכן ראשוני (FCP) (אישור חזותי למשתמש שהדף נטען ביעילות), עלייה של 25% בטעינת הדפים שמגיעים למצב של ניתוח מלא, ו-10% פחות טעינות מחדש שמרמזות על ירידה בתסכול המשתמשים.
  • ירידה של 21% מהזמן הממוצע (יותר משנייה אחת מהר יותר) עד הצגת התוכן הראשון
  • משך הזמן הממוצע לניתוח דף מצטמצם ב-38%, שמייצג שיפור של כמעט שש שניות, מה שמקטין באופן משמעותי את הזמן שנדרש כדי להציג את מה שחשוב למשתמש.

על סמך הנתונים האלה, Chrome, החל מגרסה 55, מתערב בשם כל המשתמשים כשאנחנו מזהים את הדפוס הבעייתי הידוע הזה על ידי שינוי אופן הטיפול ב-document.write() ב-Chrome (ראו סטטוס Chrome). באופן ספציפי, Chrome לא יפעיל את רכיבי <script> שהוחדרו דרך document.write() כאשר כל התנאים הבאים מתקיימים:

  1. המשתמש נמצא בחיבור איטי, במיוחד כשהמשתמש נמצא ב-2G. (בעתיד, ייתכן שהשינוי יורחב למשתמשים אחרים שמשתמשים בחיבורים איטיים, כמו 3G איטי או Wi-Fi איטי).
  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 לאלמנט הסקריפט, או להוסיף את רכיבי הסקריפט עם ממשקי ה-API של DOM, כמו document.appendChild() או parentNode.insertBefore().

איך לזהות מתי האתר שלכם מושפע

יש מספר רב של קריטריונים שקובעים אם ההגבלה נאכפת, אז איך תוכלו לדעת אם היא מושפעת?

זיהוי מתי משתמש נמצא ב-2G

כדי להבין את ההשפעה הפוטנציאלית של השינוי הזה, אתם צריכים קודם להבין כמה מהמשתמשים שלכם יהיו מחוברים לרשת 2G. אפשר לזהות את סוג הרשת והמהירות הנוכחיים של המשתמש באמצעות ה-Network Information API שזמין ב-Chrome, ולאחר מכן לשלוח התרעה למערכות האנליטיות או למערכות Real User Metrics (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

החל מגרסה 53 של Chrome, כלי הפיתוח מנפיקים אזהרות לגבי הצהרות 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 בגרסה 53. (גרסת הבטא הייתה ביולי 2016. אנחנו צופים שתוכנית 'יציב' תהיה זמינה לכל המשתמשים בספטמבר 2016).

אנחנו נתערב כדי לחסום סקריפטים שהוחדרו למשתמשי 2G באופן זמני החל מ-Chrome 54, שלפי ההערכות שלנו היא גרסה יציבה לכל המשתמשים באמצע אוקטובר 2016. לעדכונים נוספים, היכנסו אל רשומת הסטטוס של Chrome.

עם הזמן, אנחנו מנסים להתערב אם למשתמש כלשהו יש חיבור איטי (כלומר, 3G או Wi-Fi איטיים). פועלים לפי הרשומה הבאה בסטטוס Chrome.

צריכים מידע נוסף?

מידע נוסף זמין במקורות המידע הנוספים: