חיפוש

כיצד לעכב (defer) פריסת Javascript ולשפר את זמן הטעינה?

אני נתקל לא מעט בשאלה כיצד לעכב פריסת Javascript באתרי וורדפרס (Defer Loading of Javascript). הסיבה המרכזית שמעוניינים לבצע זאת היא בכדי לשפר את מהירות האתר שלכם ולגרום לכך שהתוכן יוצג עוד לפני טעינת הסקריפטים.

החל מגרסת וורדפרס 6.3 ניתן להגדיר את אסטרטגיית הטעינה (defer או async) ישירות  כשמבצעים enqueue.

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

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

מדוע יש לעכב פריסת Javascript?

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

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

הרעיון הוא להציג לגולש קודם כל את הטקסט (שברוב המקרים זה התוכן שמעניין אותו) ולעכב את טעינת הסקריפטים עד לאחר שתוכן זה נטען. אם תבדקו את האתר שלכם בכלים כגון Pingdom, GTmetrix or Google Page Speed Insights סביר להניח כי תקבלו אזהרה כגון "Defer loading of javascript״ או משהו בסגנון של ״Remove Render-Blocking JavaScript״. 

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

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

defer-vs-async-map

 

יש להסתכל על הדיאגרמות משמאל לימין!

ברירת מחדל <script>

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

defer-vs-async

<script async>

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

defer-vs-async

<script defer>

הדפדפן יוריד את הסקריפט תוך כדי שהוא מבצע פריסה ל html ויריץ את הסקריפט רק לאחר שהפריסה הסתיימה. האופציה defer מבטיחה שהסקריפטים באתר שלכם ירוצו בסדר שהם מופיעים ב document.

script-defer

כיצד לעכב פריסת Javascript?

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

1. הדרך המודרנית: פרמטר strategy (וורדפרס 6.3+)

אם אתם עובדים עם וורדפרס 6.3 ומעלה, זו הדרך שאתם צריכים להשתמש בה. העבירו מפתח strategy במערך $args כשמבצעים enqueue:

wp_enqueue_script(
    'my-script',
    get_stylesheet_directory_uri() . '/js/my-script.js',
    array(),
    '1.0.0',
    array(
        'in_footer' => true,
        'strategy'  => 'defer',
    )
);

וורדפרס מטפלת בעץ התלויות בשבילכם – אם סקריפט A תלוי בסקריפט B, שניהם יקבלו את תכונת הטעינה הנכונה באופן אוטומטי.

בכדי להשתמש ב-async במקום, שנו את 'strategy' => 'defer' ל-'strategy' => 'async'.

החל מוורדפרס 6.4, סקריפטים של הליבה והתבניות המובנות משתמשים באסטרטגיית defer ונטענים ב-<head> לגילוי מוקדם יותר. סקריפט comment-reply משתמש ב-async כיוון שתגובות הן בעדיפות נמוכה.

2. לעכב את טעינת כל הסקריפטים חוץ מ jQuery (שיטה ישנה)

שיטה זו משתמשת בפילטר clean_url כדי להזריק את תכונת defer. היא עובדת, אבל זהו מעין hack – היא מניפולטת את הפלט של ה-URL במקום את תגית הסקריפט עצמה. השתמשתי בה שנים לפני וורדפרס 6.3, ועדיין תמצאו אותה באתרים רבים.

הוסיפו את הקוד הבא לקובץ functions.php:

/* defer all js except jquery.min.js */
if ( !is_admin() ) {
    function defer_parsing_of_js ( $url ) {
        if ( FALSE === strpos( $url, '.js' ) ) return $url;
        if ( strpos( $url, 'jquery.min.js' ) ) return $url;

        // return "$url' defer ";
        return "$url' defer onload='";
    }
}
if ( !is_admin() ) {
    add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 );
}

שימו לב לשם הקובץ של jQuery שהתבנית שלכם טוענת, לפעמים הוא פשוט נקרא jquery.js אז שנו את השורה בהתאם.

הקוד המופיע מעלה יוודא כי כל הסקריפטים יטענו רק לאחר סיום הפריסה של ה html על ידי הדפדפן. אם תתנו מבט בקוד מקור של האתר שלכם, תבחינו כי המילה defer התווספה לכל אחד מהסקריפטים למעט jquery.min.js:

