מניעת בקשות רשת מיותרות באמצעות מטמון ה-HTTP

אחזור משאבים דרך הרשת איטי ויקר:

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

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

במדריך הזה נסביר את העקרונות הבסיסיים של הטמעה יעילה של אחסון במטמון HTTP.

תאימות דפדפן

למעשה, אין ממשק API אחד שנקרא HTTP Cache. זהו השם הכללי של אוסף ממשקי API של פלטפורמות אינטרנט. ממשקי ה-API האלה נתמכים בכל הדפדפנים:

Cache-Control

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

ETag

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Last-Modified

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

איך פועל מטמון ה-HTTP

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

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

במאמר HTTP Caching ב-MDN מופיעה סקירה מושגית מעמיקה יותר.

כותרות של בקשות: כדאי להשתמש בברירת המחדל (בדרך כלל)

יש כמה כותרות חשובות שצריך לכלול בבקשות היוצאות של אפליקציית האינטרנט, אבל הדפדפן כמעט תמיד מטפל בהגדרתן בשמכם כששולח בקשות. כותרות בקשה שמשפיעות על בדיקת הרעננות, כמו If-None-Match ו-If-Modified-Since, מופיעות על סמך ההבנה של הדפדפן לגבי הערכים הנוכחיים במטמון ה-HTTP.

אלה חדשות טובות – המשמעות היא שתוכלו להמשיך לכלול תגים כמו <img src="my-image.png"> ב-HTML, והדפדפן יטפל בשמירת ה-HTTP במטמון בשבילכם באופן אוטומטי, ללא מאמץ נוסף.

כותרות תגובה: הגדרת שרת האינטרנט

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

  • Cache-Control. השרת יכול להחזיר הוראה מסוג Cache-Control כדי לציין איך הדפדפן ומטמון ביניים אחר צריכים לשמור במטמון את התגובה הספציפית, ולמשך כמה זמן.
  • ETag. כשהדפדפן מוצא תגובה שפג תוקפה ששמורה במטמון, הוא יכול לשלוח אסימון קטן (בדרך כלל גיבוב של תוכן הקובץ) לשרת כדי לבדוק אם הקובץ השתנה. אם השרת מחזיר את אותו אסימון, סימן שהקובץ זהה ואין צורך להוריד אותו מחדש.
  • Last-Modified. הכותרת הזו משרתת את אותה מטרה כמו ETag, אבל היא משתמשת בשיטה מבוססת-זמן כדי לקבוע אם משאב השתנה, בניגוד לשיטה מבוססת-תוכן של ETag.

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

כדי לחסוך לכם זמן חיפוש, ריכזנו כאן הוראות להגדרה של כמה שרתי אינטרנט פופולריים:

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

באילו ערכים של כותרות תגובה כדאי להשתמש?

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

שמירת נתונים במטמון לטווח ארוך עבור כתובות URL עם גרסאות

נניח שהשרת שלכם מורה לדפדפנים לשמור קובץ CSS במטמון למשך שנה אחת (Cache-Control: max-age=31536000), אבל המעצב שלכם ביצע עדכון דחוף שצריך לפרוס באופן מיידי. איך מעדכנים את הדפדפנים כדי לעדכן את העותק 'הלא עדכני' של הקובץ שנשמר במטמון? אי אפשר, לפחות לא בלי לשנות את כתובת ה-URL של המשאב.

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

איך נהנים מהיתרונות של שני העולמות: אחסון במטמון בצד הלקוח ועדכונים מהירים? משנים את כתובת ה-URL של המשאב ומאלצים את המשתמש להוריד את התגובה החדשה בכל פעם שהתוכן שלה משתנה. בדרך כלל עושים זאת על ידי הטמעת טביעת אצבע של הקובץ או מספר גרסה בשם הקובץ – לדוגמה, style.x234dff.css.

כשמשיבים לבקשות לגבי כתובות URL שמכילות 'טביעת אצבע' או מידע לגבי ניהול גרסאות, והתוכן שלהן לא אמור להשתנות אף פעם, צריך להוסיף את הערך Cache-Control: max-age=31536000 לתשובות.

הגדרת הערך הזה מאפשרת לדפדפן לדעת שבכל פעם שהוא יצטרך לטעון את אותה כתובת URL במהלך השנה הבאה (31,536,000 שניות, הערך המקסימלי שנתמך), הוא יוכל להשתמש מיד בערך ששמור במטמון ה-HTTP, בלי שתצטרכו לשלוח בקשת רשת לשרת האינטרנט. מצוין – עכשיו יש לך את המהירות והאמינות שמגיעות מהימנעות מהרשת.

כלים לפיתוח כמו webpack יכולים להפוך את התהליך לאוטומטי של הקצאת טביעות האצבע של הגיבוב לכתובות ה-URL של הנכסים.

אימות חוזר של שרת לכתובות URL ללא גרסאות

