שתי דרכים לשליפה מראש (prefetch): תגי <link> וכותרות HTTP

Demián Renzulli
Demián Renzulli

בקודלאב הזה תלמדו איך להטמיע אחסון מקדים בשתי דרכים: באמצעות <link rel="prefetch"> וכותרת HTTP‏ Link.

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

מדידת ביצועים

קודם כול, צריך לקבוע את רמת הביצועים הבסיסית:

  1. לוחצים על Remix to Edit כדי לאפשר עריכה של הפרויקט.
  2. כדי לראות תצוגה מקדימה של האתר, מקישים על הצגת האפליקציה. לאחר מכן מקישים על מסך מלא מסך מלא.
  3. מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
  4. לוחצים על הכרטיסייה רשתות.

  5. ברשימה הנפתחת Throttling בוחרים באפשרות Fast 3G כדי לדמות סוג חיבור איטי.

  6. כדי לטעון את דף המוצר, לוחצים על Buy now (קנייה עכשיו) באפליקציית הדוגמה.

טעינת הדף product-details.html נמשכת כ-600 אלפיות השנייה:

חלונית הרשת שמוצגים בה זמני הטעינה של product-details.html

כדי לשפר את הניווט, מוסיפים תג prefetch בדף הנחיתה כדי לבצע אחסון מקדים של הדף product-details.html:

  • מוסיפים את הרכיב <link> הבא לחלק העליון של הקובץ views/index.html:
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

המאפיין as הוא אופציונלי אבל מומלץ. הוא עוזר לדפדפן להגדיר את הכותרות הנכונות ולקבוע אם המשאב כבר נמצא במטמון. דוגמאות לערכים של המאפיין הזה: document, script, style, font, image ו-others.

כדי לוודא שהאחסון המקדים פועל:

  1. כדי לראות תצוגה מקדימה של האתר, מקישים על הצגת האפליקציה. לאחר מכן מקישים על מסך מלא מסך מלא.
  2. מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
  3. לוחצים על הכרטיסייה רשתות.

  4. ברשימה הנפתחת Throttling בוחרים באפשרות Fast 3G כדי לדמות סוג חיבור איטי.

  5. מבטלים את הסימון בתיבה Disable cache (השבתת המטמון).

  6. טוענים מחדש את האפליקציה.

עכשיו, כשדף הנחיתה נטען, גם הדף product-details.html נטען, אבל בעדיפות הנמוכה ביותר:

חלונית של רשת המדיה שמציגה את הקובץ product-details.html שנאגר מראש.

הדף נשמר במטמון ה-HTTP למשך חמש דקות, ולאחר מכן חלים הכללים הרגילים של Cache-Control לגבי המסמך. במקרה כזה, ל-product-details.html יש כותרת cache-control עם הערך public, max-age=0, כלומר הדף נשמר למשך חמש דקות בסך הכול.

הערכה מחדש של הביצועים

  1. טוענים מחדש את האפליקציה.
  2. כדי לטעון את דף המוצר, לוחצים על Buy now (קנייה עכשיו) באפליקציית הדוגמה.

כדאי לעיין בחלונית Network. יש שני הבדלים בהשוואה למעקב אחר הרשת הראשוני:

  • בעמודה Size מוצג 'מטמון של משיכה מראש (prefetch)', כלומר המשאב הזה אוחזר מהמטמון של הדפדפן ולא מהרשת.
  • בעמודה זמן מוצג שהזמן הנדרש לטעינת המסמך הוא עכשיו כ-10 אלפיות השנייה.

זוהי הפחתה של כ-98% בהשוואה לגרסה הקודמת, שבה הזמן היה כ-600 אלפיות השנייה.

חלונית הרשת שבה מוצג הקובץ product-details.html שאוחזר ממטמון השליפה מראש.

בונוס: שימוש ב-prefetch כתוספת הדרגתית

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

כדי להטמיע אחסון נתונים מראש דינמי, קודם צריך להסיר את התג <link rel="prefetch"> מ-views/index.html:

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

