DCSIMG
עמוד הבית| חבילות השירות שלנו| חומר חופשי| צור קשר
איך נשפר את ה- caching לדפים סטטים - בלוג היועצים של מיקרוסופט ישראל

בלוג היועצים של מיקרוסופט ישראל

איך נשפר את ה- caching לדפים סטטים

אתם מפתחים אתר אינטרנט ואתם רוצים לשפר בו ביצועים?
נראה לכם שכבר עשיתם הכל?
הנה עוד דבר קטן שאפשר לנסות...
caching לדפים סטטים (JS, CSS, Images וכו').

[אני אדבר על קבצי JS, אך הכל נכון גם לסוגי הדפים האחרים]

כברירת מחדל, הדפדפן שלכם מבצע caching באופן הבא:
בכל פעם שהוא נדרש "להוריד" דף מהשרת, הוא בודק האם הדף קיים ב- cache המקומי שלו.
הבדיקה מתבצעת עבור כל ה- url , כולל הפרמטרים.
אם הדף לא נמצא ב- cache, הדפדפן ניגש לשרת ו"מבקש" את הדף.
אם הדף כן נמצאב-cache, הדפדפן ניגש לשרת ו"מבקש" את הדף ומוסיף ב – header של הבקשה "שאלה": If-Modified-Since: dd/mm/yyyy hh:MM:ss.
אם השרת מזהה שהדף הקיים אצלו לא שונה מאז התאריך הנקוב ב- request הוא לא מחזיר את הדף המבוקש, אלא מחזיר לדפדפן סטטוס  304(Not Modified). הדפדפן "מבין" שהדף שקיים אצלו ב- cache עדיין עדכני ומשתמש בו.

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

אז מה אפשר לעשות?
בואו נראה איך אי יכול "לחסוך" את הגישות המיותרות לשרת...

כאשר אני בונה את האתר אני אגדיר ספריית Scripts שבה אמקם את קבצי ה - JS שלי.
בשרת ה - IIS אני יכול הגדיר לספרייה content expiration. יש 2 אפשרויות:
לפי תאריך – כך, כאשר הדף ירד לדפדפן הוא ירד עם הנתון של "עד איזה תאריך הקובץ יכול להיות ב - cache", כך שעד תאריך זה, הדפדפן לא יגש לשרת לבקש את הדף, אלא יקח אותו ישירות מה - cache. לאחר תאריך זה, הדפדפן יחזור להתנהגות ברירת המחדל של בדיקת cahce עם סטטוס 304.
content_expiration_date
החסרון של ההגדרה הזו הוא שקשה להגדיר תאריך, אלא אם יודעים מתי הגרסה הבאה מתוכננת. בנוסף לכך זה דורש כל פעם לגשת לשרת ה - IIS ולעדכן את התאריך.

אפשרות שנייה היא לפי קבוע זמן - מספר ימים, והשרת מתרגם זאת לתאריך עתידי. כך, כאשר הדף יורד מהשרת לדפדפן הוא יורד עם "תאריך תוקף" עתידי וכל עוד הנתון בתוקף הדפדפן ייקח את הדף מה - cache ללא פניות לשרת. לאחר שיעברו מספר הימים שהוגדרו, הדפדפן יפנה שוב לשרת ויוריד מחדש דף עם "תאריך תוקף" שחושב מחדש לפי מספר הימים המוגדר. כך שאם הגדרנו 5 ימים, כל 5 ימים הדפדפן ייגש לשרת להוריד דף חדש.
content_expiration_duration
החיסרון של הגדרה זו הוא שקשה לקבוע מספר ימים כזה שתמיד יפוג ביום של העלאת גרסה חדשה.

אז מה עוד אפשר לעשות?
אחת השיטות המקובלות היא כתיבת url של דף עם פרמטר שהוא מספר הגרסה של המערכת:
<script src="myscript.js?v=1.4.6"/>
בנוסף לכך, הגדרת התאריך ב - content expiration לכמה שנים קדימה, כך שבעצם ה- url תמיד יילקח מה - cache.
וכאשר מעלים גרסה חדשה של האתר, ה - url ישתנה (מכיוון שהוא כולל מספר גרסה) וכך הדפדפן ייגש לשרת לקחת דף חדש, שגם הוא יכנס ל - cache עד קץ הדורות

החסרונות של פתרון זה הם לפחות 2:
- אנחנו "מנפחים" את ה - cache של הדפדפן.
- האם כל פעם כשמעלים גרסה נעבור על כל ה - urls ונעדכן את מספר הגרסה?

אז ככה, לגבי הבעיה הראשונה, במידה מסוימת אפשר להתנהג כבת יענה (לטמון ראשינו בחול).
לגבי הבעיה השנייה:
ניתן לייצר את הגדרת ה - Script ע"י הפונקציה RegisterClientScriptInclude() מתוך דף ה - aspx, כך בכל פעם תחולל תגית ה- script מחדש עם ה - url ומספר הגרסה הנוכחי. דוגמא:
Page.ClientScript.RegisterClientScriptInclude("myjscriptfilekey", "/myscript.js?v="+GetVersion());

אפשרות נוספת היא הגדרת server control שמייצר את תגית ה - script.
היתרון בפתרון זה הוא שהוא נותן למתכנת תחושה שהוא רגיל אליה - כתיבת תגית ה- script בתוך ה - Head בעצמו, אך מכיוון שזהו server control התגית תחולל כל פעם מחדש עם הגרסה העדכנית.

דוגמא ל – server control:

    public class Script : Control
    {
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "Execution")]
        protected override void Render(HtmlTextWriter output)
        {
            Version v = GetMyApplicationVersion();
            output.AddAttribute(HtmlTextWriterAttribute.Src, this.Url+"?v="+v.ToString());
            output.AddAttribute("type", "text/javascript");
            output.RenderBeginTag(HtmlTextWriterTag.Script);
            output.RenderEndTag();
            output.Flush();
        }

        [UrlProperty()]
        public string Url
        {
            get
            {
                String url = (String)ViewState["Url"];
                return ((url == null) ? String.Empty : url);
            }

            set
            {
                ViewState["Url"] = value;
            }
        }
    }   