לצערנו, לא כל כתובות ה-URL שאתם טוענים כוללות גרסאות. יכול להיות שאין לכם אפשרות לכלול שלב build לפני הפריסה של אפליקציית האינטרנט, ולכן אתם לא יכולים להוסיף גיבוב לכתובות ה-URL של הנכסים. לכל אפליקציית אינטרנט נדרשים קובצי HTML – הקובצים האלה אף פעם (כמעט!) לא יכללו פרטי גרסאות, כי אף אחד לא יתאמץ להשתמש באפליקציית האינטרנט שלכם אם הוא יצטרך לזכור שכתובת ה-URL שבה צריך לבקר היא https://example.com/index.34def12.html. אז מה אפשר לעשות לגבי כתובות ה-URL האלה?

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

הערכים הבאים של Cache-Control יכולים לעזור לכם לשפר את האופן שבו כתובות URL ללא גרסאות מאוחסנות במטמון ואת המיקום שבו הן מאוחסנות:

  • no-cache. כך הורה הדפדפן על כך שהוא צריך לבצע אימות מחדש מול השרת בכל פעם לפני שהוא משתמש בגרסה שנשמרה במטמון של כתובת ה-URL.
  • no-store. כך תורה לדפדפן ולמטמון ביניים אחר (כמו CDN) אף פעם לא לאחסן גרסה כלשהי של הקובץ.
  • private. דפדפנים יכולים לשמור את הקובץ במטמון, אבל מטמון ביניים לא יכול.
  • public. כל מטמון יכול לאחסן את התגובה.

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

אפשר גם להגדיר את הערך ETag או Last-Modified. כפי שצוין בקטע כותרות תגובה, ETag ו-Last-Modified משמשים למטרה זהה: לקבוע אם הדפדפן צריך להוריד מחדש קובץ שנשמר במטמון ופג התוקף שלו. מומלץ להשתמש ב-ETag כי הוא מדויק יותר.

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

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

הגדרת ETag או Last-Modified משפרת את היעילות של בקשת האימות מחדש, כי היא מאפשרת לה להפעיל את כותרות הבקשה If-Modified-Since או If-None-Match שצוינו בקטע כותרות בקשה.

כששרת אינטרנט שהוגדר בצורה נכונה רואה את כותרות הבקשה הנכנסות האלה, הוא יכול לאשר אם הגרסה של המשאב שכבר נמצאת בדפדפן במטמון ה-HTTP תואמת לגרסה האחרונה בשרת האינטרנט. אם יש התאמה, השרת יכול להגיב בתגובת HTTP מסוג 304 Not Modified, שמקבילה ל'המשך שימוש במה שכבר יש לך!' כששולחים תגובה מהסוג הזה, צריך להעביר מעט מאוד נתונים, ולכן התהליך בדרך כלל מהיר בהרבה מאשר לשלוח עותק של המשאב המבוקש.

הדמיה חזותית של לקוח שמבקש משאב והשרת שמגיב עם כותרת 304.
הבקשה של הדפדפן מבקשת מהשרת את /file, ומצרפת את הכותרת If-None-Match כדי להורות לשרת להחזיר את הקובץ המלא רק אם הערך של ETag בקובץ בשרת לא תואם לערך של If-None-Match בדפדפן. במקרה הזה, שני הערכים תואמים, ולכן השרת מחזיר תגובה מסוג 304 Not Modified עם הוראות לגבי משך הזמן שנותר לשמירת הקובץ במטמון (Cache-Control: max-age=120).

סיכום

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

הגדרות Cache-Control הבאות הן התחלה טובה:

  • Cache-Control: no-cache למשאבים שצריך לאמת מחדש מול השרת לפני כל שימוש.
  • Cache-Control: no-store למשאבים שאף פעם לא צריך לשמור במטמון.
  • Cache-Control: max-age=31536000 למשאבים עם גרסאות.

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

מידע נוסף

אם אתם רוצים להרחיב את הידע הבסיסי שלכם בשימוש בכותרת Cache-Control, כדאי לעיין במדריך של Jake Archibald בנושא שיטות מומלצות לשמירת נתונים במטמון וטעויות נפוצות שקשורות ל-max-age.

במאמר המטמון הוא חברך מוסבר איך לבצע אופטימיזציה של השימוש במטמון עבור מבקרים חוזרים.

נספח: טיפים נוספים

אם יש לכם זמן, הנה כמה דרכים נוספות לשיפור השימוש במטמון ה-HTTP:

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

נספח: תרשים זרימה של Cache-Control

תרשים זרימה
תהליך קבלת ההחלטות לגבי הגדרת הכותרות Cache-Control.

נספח: Cache-Control דוגמאות

ערך של Cache-Control הסבר
max-age=86400 הדפדפנים ומאגרי המטמון הביניים יכולים לשמור את התשובה במטמון למשך עד יום אחד (60 שניות x 60 דקות x 24 שעות).
private, max-age=600 הדפדפן יכול לשמור את התגובה במטמון (אבל לא במטמון ביניים) למשך עד 10 דקות (60 שניות x 10 דקות).
public, max-age=31536000 התשובה יכולה להישמר במטמון כלשהו למשך שנה אחת.
no-store אסור לשמור את התגובה במטמון, וצריך לאחזר אותה במלואה בכל בקשה.