תוספים ל-Chrome: הרחבת ממשק ה-API לתמיכה בניווט מיידי

Dave Tapuska
Dave Tapuska

אמ;לק: ה-API של התוספים עודכן כדי לתמוך במטמון לדף הקודם/הבא ובניווטים שנטענים מראש. פרטים נוספים מופיעים בהמשך.

ב-Chrome השקיעו מאמצים רבים כדי להאיץ את הניווט. טכנולוגיות של ניווט מיידי, כמו מטמון לדף הקודם/הבא (שנשלח במחשב ב-Chrome 96) וכללי ספקולציות (שנשלחו ב-Chrome 103), משפרות את חוויית החזרה אחורה והבאה. בפוסט הזה נבחן את העדכונים שביצענו בממשקי ה-API של תוספים לדפדפן כדי להתאים לתהליכי העבודה החדשים האלה.

הבנת סוגי הדפים

לפני השימוש במטמון לדף הקודם/הבא ובעיבוד מראש, לכרטיסייה בודדת היה רק דף פעיל אחד. זה תמיד היה גלוי. אם משתמש חוזר לדף הקודם, הדף הפעיל ייהרס (דף ב') והדף הקודם בהיסטוריה ישוחזר במלואו (דף א'). לתוספים לא היה צורך לדאוג באיזה חלק של דפי מחזור החיים נמצא כי היה רק חלק אחד לכרטיסייה, המצב הפעיל/הגלוי.

הוצאה של הדף הפעיל
הסרת הדף הפעיל.

עם מטמון לדף הקודם/הבא ועיבוד מראש, כבר אין קשר אחד-אחד בין כרטיסיות לדפים. עכשיו, כל כרטיסייה מאחסנת בפועל מספר דפים ודפים במעבר בין מצבים, ולא להרוס ולבנות מחדש.

לדוגמה, דף יכול להתחיל את חייו כדף שעבר עיבוד מראש (לא גלוי), מעבר לדף פעיל (גלוי) כשהמשתמש לוחץ על קישור, ואז להיות מאוחסן במטמון לדף הקודם/הבא (לא גלוי) כשהמשתמש מנווט לדף אחר, כל זה מבלי שהדף יושמד. בהמשך המאמר הזה נבחן את הנכסים החדשים שנחשפים, כדי לעזור לתוספים להבין מהם דפי המצב.

סוגי דפים
סוגי דפים.

שימו לב שכרטיסייה יכולה לכלול סדרה של דפים שעברו עיבוד מראש (לא רק דף אחד), דף פעיל (גלוי) יחיד וסדרה של דפים שנשמרו במטמון לדף הקודם/הבא.

מה משתנה אצל מפתחי תוספים?

FrameId == 0

ב-Chromium, אנחנו מתייחסים למסגרת העליונה/הראשית בתור המסגרת החיצונית ביותר.

מחברי תוספים שמניחים שה-frameId של המסגרת הקיצונית הוא 0 (שיטה מומלצת קודמת) עלולים להיתקל בבעיות. מכיוון שכרטיסייה יכולה עכשיו לכלול כמה פריימים קיצוניים (בעיבוד מראש ודפים שנשמרו במטמון), ההנחה שיש כרטיסייה קיצונית אחת היא שגויה. frameId == 0 עדיין ימשיך לייצג את המסגרת החיצונית של הדף הפעיל, אבל הפריימים החיצוניים ביותר של דפים אחרים באותה כרטיסייה לא יהיו אפס. כדי לפתור את הבעיה, הוספנו שדה חדש בשם frameType. עיינו בקטע איך אפשר לקבוע אם מסגרת היא המסגרת החיצונית ביותר? בפוסט הזה.

מחזור החיים של מסגרות לעומת מסמכים

מושג נוסף שבעייתי בשימוש בתוספים הוא מחזור החיים של הפריים. מסגרת מארחת מסמך (שמשויך לכתובת URL שהתחייבת אליה). המסמך יכול להשתנות (למשל באמצעות ניווט), אבל ה-frameId לא ישתנה, ולכן קשה לשייך שמשהו קרה במסמך ספציפי עם frameIds בלבד. אנחנו משיקים קונספט של documentId שהוא מזהה ייחודי לכל מסמך. אם מנווטים במסגרת ופותחים מסמך חדש, המזהה משתנה. השדה הזה שימושי כדי לקבוע מתי דפים משנים את המצב של מחזור החיים שלהם (בין עיבוד מראש/פעיל/מטמון) כי הוא נשאר ללא שינוי.

אירועי ניווט באתר

אירועים במרחב השמות chrome.webNavigation יכולים לפעול כמה פעמים באותו דף, בהתאם למחזור החיים שבו הם נמצאים. עיינו בקטעים "איך אפשר לדעת באיזה מחזור חיים של הדף?" ו"איך אפשר לקבוע מתי דף עובר?".

איך אפשר לדעת מהו מחזור החיים של הדף?

