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

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

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

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

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

  1. המשתמש מחובר לאינטרנט איטי, במיוחד כשהוא מחובר לרשת 2G. (בעתיד, יכול להיות שהשינוי יורחב למשתמשים אחרים עם חיבורים איטיים, כמו חיבור 3G איטי או חיבור Wi-Fi איטי).
  2. ה-document.write() נמצא במסמך ברמה העליונה. ההתערבות לא חלה על סקריפטים שנכתבו ב-document.‎ בתוך iframes, כי הם לא חוסמים את הרינדור של הדף הראשי.
  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, ולאחר מכן לשלוח התראה למערכות הניתוח או למערכות למדידת ביצועי משתמשים אמיתיים (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, DevTools מציג אזהרות לגבי הצהרות document.write() problematic. באופן ספציפי, אם בקשת 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, באופן זמני החל מגרסה 54 של Chrome. ההערכה היא שהגרסה היציבה של Chrome 54 תהיה זמינה לכל המשתמשים באמצע אוקטובר 2016. בכניסה הזו תוכלו למצוא עדכונים נוספים.

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

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

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