אחזור משאבים דרך הרשת הוא גם איטי וגם יקר:
- תגובות גדולות דורשות הרבה נסיעות הלוך ושוב בין הדפדפן לשרת.
- הדף לא ייטען עד שכל המשאבים החיוניים שלו יורדו במלואם.
- אם משתמש נכנס לאתר שלכם באמצעות חבילת גלישה מוגבלת, כל בקשה מיותרת לאחזור מהרשת מבזבזת לו כסף.
איך אפשר להימנע מבקשות מיותרות לאחזור מהרשת? מטמון ה-HTTP של הדפדפן הוא קו ההגנה הראשון. זו לא בהכרח הגישה הכי יעילה או גמישה, ויש לכם שליטה מוגבלת על משך החיים של התגובות שנשמרו במטמון, אבל היא יעילה, נתמכת בכל הדפדפנים ולא דורשת הרבה עבודה.
במדריך הזה נסביר את העקרונות הבסיסיים של הטמעה יעילה של שמירה במטמון של HTTP.
תאימות דפדפן
אין ממש API אחד שנקרא HTTP Cache. זהו השם הכללי של אוסף ממשקי API של פלטפורמת אינטרנט. ממשקי ה-API האלה נתמכים בכל הדפדפנים:
Cache-Control
ETag
Last-Modified
איך פועל מטמון ה-HTTP
כל בקשות ה-HTTP שהדפדפן שולח מנותבות קודם לשמירה במטמון הדפדפן כדי לבדוק אם יש תגובה תקינה שנשמרה במטמון, שאפשר להשתמש בה כדי למלא את הבקשה. אם יש התאמה, התגובה נקראת מהמטמון, וכך נמנעים גם זמן האחזור של הרשת וגם עלויות הנתונים שנובעות מההעברה.
ההתנהגות של מטמון ה-HTTP נשלטת על ידי שילוב של כותרות בקשה וכותרות תגובה. בתרחיש אידיאלי, תהיה לכם שליטה גם על הקוד של אפליקציית האינטרנט (שיקבע את כותרות הבקשה) וגם על ההגדרות של שרת האינטרנט (שיקבעו את כותרות התגובה).
במאמר שמירה במטמון של HTTP של MDN יש סקירה כללית מעמיקה יותר של הנושא.
כותרות של בקשות: בדרך כלל כדאי להשתמש בברירות המחדל
יש כמה כותרות חשובות שצריך לכלול בבקשות היוצאות של אפליקציית האינטרנט, אבל הדפדפן כמעט תמיד דואג להגדיר אותן בשבילכם כשהוא שולח בקשות. כותרות של בקשות שמשפיעות על בדיקת העדכניות, כמו If-None-Match ו-If-Modified-Since, מופיעות על סמך האופן שבו הדפדפן מבין את הערכים הנוכחיים במטמון ה-HTTP.
אלה חדשות טובות – זה אומר שאתם יכולים להמשיך לכלול תגים כמו <img src="my-image.png"> ב-HTML, והדפדפן מטפל באופן אוטומטי בשמירה במטמון של HTTP, בלי מאמץ נוסף.
כותרות תגובה: הגדרת שרת האינטרנט
החלק החשוב ביותר בהגדרת השמירה במטמון של HTTP הוא הכותרות ששרת האינטרנט מוסיף לכל תגובה יוצאת. הכותרות הבאות משפיעות על התנהגות יעילה של שמירה במטמון:
Cache-Control. השרת יכול להחזיר הוראתCache-Controlכדי לציין איך ולכמה זמן הדפדפן ומטמונים אחרים צריכים לשמור במטמון את התגובה הספציפית.ETag. כשהדפדפן מוצא תגובה שפג התוקף שלה במטמון, הוא יכול לשלוח אסימון קטן (בדרך כלל גיבוב (hash) של תוכן הקובץ) לשרת כדי לבדוק אם הקובץ השתנה. אם השרת מחזיר את אותו אסימון, הקובץ זהה ואין צורך להוריד אותו מחדש.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 יכולים להפוך את התהליך לאוטומטי ולהקצות טביעות אצבע של גיבוב (hash) לכתובות ה-URL של הנכסים.
אימות מחדש של השרת לכתובות URL ללא גרסה
לצערנו, לא כל כתובות ה-URL שאתם טוענים כוללות גרסאות. יכול להיות שאתם לא יכולים לכלול שלב של פיתוח לפני פריסת אפליקציית האינטרנט, ולכן אתם לא יכולים להוסיף גיבובים לכתובות ה-URL של הנכסים. כל אפליקציית אינטרנט צריכה קובצי HTML – הקבצים האלה (כמעט!) אף פעם לא יכללו מידע על ניהול גרסאות, כי אף אחד לא יטרח להשתמש באפליקציית האינטרנט אם הוא יצטרך לזכור שכתובת ה-URL שצריך להיכנס אליה היא https://example.com/index.34def12.html. אז מה אפשר לעשות עם כתובות ה-URL האלה?
זה תרחיש אחד שבו צריך להודות בתבוסה. שמירה במטמון של HTTP לבדה לא מספיקה כדי להימנע לחלוטין מהרשת. (אל דאגה, בקרוב תלמדו על קובצי Service Worker, שיספקו את התמיכה שאתם צריכים כדי להטות את הכף לטובתכם). אבל יש כמה דברים שאפשר לעשות כדי לוודא שהבקשות לאחזור מהרשת יהיו מהירות ויעילות ככל האפשר.
הערכים הבאים של 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, נועדו לפתור. השרת יוצר ומחזיר אסימון שרירותי, שהוא בדרך כלל גיבוב (hash) או טביעת אצבע אחרת של תוכן הקובץ. הדפדפן לא צריך לדעת איך נוצרת טביעת האצבע, אלא רק לשלוח אותה לשרת בבקשה הבאה. אם טביעת האצבע עדיין זהה, המשאב לא השתנה והדפדפן יכול לדלג על ההורדה.
הגדרת ETag או Last-Modified הופכת את בקשת האימות מחדש ליעילה הרבה יותר, כי היא מאפשרת להפעיל את כותרות הבקשה If-Modified-Since או If-None-Match שמוזכרות בקטע כותרות של בקשות.
כששרת אינטרנט שמוגדר כמו שצריך רואה את כותרות הבקשות הנכנסות האלה, הוא יכול לאשר אם גרסת המשאב שכבר נמצאת במטמון ה-HTTP של הדפדפן תואמת לגרסה העדכנית ביותר בשרת האינטרנט. אם יש התאמה, השרת יכול להחזיר תגובת HTTP מסוג 304 Not Modified, שמשמעותה היא "היי, אפשר להמשיך להשתמש במה שכבר יש לך!" כששולחים תגובה מהסוג הזה, יש מעט מאוד נתונים להעביר, ולכן בדרך כלל זה הרבה יותר מהיר מאשר לשלוח בחזרה עותק של המשאב המבוקש.
/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, כדאי לעיין במדריך של ג'ייק ארצ'יבלד Caching best practices and max-age gotchas.
במאמר Love your cache מוסבר איך לבצע אופטימיזציה של השימוש במטמון למבקרים חוזרים.
נספח: טיפים נוספים
אם יש לכם עוד זמן, הנה דרכים נוספות שבהן תוכלו לבצע אופטימיזציה של השימוש במטמון ה-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 |
אסור לשמור את התשובה במטמון וצריך לאחזר אותה במלואה בכל בקשה. |