הסוג DocumentLifecycle נוסף לכמה ממשקי API של תוספים שבהם frameId היה זמין בעבר. אם הסוג DocumentLifecycle קיים באירוע (למשל onCommitted), הערך שלו הוא המצב שבו האירוע נוצר. תמיד תוכלו לשלוח שאילתות על מידע באמצעות ה-methods WebNavigation getFrame() ו-getAllFrames(), אבל עדיף להשתמש בערך מהאירוע. אם משתמשים באחת משתי השיטות, חשוב לשים לב שמצב הפריים עשוי להשתנות בין מועד יצירת האירוע לבין מועד סיום ההבטחה החוזרת בשתי השיטות.

השדה DocumentLifecycle כולל את הערכים הבאים:

  • "prerender" : לא מוצג כרגע למשתמש, אבל בהכנה לקראת שעשוי להיות מוצג למשתמש.
  • "active": מוצג כרגע למשתמש.
  • "cached": מאוחסן במטמון לדף הקודם/הבא.
  • "pending_deletion": מתבצעת השמדה של המסמך.

איך אפשר לבדוק אם מסגרת היא המסגרת החיצונית ביותר?

בעבר, יכול להיות שתוספים בדקו אם frameId == 0 כדי לקבוע אם האירוע שמתרחש הוא במסגרת הקיצונית ביותר או לא. כשיש מספר דפים בכרטיסייה, יש עכשיו כמה פריימים חיצוניים, כך שההגדרה של frameId היא בעייתית. אף פעם לא יישלחו אירועים לגבי פריימים ששמורים במטמון לדף הקודם/הבא. עם זאת, בפריימים שעברו עיבוד מראש, frameId יהיה לא אפס בפריים החיצוני ביותר. לכן, משתמשים ב-frameId == 0 כאות כדי לקבוע אם זו הפריים החיצוני ביותר שגוי.

כדי לעזור בכך, הוספנו סוג חדש בשם FrameType, כך שעכשיו קל יותר לקבוע אם הפריים הוא אכן המסגרת החיצונית ביותר. FrameType מכיל את הערכים הבאים:

  • "outermost_frame": נקרא בדרך כלל המסגרת העליונה. שימו לב שיש עותקים כפולים שלהם. לדוגמה, אם יש לכם דף שעבר עיבוד מראש ודף שנשמר במטמון, לכל אחד מהם יש מסגרת חיצונית ביותר שאפשר לקרוא למסגרת העליונה שלו.
  • "fenced_frame": שמור לשימוש בעתיד.
  • "sub_frame": בדרך כלל iframe.

אנחנו יכולים לשלב את DocumentLifecycle עם FrameType כדי לקבוע אם פריים הוא הפריים החיצוני הפעיל. לדוגמה: js tab.documentLifecycle == “active” && frameType == “outermost_frame”

איך אפשר לפתור בעיות בנושא זמן שימוש במסגרות?

כפי שציינו שמעל מסגרת מארחת מסמך, והמסגרת יכולה לעבור למסמך חדש, אבל ב-frameId לא ישתנה. זה יוצר בעיות כשמקבלים אירוע עם frameId בלבד. כשמחפשים את כתובת ה-URL של המסגרת, היא עשויה להיות שונה ממה שמתרחש כשהאירוע התרחש, המצב הזה נקרא 'בעיה בזמן השימוש'.

כדי לפתור את הבעיה השתמשנו גם ב-documentId (וגם ב-parentDocumentId). ה-method webNavigation.getFrame() הופכת את frameId לאופציונלי אם מספקים documentId. הערך documentId ישתנה בכל פעם שמנווטים במסגרת.

איך אוכל לקבוע מתי דף עובר?

יש אותות מפורשים כדי לקבוע מתי דף עובר בין מדינות.

בואו נבחן את האירועים של WebNavigation.

בניווט ראשון בדף כלשהו, תראו ארבעה אירועים לפי הסדר הבא. שימו לב שארבעת האירועים האלה יכולים להתרחש כשהמצב DocumentLifecycle הוא "prerender" או "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

אפשר לראות את זה בתרשים שלמטה, שבו documentId משתנה ל-"xyz" כשהדף שעבר עיבוד מראש הופך לדף הפעיל.

ה-documentId משתנה כשהדף שעבר עיבוד מראש הופך לדף הפעיל
הdocumentId משתנה כשהדף שעבר עיבוד מראש הופך לדף הפעיל.

כשדף עובר ממטמון לדף הקודם/הבא או מעיבוד מראש למצב הפעיל, יהיו שלושה אירועים נוספים (אבל כאשר DocumentLifecyle יהיה "active").

onBeforeNavigate
onCommitted
onCompleted

האירוע documentId יישאר ללא שינוי באירועים המקוריים. אפשר לראות את זה למעלה כשמפעיל documentId == xyz. שימו לב ואותם אירועי ניווט מופעלים, חוץ מהאירוע onDOMContentLoaded, כי הדף כבר נטען.

אם יש לכם הערות או שאלות, אתם מוזמנים לשאול בקבוצת Chromium-extensions.