לעכב-פריסת-javascript-באתר-וורדפרס-מהירות
במידה ואתם מעוניינים לבצע טעינה אסינכרונית בדרך זו, שנו את המילה defer ל async בשורה מספר 10.

3. לעכב את טעינת הסקריפטים לפי ה handle

וורדפרס 4.1 הציגה את הפילטר script_loader_tag והשימוש בפילטר זה מתבצע על ידי הקוד הבא:

function add_defer_attribute($tag, $handle) {
    if ( 'my-js-handle' !== $handle )
        return $tag;
    return str_replace( ' src', ' defer src', $tag );
}
add_filter('script_loader_tag', 'add_defer_attribute', 10, 2);

אתם נדרשים לשנות את ה handle בשורה 2 אשר (אם ביצעתם enqueue כראוי לסקריפט) יהיה הפרמטר הראשון ברישום של אותו סקריפט:

wp_register_script('my-js-handle', $src, $deps, $ver, $in_footer);

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

ומה אם אתם מעוניינים לעכב את פריסת ה js ביותר מסקריפט אחד?

על מנת לעכב מספר סקריפטים ע״י שימוש בדרך זו אנו צריכים ליצור מערך, לבצע לולאה על אותו מערך ולהוסיף defer לכל אחד מהסקריפטים. הוסיפו את הקוד הבא לקובץ functions.php והוסיפו את ה handles שלכם בשורה 2:

function add_defer_attribute($tag, $handle) {
   $scripts_to_defer = array('my-js-handle', 'another-handle');
   foreach($scripts_to_defer as $defer_script) {
      if ($defer_script !== $handle) return $tag;
      return str_replace(' src', ' defer src', $tag);
   }
   return $tag;
}
add_filter('script_loader_tag', 'add_defer_attribute', 10, 2);

Defer לעומת Delay – מה ההבדל?

חלק מתוספי הביצועים מציעים אפשרות "Delay JavaScript" לצד defer. אלו דברים שונים:

Defer מוריד את הסקריפט במקביל ומריץ אותו אחרי שה-HTML נותח. הסקריפט עדיין רץ בכל טעינת עמוד – רק מאוחר יותר.

Delay (לפעמים נקרא lazy load JS) לא טוען את הסקריפט בכלל עד שמתרחשת אינטראקציה של המשתמש – גלילה, לחיצה, או הקשה. זה מסיר את הסקריפט לגמרי מנתיב הטעינה הראשוני, מה שיכול לשפר דרמטית את ציוני INP.

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

אם אתם משתמשים בסרטוני YouTube, תנו מבט במדריך עיכוב פריסת Javascript לסרטוני YouTube.

איזו שיטה כדאי לבחור?

וורדפרס 6.3+: השתמשו בפרמטר strategy כשמבצעים enqueue. זו הדרך הנקייה והאמינה ביותר.

אתרים לפני 6.3: השתמשו בפילטר script_loader_tag לשליטה לפי handle.

תיקון כללי מהיר: שיטת clean_url עדיין עובדת אם צריכים לעכב הכל בבת אחת, אבל עברו לפרמטר strategy כשאפשר.

סקריפטים לא חיוניים: שקלו טעינה עצלה של JavaScript או עיכוב ביצוע עד אינטראקציה עבור אנליטיקס, צ'אט וכפתורי שיתוף.

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

שאלות נפוצות

שאלות נפוצות בנושא עיכוב פריסת JavaScript בוורדפרס:

האם להשתמש ב-defer או async לסקריפטים בוורדפרס?
השתמשו ב-defer לרוב הסקריפטים בוורדפרס. הוא שומר על סדר הביצוע וממתין עד שה-DOM מוכן, מה שמונע בעיות תלויות. השתמשו ב-async רק לסקריפטים עצמאיים שלא תלויים בקוד אחר, כמו אנליטיקס או פיקסלים של מעקב.
אפשר לעכב את jQuery בוורדפרס?
באופן כללי, לא. תוספים ותבניות רבות בוורדפרס תלויים בכך ש-jQuery זמין מיידית. עיכוב שלו עלול לשבור סקריפטים אינליין שקוראים ל-jQuery() או $() לפני שהקובץ המעוכב נטען. דוגמאות הקוד במדריך זה מדלגות במכוון על jquery.min.js.
האם צריך לעכב JavaScript אם משתמשים בתוסף קאש?
רוב תוספי הקאש כמו WP Rocket, LiteSpeed Cache ו-W3 Total Cache כוללים אפשרויות מובנות לעכב או לדחות JavaScript. אם הפעלתם הגדרות אלו, הוספת קוד defer ידני היא מיותרת ועלולה לגרום לקונפליקטים. בדקו קודם את הגדרות אופטימיזציית ה-JS בתוסף שלכם.
מה זה פרמטר strategy בוורדפרס 6.3?
וורדפרס 6.3 הוסיפה מפתח strategy למערך $args בפונקציות wp_enqueue_script() ו-wp_register_script(). הגדירו אותו ל-'defer' או 'async' כדי לשלוט בטעינת הסקריפט באופן נטיבי. וורדפרס מטפלת בשרשרת התלויות אוטומטית, מה שהופך פילטרים כמו script_loader_tag למיותרים ברוב המקרים.
האם שיטת clean_url בטוחה לשימוש?
היא עובדת, אבל זה hack. פילטר clean_url תוכנן לסניטציה של כתובות URL, לא להזרקת תכונות HTML. הוא עלול להתנגש עם תוספים אחרים שגם מסננים כתובות URL. לפרויקטים חדשים, השתמשו בפרמטר strategy (וורדפרס 6.3+) או בפילטר script_loader_tag.
איך לבדוק אם עיכוב JavaScript באמת שיפר את הביצועים?
הריצו את האתר דרך Google PageSpeed Insights לפני ואחרי השינוי. חפשו שיפורים ב-LCP (Largest Contentful Paint) ובביקורת "Remove render-blocking resources". אפשר גם לבדוק בלשונית Network ב-Chrome DevTools שהסקריפטים מכילים את תכונת defer.

לסיכום

במדריך זה סקרנו שלוש דרכים לעכב פריסת javascript בוורדפרס – פרמטר strategy המודרני, שיטת clean_url הישנה, וגישת script_loader_tag. אם אתם על וורדפרס 6.3 ומעלה, השתמשו בפרמטר strategy המובנה ודלגו על הפילטרים.

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

אם יש לכם שאלות או גישה אחרת שעובדת לכם, כתבו תגובה למטה.