לאחר מכן מוסיפים את הקוד הבא ל-public/script.js כדי להצהיר על פונקציה שמחדירה באופן דינמי את התג prefetch כשהמשתמש מחובר לאינטרנט במהירות גבוהה:

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

הפונקציה פועלת באופן הבא:

  • הוא בודק את המאפיין effectiveType של Network Information API כדי לקבוע אם המשתמש מחובר לרשת 4G (או מהירה יותר).
  • אם התנאי הזה מתקיים, המערכת יוצרת תג <link> עם prefetch כסוג של רמז, מעבירה את כתובת ה-URL שתתבצע לה אחזור מראש במאפיין href ומציינת שהמשאב הוא document של HTML במאפיין as.
  • לבסוף, הוא מוסיף את הסקריפט באופן דינמי ב-head של הדף.

לאחר מכן מוסיפים את script.js ל-views/index.html, ממש לפני תג הסגירה </body>:

<body>
      ...
      <script src="/script.js"></script>
</body>

שליחת הבקשה ל-script.js בסוף הדף מבטיחה שהוא ייטען ויתבצע אחרי שהדף ינותח וייטען.

כדי לוודא שהאחזור מראש לא יפריע למשאבים חיוניים לדף הנוכחי, מוסיפים את קטע הקוד הבא כדי לקרוא ל-injectLinkPrefetchIn4g() באירוע window.load:

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

עכשיו מתבצע דפדוף מראש של product-details.html בדף הנחיתה רק בחיבורים מהירים. כדי לוודא ש:

  1. כדי לראות תצוגה מקדימה של האתר, מקישים על הצגת האפליקציה. לאחר מכן מקישים על מסך מלא מסך מלא.
  2. מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
  3. לוחצים על הכרטיסייה רשתות.
  4. ברשימה הנפתחת Throttling, בוחרים באפשרות Online.
  5. טוענים מחדש את האפליקציה.

הערך product-details.html אמור להופיע בחלונית 'רשת':

חלונית של רשת המדיה שמציגה את הקובץ product-details.html שנטען מראש.

כדי לוודא שדף המוצר לא נטען מראש בחיבורים איטיים:

  1. ברשימה הנפתחת 'הגבלת קצב נתונים', בוחרים באפשרות 3G איטי.
  2. טוענים מחדש את האפליקציה.

החלונית רשת צריכה לכלול רק את המשאבים של דף הנחיתה, ללא product-details.html:

חלונית הרשת שמראה שלא בוצע אחסון מראש של הקובץ product-details.html.

אפשר להשתמש בכותרת ה-HTTP Link כדי לבצע אחסון מקדים של אותם סוגי משאבים כמו התג link. ההחלטה מתי להשתמש באפשרות אחת או באחרת תלויה בעיקר בהעדפה שלכם, כי ההבדל בביצועים הוא זניח. במקרה כזה, אפשר להשתמש בו כדי לבצע אחסון מראש של קובץ ה-CSS הראשי של דף המוצר, כדי לשפר עוד יותר את העיבוד שלו.

מוסיפים כותרת HTTP Link עבור style-product.css בתגובת השרת לדף הנחיתה:

  1. פותחים את הקובץ server.js ומחפשים את הטיפול get() של כתובת ה-URL ברמה הבסיסית: /.
  2. מוסיפים את השורה הבאה בתחילת ה-handler:
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. כדי לראות תצוגה מקדימה של האתר, מקישים על הצגת האפליקציה. לאחר מכן מקישים על מסך מלא מסך מלא.
  2. מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
  3. לוחצים על הכרטיסייה רשתות.
  4. טוענים מחדש את האפליקציה.

עכשיו מתבצע אחזור מראש של style-product.css בעדיפות הנמוכה ביותר אחרי טעינת דף הנחיתה:

חלונית הרשת שמוצג בה style-product.css שנאגר מראש.

כדי לעבור לדף המוצר, לוחצים על Buy now (קנייה עכשיו). בודקים את החלונית Network:

חלונית הרשת שבה מוצג הקובץ style-product.css שאוחזר מהמטמון של שליפה מראש.

קובץ style-product.css אוחזר מ'מטמון האחסון המהיר', והטעינה שלו ארכה רק 12 אלפיות השנייה.