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

טעינת הדף 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 ואחרים.

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

  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 השליפה מראש (prefetch).

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

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

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

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

  • בעמודה גודל מוצג 'מטמון מראש', כלומר המשאב אוחזר מהמטמון של הדפדפן ולא מהרשת.
  • בעמודה זמן מוצג שזמן הטעינה של המסמך הוא עכשיו כ-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. כדי לראות תצוגה מקדימה של האתר, לוחצים על View App (הצגת האפליקציה) ואז על Fullscreen מסך מלא (מסך מלא).
  2. מקישים על 'Control+Shift+J' (או על 'Command+Option+J' ב-Mac) כדי לפתוח את כלי הפיתוח.
  3. לוחצים על הכרטיסייה רשתות.
  4. טוענים מחדש את האפליקציה.

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

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

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

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

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