דיון ותגובות
40 תגובות  ]
  • רמי 18 יולי 2016, 0:59

    אחלה טיפ!

  • מתן 18 יולי 2016, 10:26

    מעולה, תודה.

  • חתול 18 יולי 2016, 12:52

    ניסיתי אצלי באתר ו־jquery לא נטען כי השם שלו הוא jquery.js ולא jquery.min.js. ערכתי את הקוד בהתאם ואז הוא עובד יופי.
    שווה לכתוב תוסף עם הקוד הזה.

  • Rob 21 יולי 2016, 9:05

    יכול להיות מצב שהקוד הראשון דווקא גורם להאטה של האתר?

  • Rob 7 אוגוסט 2016, 14:13

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

    • חתול 7 אוגוסט 2016, 14:17

      לבדוק מה התסריט שמריץ את הסליידר ולהוסיף אותו לחריגים יחד עם jquery.

  • רועי יוסף 7 אוגוסט 2016, 15:43

    חתול צודק.. נסה את הקוד הבא:

    /* defer all js except jquery.min.js & revolution slider */
    if ( !is_admin() ) {
        function defer_parsing_of_js ( $url ) {
            if ( FALSE === strpos( $url, '.js' ) ) return $url;
            if ( strpos( $url, 'jquery.min.js' ) ) return $url;
            if ( strpos( $url, 'jquery.themepunch.tools.min.js' ) ) return $url;
            if ( strpos( $url, 'jquery.themepunch.revolution.min.js' ) ) return $url;
    
            return "$url' defer onload='";
        }
    }
    if ( !is_admin() ) {
        add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 );
    }
    • Rob 8 אוגוסט 2016, 13:56

      תודה.
      ההסברים האלה מאוד עוזרים, תוכל לעשות עמוד שמרכז את כולם ביחד?

    • Rob 9 אוגוסט 2016, 15:18

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

      • רועי יוסף 11 אוקטובר 2016, 14:47

        רוב, עדכנתי את המאמר, בחלקו האחרון הוספתי הסבר כיצד לבצע defer לבעלי Revolution Slider… בהצלחה 🙂

        • רוב 13 אוקטובר 2016, 8:31

          תודה

        • רוב 9 נובמבר 2016, 11:07

          נראה לי שיש שגיאה בקוד של ה-Revolution Slider.
          בתגובות כתוב jquery.themepunch.tools.min.js ובדוגמה למעלה כתוב jquery.themepunch.tools.min אני מתאר לעצמי שצריך את ה-.min.js?

          • רועי יוסף 12 נובמבר 2016, 15:42

            אני חושב שזה לא ישנה במקרה הזה.. שניהם יעבדו..

          • רוב 13 נובמבר 2016, 8:34

            כנראה שאני עושה משהו לא נכון, כי הסליידר עדיין נעלם לי למורת שאני מעתיק את הקוד

  • ‫אלון 14 אוגוסט 2018, 14:03

    יש תוסף שעושה את זה?

  • רוב 16 אוקטובר 2018, 15:08

    בעקבות לקוח שאומר שהאתר איטי, קראתי שוב את המאמר שלך. יש הבדל בין סעיף 1 וסעיף 2? צריך את שניהם או רק אחד מהם? בבדיקות שעשיתי אני מקבל הודעה ש-First Byte Time לא טוב, ממה שהבנתי זה קשור לשרת (זה נכון?) יש משהו שאפשר לעשות פרט לאפשרות של מעבר שרת או שדרוג שלו?

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

  • טל 13 מאי 2019, 23:08

    היי, איך אני יודע מה שם הקובץ של הjquery שלי שהתבנית טוענת?

  • טל 13 מאי 2019, 23:18

    ועוד דבר, בחלק של "לעכב את טעינת הסקריפטים לפי ה handle" לא הבנתי מה ואיפה צריך לשנות?
    זה הקוד שלי בfunction.php

    /* defer all js except jquery.min.js */
    if ( !is_admin() ) {
        function defer_parsing_of_js ( $url ) {
            if ( FALSE === strpos( $url, '.js' ) ) return $url;
            if ( strpos( $url, 'jquery.js' ) ) return $url;
    
            // return "$url' defer ";
            return "$url' defer onload='";
        }
    }
    if ( !is_admin() ) {
        add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 );
    }
  • אהרן 25 יולי 2019, 22:01

    הי רועי,

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

    • רועי יוסף 25 יולי 2019, 22:07

      היי אהרן,

      שמח לשמוע שאתה נעזר בתוכן 🙂 בכדי לבדוק גש לקוד המקור בדפדפן ותראה אם מופיעה המילה defer בקריאה לקבצי ה javascript….

  • שחר 25 אוגוסט 2019, 9:15

    תודה

  • רוב 24 נובמבר 2019, 9:58

    יש משהו שיכול לטפל בקבצים של ה-CSS? יש קובץ של dashicons.min.css שעושה בעיות לפי גוגל.

  • רוב 8 דצמבר 2019, 9:31

    כדאי להוסיף את defer גם ל Google Analytics? בקוד הוא מופיע עם async…

    • רועי יוסף 8 דצמבר 2019, 9:53

      לא, ההמלצה של גוגל היא לטעון (ולהריץ) את אנליטיקס יחסית מוקדם ולכן השאר את אנליטיקס כ async…

      • רוב 8 דצמבר 2019, 10:30

        תודה, אני רק מקווה שהכלי שלהם לא מתלונן על זה

  • רוב 6 ינואר 2020, 15:14

    נראה לי שיש שינוי ב-Revolution Slider השמות השתנו

    if ( !is_admin() ) {
        function defer_parsing_of_js ( $url ) {
            if ( FALSE === strpos( $url, '.js' ) ) return $url;
            if ( strpos( $url, 'jquery.js' ) ) return $url;
            if ( strpos( $url, 'revolution.tools.min.js' ) ) return $url;
    		if ( strpos( $url, 'rs6.min.js' ) ) return $url;
    
            return "$url' defer onload='";
        }
    }
    if ( !is_admin() ) {
        add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 );
    }

    יכול להתאים יותר?

    • רועי יוסף 6 ינואר 2020, 15:16

      תודה שאתה משתף רוב! 🙂
      ייתכן מאד, האם ביצעת בדיקה ווידאת שזה עובד?

      • רוב 7 ינואר 2020, 8:56

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

השאירו תגובה

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

Savvy WordPress Development official logo