וכך נשתמש בו בתוך דף ה - aspx:
<mcs:Script Url="MyScript.js" runat="server"/>

וזה מה שירונדר:
<script src="MyScript.js?v=1.0.3630.23231" type="text/javascript"></script>

 

יש לכם רעיונות נוספים/אחרים איך לשפר את הביצועים?

 

בהצלחה,

טל

 

שירותי MCS רלוונטיים

  • (PDF) שירות ניתוח פערים ושיפור ביצועים
  • (PDF) שירות תכנון וניתוח בדיקות ביצועים
  • (PDF) סדנת פיתוח מערכות מונחה ביצועים
  • תוכן התגובה

    shlomo כתב/ה:

    מגניב מאוד - תודה רבה

    # December 17, 2009 8:28 AM

    Moshe L כתב/ה:

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

    לעצם העניין - יש לי בבלוג מדור שלם העוסק בביצועים:

    blogs.microsoft.co.il/.../default.aspx

    # December 17, 2009 9:31 AM

    אביאור כתב/ה:

    טל תודה טיפ נחמד ,

    הטיפ שלך יפה כאשר אנו מוסיפים את ה Resources  בצורה ידנית

    אבל הבעיה האמתית היא שמנגנון ה App_themes לא תומך בשיטה זאת וכל קבצי ה CSS ותמונות יורדים אוטמטית לדף ואין לנו שליטה על זה

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

    # December 17, 2009 10:20 AM

    alikl כתב/ה:

    טל,

    אחלה טריק!

    מקיף וגם פראקטי ביותר

    תודה על השיתוף

    # December 17, 2009 6:09 PM

    Tal Ben-Shalom כתב/ה:

    אביאור (ניסים?),

    שמח לפגוש אותך :-)

    אתגר מעניין העלת כאן.

    חברים - מישהו חושב שיכול לקחת את הרעיונות שהוצגו כאן ולהרחיב לטובת themes?

    # December 17, 2009 10:56 PM

    בלוג היועצים של מיקרוסופט ישראל כתב/ה:

    יש לכם אתר אינטרנט שמתארח ב – IIS6 ונמצא מאחורי NLB והדפים שלכם לפעמים עולים לאט ולפעמים יותר מהר ?!

    # January 31, 2010 4:30 PM
    שלח תגובה

    (שדה חובה)  

    (שדה חובה)  

    (אופציונלי)

    (שדה חובה) 

    Please add 8 and 1 and type the answer here:


    Enter the numbers above: