אהבת את המטמון ❤️

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

הפוסט הזה הוא כתבה נלווית לסרטון Love your cache, שחלק מהתוכן המורחב בכנס Chrome Dev Summit 2020. מומלץ לצפות בסרטון:

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

בפוסט הזה אדבר על ברירת מחדל מודרנית וחכמה לשמירת נתונים במטמון – ברירת מחדל שבה לא מתבצעת שמירת נתונים במטמון בכלל. אבל זו רק ברירת המחדל, וזה כמו ניואנסים יותר מאשר פשוט "להשבית את זה". כדאי להמשיך!

יעדים

כשאתר נטען בפעם השנייה, יש לכם שני יעדים:

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

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

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

רקע

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

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

קצת רקע: אחת הסיבות הנפוצות ל'מטמון לא עדכני' היא למעשה הגדרת ברירת המחדל של המטמון משנת 1999. הוא מסתמך על הכותרת Last-Modified:

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

כל קובץ שאתם טוענים נשמר למשך 10% נוספים ממחזור החיים הנוכחי שלו, כפי שהוא מופיע בדפדפן. לדוגמה, אם index.html נוצר לפני חודש, הוא יישמר במטמון של הדפדפן למשך עוד שלושה ימים בערך.

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

השביל המואר היטב

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

אפשר להגדיר את מארח האינטרנט כך שיגיב לבקשות אינטרנט באמצעות הכותרת הזו:

Cache-Control: max-age=0,must-revalidate,public

פירוש הדבר הוא שהקובץ תקף לזמן קצר מאוד, וצריך לאמת אותו מהרשת כדי שתוכלו להשתמש בו שוב (אחרת הוא רק 'מוצע').

תהליך האימות הזה זול יחסית מבחינת הבייטים המועברים – אם קובץ תמונה גדול לא השתנה, הדפדפן יקבל תגובה קטנה מסוג 304 – אבל הוא כרוך בזמן אחזור כי המשתמש עדיין צריך לעבור לרשת כדי לבדוק. וזה החיסרון העיקרי של הגישה הזו. הפתרון הזה יכול להתאים מאוד לאנשים עם חיבורים מהירים בעולם הראשון, ובמקומות שבהם ל-CDN שבחרתם יש כיסוי מצוין, אבל לא לאנשים עם חיבורים איטיים יותר בנייד או עם תשתית חלשה.

עם זאת, זוהי גישה מודרנית שהיא ברירת המחדל ב-CDN פופולרי, Netlify, אבל אפשר להגדיר אותה כמעט בכל CDN. ב-Firebase Hosting, אפשר לכלול את הכותרת הזו בקטע האירוח בקובץ firebase.json:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

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

כתובות URL עם טביעת אצבע

אם תכללו גיבוב של תוכן הקובץ בשם של נכסים, תמונות וכו' שמוצגים באתר, תוכלו להבטיח שלקבצים האלה תמיד יהיה תוכן ייחודי. לדוגמה, הקבצים יקראו sitecode.af12de.js. כשהשרת שלכם מגיב לבקשות לקבצים האלה, אתם יכולים להורות לדפדפנים של משתמשי הקצה לשמור אותם במטמון למשך זמן רב, על ידי הגדרת הכותרת הבאה:

Cache-Control: max-age=31536000,immutable

הערך הזה הוא שנה, בשניות. לפי המפרט, זה שווה למעשה ל-"ללא הגבלת זמן".

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

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

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

כמובן, אי אפשר לשנות את השם של הדפים 'הידידותיים' שמוצגים למשתמשים בדרך הזו: אי אפשר לשנות את השם של הקובץ index.html ל-index.abcd12.html, כי אי אפשר לבקש מהמשתמשים לעבור לכתובת URL חדשה בכל פעם שהם טוענים את האתר. אי אפשר לשנות את השם של כתובות ה-URL ה'ידידותיות' האלה ולשמור אותן במטמון בדרך הזו, ולכן אני רוצה להציע פתרון ביניים אפשרי.

דרך ביניים

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

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

<img src="/images/foo.jpeg" loading="lazy" />

אם תעדכנו או תשנו את האתר על ידי מחיקה או שינוי של התמונה הזו שנטענת באיטרציה, משתמשים שיציגו גרסה ששמורה במטמון של ה-HTML שלכם עשויים לראות תמונה שגויה או לא לראות תמונה בכלל – כי עדיין נשמרה במטמון הגרסה המקורית של /images/foo.jpeg כשהם נכנסו שוב לאתר.

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

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

Cache-Control: max-age=3600,immutable,public

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

אפשרויות שאינן HTML

בנוסף ל-HTML, יש אפשרויות נוספות לקבצים שנמצאים באמצע הדרך:

  • באופן כללי, כדאי לחפש נכסים שלא משפיעים על אחרים

    • לדוגמה: הימנעו משימוש ב-CSS, כי הוא גורם לשינויים באופן שבו ה-HTML מוצג.
  • תמונות גדולות שמשולבות במאמרים עדכניים

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

    • ייתכן שנתוני JSON לגבי מזג האוויר יתפרסמו רק כל שעה, כך שאפשר לשמור את התוצאה הקודמת במטמון למשך שעה – היא לא תשתנה בחלון שלכם
    • ייתכן שקצבי הבנייה של גרסאות build של פרויקט בקוד פתוח מוגבלים, לכן כדאי לשמור במטמון קובץ של קובץ אימג' של סטטוס build עד שיכול להיות שהסטטוס ישתנה.

סיכום

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

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

ראה גם

למדריך כללי בנושא מטמון HTTP, אפשר לעיין במאמר מניעת בקשות מיותרות ברשת באמצעות מטמון HTTP.