Back to Top

Selective Plugin Loading

Previous Post:

Selective Plugin Loading

Using plugins for your WordPress website or blog is undoubtedly a must, but if you abuse them you might eventually find yourself in tight situations. Many plugins out there are poorly written and eat up a lot of memory, or even if they aren’t they simply don’t need to be included every single time.

For example, plugins that are designed specifically for the back-end such as TinyMCE Advanced, Ozh’ Admin Drop Down Menu should only be included when you access wp-admin.

The approach we are going to use can be called Selective Plugin Loading, which means you need to check whether the plugin files need to be loaded first before you actually allow WordPress to include_once() any of them.

Since WordPress includes plugins rather early and no hooks are available when that happens, the only way we can selectively load plugins is to hack WordPress’s core files. Don’t worry, you will only have to touch three files, one of which is not actually part of a WordPress’s installation, which means you will need to edit just two core files.

Before continuing with this approach I highly suggest that you read an article about Memory Usage to get a better idea why we have to do this. I also do not recommend this to inexperienced WordPress users because it can cause unexpected behaviours to your plugins’ functionality. You have been warned!

The Ideas

As you might have guessed, the three files you will have to edit is wp-config.php, wp-settings.php and wp-blog-header.php. It is recommended that you create backups for those three files if possible.

Selectively load admin-only plugins

Open wp-config.php and find:

  1. /** Sets up WordPress vars and included files. */
  2. require_once(ABSPATH . 'wp-settings.php');
/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

then add before:

  1. function is_plugin_eligible($plugin, $theme_loaded = false)
  2. {
  3.     $filename = basename($plugin, '.php');
  4.     // this array consists of plugins' main filename
  5.     $is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
  6.     // load admin-only plugins if needed
  7.     // load all normal plugins
  8.     if (!is_admin() && in_array($filename, $is_admin)) return false;
  9. }
function is_plugin_eligible($plugin, $theme_loaded = false)
{
	$filename = basename($plugin, '.php');
	// this array consists of plugins' main filename
	$is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
	// load admin-only plugins if needed
	// load all normal plugins
	if (!is_admin() && in_array($filename, $is_admin)) return false;
}

Now open wp-settings.php and find:

  1. // Load active plugins.
  2. foreach ( wp_get_active_and_valid_plugins() as $plugin )
  3.     include_once( $plugin );
  4. unset( $plugin );
// Load active plugins.
foreach ( wp_get_active_and_valid_plugins() as $plugin )
	include_once( $plugin );
unset( $plugin );

then change those codes to:

  1. // Load active plugins.
  2. foreach ( wp_get_active_and_valid_plugins() as $plugin )
  3.     if (is_plugin_eligible($plugin))
  4.         include_once( $plugin );
  5. unset( $plugin );
// Load active plugins.
foreach ( wp_get_active_and_valid_plugins() as $plugin )
	if (is_plugin_eligible($plugin))
		include_once( $plugin );
unset( $plugin );

Now if you refresh your website you should notice some reduction in PHP memory usage used by WordPress.

What we have just done is limit the inclusion of some admin-only plugins to admin page only, while other plugins should be loaded normally. If you want to selectively load more admin-only plugins, simply extend the $is_admin array with their filenames (without the .php extension of course).

At this point I can say that the above codes are pretty safe and you won’t have to edit anything else. If you want to load plugins based on actual front-end pages, however, things will get more complicated (and riskier!). Anyway, let’s move on, shall we?

Selectively load all plugins

In case you don’t know, there are two ways the front-end WordPress initializes, either with or without theme support. With theme support functions like is_home()1, is_category()2, etc. are available for you to use, thus allowing you to know what page you’re on and selectively load needed plugins. That’s why the $theme_loaded variable is in used in the is_plugin_eligible() function above.

Now if you are using a plugin called Javascript Slider and you would like to load such plugin only on homepage, you can change is_plugin_eligible() to this:

  1. function is_plugin_eligible($plugin, $theme_loaded = false)
  2. {
  3.     $filename = basename($plugin, '.php');
  4.     // this array consists of plugins' main filename
  5.     $is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
  6.     // load admin-only plugins if needed
  7.     if (!is_admin() && in_array($filename, $is_admin)) return false;
  8.  
  9.     if ('true' == $theme_loaded)
  10.     {
  11.         // load Javascript Slider only on homepage, is_home() returns true
  12.         if (is_home() && 'javascript-slider' == $filename) return true;
  13.     }
  14.  
  15.     return false;
  16. }
function is_plugin_eligible($plugin, $theme_loaded = false)
{
	$filename = basename($plugin, '.php');
	// this array consists of plugins' main filename
	$is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
	// load admin-only plugins if needed
	if (!is_admin() && in_array($filename, $is_admin)) return false;

	if ('true' == $theme_loaded)
	{
		// load Javascript Slider only on homepage, is_home() returns true
		if (is_home() && 'javascript-slider' == $filename) return true;
	}

	return false;
}

Please note the use of return false; on line 15, it will tell WordPress not to load any other plugin rather than Javascript Slider.

However, most of the time you will need to selectively load only a certain number of plugins and then globally load the rest. To make that happen we will change is_plugin_eligible() to this:

  1. function is_plugin_eligible($plugin, $theme_loaded = false)
  2. {
  3.     $filename = basename($plugin, '.php');
  4.     // this array consists of plugins to load globally
  5.     $is_global = array('plugin1', 'plugin2');
  6.     // this array consists of plugins' main filename
  7.     $is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
  8.     // load admin-only plugins if needed
  9.     if (!is_admin() && in_array($filename, $is_admin)) return false;
  10.  
  11.     // load global plugins
  12.     if (in_array($filename, $is_global)) return true;
  13.  
  14.     if ('true' == $theme_loaded)
  15.     {
  16.         // load Javascript Slider only on homepage, is_home() returns true
  17.         if (is_home() && 'javascript-slider' == $filename) return true;
  18.     }
  19.  
  20.     return false;
  21. }
function is_plugin_eligible($plugin, $theme_loaded = false)
{
	$filename = basename($plugin, '.php');
	// this array consists of plugins to load globally
	$is_global = array('plugin1', 'plugin2');
	// this array consists of plugins' main filename
	$is_admin = array('tinymce-advanced', 'wp_ozh_adminmenu');
	// load admin-only plugins if needed
	if (!is_admin() && in_array($filename, $is_admin)) return false;

	// load global plugins
	if (in_array($filename, $is_global)) return true;

	if ('true' == $theme_loaded)
	{
		// load Javascript Slider only on homepage, is_home() returns true
		if (is_home() && 'javascript-slider' == $filename) return true;
	}

	return false;
}

‘Plugin1′ and ‘plugin2′ are the two plugins that will be loaded regardless of what page you are on while Javascript Slider will be loaded only when is_home() returns true. If you test the above codes it will not work just yet because there’s one more file you still haven’t edited: wp-blog-header.php.

Open that file and find:

  1.     wp();
	wp();

then add after:

  1. // Load active plugins.
  2. foreach ( wp_get_active_and_valid_plugins() as $plugin )
  3.     if (is_plugin_eligible($plugin, true))
  4.         include_once( $plugin );
  5. unset( $plugin );
// Load active plugins.
foreach ( wp_get_active_and_valid_plugins() as $plugin )
	if (is_plugin_eligible($plugin, true))
		include_once( $plugin );
unset( $plugin );

Yes it is the same snippet we put into wp-settings.php with one difference: the second parameter of the function ($theme_loaded is now true). After you insert this Javascript Slider will not be loaded on any page except your homepage, cool eh?

To make use of this approach even more you should know all the conditional functions3 that allow you to check what page you’re on as well as how to use some global variables in WordPress. After WordPress calls wp() most functions and global variables you need are already available. You can, therefore, make a good use of them to selectively load anything you like ;).

The Catch

While loading plugins selectively though hacking core files can be helpful sometimes, it would be irresponsible of me to stop writing without telling you some major drawbacks this approach has.

Obviously, the first drawback is you have to edit core WordPress files, thus making the update process for WordPress a little bit time-consuming. Although I don’t think it’s such a big problem, some people will not like doing so at all.

Secondly, all what we really need is selectively load the plugins’ .php files and nothing more. However, we also selectively load media files enqueued or echoed by those plugins, which is a bad thing because we will render minify plugins nearly useless (each page will has its own Javascript and CSS files enqueued).

The last (and the worst) drawback is that some plugins will fail to work because we include its codes way too late. If you open wp-settings.php and look around line 283 you should see do_action( 'init' );, one of the most used actions for plugin developers. They often use that action to init their own plugins, and including plugins after do_action( 'init' ); like above is actually killing them (not to mention the fact that all filters you apply to those plugins through theme’s functions.php WILL fail.)

Oh hey, don’t be scared! If you use this Selective Plugin Loading approach to selectively load admin-only plugins in admin page, you’re completely safe. Even if you selectively load front-end plugins, you can still be safe if you know what you’re doing (not all plugins use the init action, for your information).

Nevertheless, I hope that you enjoy reading this article as much as I did writing it. ‘Til next time!

References

  1. http://codex.wordpress.org/Function_Reference/is_home []
  2. http://codex.wordpress.org/Function_Reference/is_catego ... s_category []
  3. http://codex.wordpress.org/Conditional_Tags []
Elegant Themes - Designed with Modest Elegance
Print Article Trackback Trackback to this Article   Subscribe to Comments RSS Subscribe to Comments RSS
 Sponsor   Themes by Elegant Themes - $39 for unlimited access to 80+ WordPress Themes!

14 Opinions for Selective Plugin Loading (1 Trackback)

  1. User's Gravatar
    2
    red August 29, 2011 at 3:55 am – Permalink

    Thank you thank you thank you thank you.

    There are a healthy number of good articles about WP optimization and none of them mention this approach. Several mention deregistering styles and javascript, which is very helpful, especially when trying to make the grade with Yslow. After all of the optimizations though, we were loading fast when cached, but still using ~47MB per page load (and ~62MB in the admin area) with a site that had about 24 plugins. Yes, that is a lot of plugins (and included caching plugins), but most have a light footprint, and that is part of the beauty of WordPress – all of the extendibility. It seemed like we shouldn’t have to disable all the plugins to avoid procwatch and 500 errors – you should be able to run a robust site with all the fixings and still be a good neighbor. Let’s set our standards high.

    So I set about timing each plugin – deactivated all and turned on one by one and used the TPC! Memory Usage plugin ( http://wordpress.org/extend/plugins/tpc-memory-usage/ fantastic plugin!) to track the memory used for each. It (WP 3.2.0) went from 22MB naked to 49MB in full regalia. WP ecommerce was the largest consumer, but ecommerce was also the main focus of the site. With each plugin though, there was a memory usage increase, meaning that the deregistering of the style and scripts did only that – the plugins were still getting called up with each page load. So had to find a way to not call ALL of the plugins on every page.

    Then I found your article – how to only load the plugins you need on the pages you need them (and with that, deregistering wasn’t needed if the plugin wasn’t loaded). THANK YOU. There were several I needed to load globally, and others I needed to load according to the page . However, the later only worked in this example if they were theme loaded. There were a few cases where the plugins weren’t theme loaded (some of the largest memory users), so I couldn’t control when they loaded. So went about it a slightly different way.

    Please review to see if you think there are better ways to approach this – appreciate the feedback.

    1. Left wp-blog-header.php un-edited

    2. Edited wp-settings.php to include this line:
    if (is_plugin_eligible($plugin))

    around line 191:

    1. foreach ( wp_get_active_and_valid_plugins() as $plugin )
    2.     if (is_plugin_eligible($plugin))
    3.        include_once( $plugin );
    4. unset( $plugin );
    foreach ( wp_get_active_and_valid_plugins() as $plugin )
        if (is_plugin_eligible($plugin))
    	   include_once( $plugin );
    unset( $plugin );

    3. Added this version of the is_plugin_eligble() right above the require for wp-settings.php in the wp-config.php, and in this scenario it’s only getting called once.

    1. function is_plugin_eligible($plugin, $theme_loaded = false) {
    2.  
    3.     // this array consists of plugins to load globally
    4.     $is_global = array(
    5.         // these didn't play nice unless set as global
    6.         'frontpage-slideshow',
    7.  
    8.     // capture the affiliate id no matter where someone enters
    9.         'wp_affiliate_platform',
    10.         'wp-ecommerce-affiliate-integration',
    11.  
    12.         // used globally
    13.         'tpcmem',
    14.         'use-google-libraries',
    15.         'wp-seo',
    16.         'db-cache-reloaded',
    17.         'wp-cache',
    18.  
    19.         // security
    20.         'wordpress-firewall-2',
    21.         'loginlockdown',
    22.         'chapsecurelogin',
    23.         'bulletproof-security'
    24.         );
    25.  
    26.     $is_admin = array(
    27.        ''//'tinymce-advanced'
    28.         );
    29.     $is_home = array(
    30.         ''//'frontpage-slideshow'
    31.         );
    32.     $is_contact = array(
    33.         'wp-contact-form-7',
    34.         'contact-form-7-db',
    35.         'really-simple-captcha'
    36.         );
    37.     $is_sitemap = array(
    38.         'wp-realtime-sitemap'
    39.         );
    40.     $is_product = array(
    41.         'wp-shopping-cart',
    42.         'gold_shopping_cart',
    43.         'wordpress-https',
    44.         'custom-fields',
    45.         'related-products',
    46.         'wp-e-commerce-weight-region-shipping',
    47.         'shortcode-exec-php'
    48.         );
    49.     $is_affiliate = array(
    50.         ''//'wp_affiliate_platform',
    51.         //'wp-ecommerce-affiliate-integration'
    52.         );
    53.  
    54.  
    55.     if(is_admin()){//include everything
    56.         return true;
    57.     }
    58.     if(in_array($filename, $is_global)){
    59.         return true;
    60.     }
    61.  
    62.  
    63.     if($_SERVER['REQUEST_URI']=='/'
    64.       && in_array($filename, $is_home)){
    65.         return true;
    66.     }
    67.     if((stripos($_SERVER['REQUEST_URI'],'/contact-us/')!==false
    68.         || stripos($_SERVER['REQUEST_URI'],'/request-a-catalog/')!==false)
    69.       && in_array($filename, $is_contact)){
    70.         return true;
    71.     }
    72.  
    73.     if(stripos($_SERVER['REQUEST_URI'],'/site-map/')!==false
    74.       && in_array($filename, $is_sitemap)) {
    75.         return true;
    76.     }
    77.     if(stripos($_SERVER['REQUEST_URI'],'/affiliate-program/')!==false
    78.       && in_array($filename, $is_affiliate)) {
    79.         return true;
    80.     }
    81.     if(stripos($_SERVER['REQUEST_URI'],'logout')!==false  // so i can call clear cart on logout
    82.       && stripos($_SERVER['REQUEST_URI'],'wp-login')!==false // so doesn't load for affiliate logout
    83.       && in_array($filename, array('wp-shopping-cart'))) {
    84.         return true;
    85.     }
    86.     if(stripos($_SERVER['REQUEST_URI'],'/products/')!==false
    87.       && in_array($filename, $is_product)) {
    88.         return true;
    89.     }
    90.  
    91.     return false;
    92. }
    function is_plugin_eligible($plugin, $theme_loaded = false) {
    
        // this array consists of plugins to load globally
        $is_global = array(
            // these didn't play nice unless set as global
            'frontpage-slideshow',
    
    	// capture the affiliate id no matter where someone enters
            'wp_affiliate_platform',
            'wp-ecommerce-affiliate-integration',
    
            // used globally
            'tpcmem',
            'use-google-libraries',
            'wp-seo',
            'db-cache-reloaded',
            'wp-cache',
    
            // security
            'wordpress-firewall-2',
            'loginlockdown',
            'chapsecurelogin',
            'bulletproof-security'
            );
    
        $is_admin = array(
           ''//'tinymce-advanced'
            );
        $is_home = array(
            ''//'frontpage-slideshow'
            );
        $is_contact = array(
            'wp-contact-form-7',
            'contact-form-7-db',
            'really-simple-captcha'
            );
        $is_sitemap = array(
            'wp-realtime-sitemap'
            );
        $is_product = array(
            'wp-shopping-cart',
            'gold_shopping_cart',
            'wordpress-https',
            'custom-fields',
            'related-products',
            'wp-e-commerce-weight-region-shipping',
            'shortcode-exec-php'
            );
        $is_affiliate = array(
            ''//'wp_affiliate_platform',
            //'wp-ecommerce-affiliate-integration'
            );
    
    
        if(is_admin()){//include everything
            return true;
        }
        if(in_array($filename, $is_global)){
            return true;
        }
    
    
        if($_SERVER['REQUEST_URI']=='/'
          && in_array($filename, $is_home)){
            return true;
        }
        if((stripos($_SERVER['REQUEST_URI'],'/contact-us/')!==false
            || stripos($_SERVER['REQUEST_URI'],'/request-a-catalog/')!==false)
          && in_array($filename, $is_contact)){
            return true;
        }
    
        if(stripos($_SERVER['REQUEST_URI'],'/site-map/')!==false
          && in_array($filename, $is_sitemap)) {
            return true;
        }
        if(stripos($_SERVER['REQUEST_URI'],'/affiliate-program/')!==false
          && in_array($filename, $is_affiliate)) {
            return true;
        }
        if(stripos($_SERVER['REQUEST_URI'],'logout')!==false  // so i can call clear cart on logout
          && stripos($_SERVER['REQUEST_URI'],'wp-login')!==false // so doesn't load for affiliate logout
          && in_array($filename, array('wp-shopping-cart'))) {
            return true;
        }
        if(stripos($_SERVER['REQUEST_URI'],'/products/')!==false
          && in_array($filename, $is_product)) {
            return true;
        }
    
        return false;
    }

    Do you think it would be better to use REDIRECT_SCRIPT_URL, SCRIPT_URL, or SCRIPT_URI instead of REQUEST_URI ? Any more efficient/correct way to acheive the same end?

    This is working great for us – these changes increased the site’s speed incredibly on non-ecommerce pages, down from 49MB to about 28MB of memory with all the other activity going on. Any thoughts on how to selectively load plugins in the admin area? Seems that maybe we would only need to load plugins when we’re in the plugin’s settings. Also did the remove meta boxes addition to the functions file to help decrease the memory usage in the admin area, which took it down about 7MB, but applying this same idea of selectively loading plugins to the admin area seems like it could lead to a lot of savings.

    Thank you again and looking forward to your thoughts/feedback.

    • User's Gravatar
      3
      OddOneOut August 30, 2011 at 10:51 pm – Permalink

      Hi, it’s great that you find this article useful :).

      Do you think it would be better to use REDIRECT_SCRIPT_URL, SCRIPT_URL, or SCRIPT_URI instead of REQUEST_URI ? Any more efficient/correct way to acheive the same end?

      I think $_SERVER['REQUEST_URI'] will work just fine, but you might want to cover more possibilities, such as a page with a URL like this: hxxp://example.com/contact-us/child-page/. Also, if you choose to selectively load some plugins in the front end, make sure you double check their functionality extremely carefully (keep in mind all the drawbacks I have mentioned in the post).

      Another thing I would like to suggest is you should open class-wp.php, which is inside wp-includes, and look for the parse_request() function, it will show you how to effectively and correctly handle a WordPress request (since you’re not using any template functions in is_plugin_eligible()).

      Any thoughts on how to selectively load plugins in the admin area? Seems that maybe we would only need to load plugins when we’re in the plugin’s settings.

      I would recommend against that, unless your admin area is unbearably slow. Why? Because we need to include plugins’ codes to actually see their menus. It is indeed possible, but not that useful IMO.

  2. User's Gravatar
    4
    Mr. Rich January 31, 2012 at 3:17 pm – Permalink

    All I can say is thank you… for all the optimization techniques – this by far is the best!

  3. User's Gravatar
    5
    Paco Delacroix February 16, 2012 at 10:32 pm – Permalink

    Hi, Is what I was looking for, but I am not being able to run my plugins, after making all the changes in the wp-config.php, wp-settings.php, wp-blog-header.php.

    The message I receive is :
    Fatal error: Call to a member function the_slider() on a non-object in C:\Inetpub\vhosts\pro-evolution.com.ar\httpdocs\zonacoaching\wp-content\themes\channel2\index.php on line 4

    I´m sure I am missing something.

    Thanks
    Regards,
    Paco Delacroix

    • User's Gravatar
      6
      OddOneOut February 16, 2012 at 11:42 pm – Permalink

      The theme you’re using (channel2?) is probably using a plugin that has been selectively loaded using this method. You should load that plugin normally and selectively load the rest.

  4. User's Gravatar
    7
    Felipe Veiga April 11, 2012 at 5:09 am – Permalink

    First of all, thanks for sharing this great tip!

    Odd, every time the wordpress core is updated will you lose the changes made to the files?

  5. User's Gravatar
    8
    Zauker June 6, 2012 at 1:34 am – Permalink

    Thank you for the excellent work I was looking for a way to load the plugins in a selective and I was inspired by your article. By chance I found a good way to do this via plugin and not a hack of the core. In this way you can deal with updates of wordpress in peace and security

    • User's Gravatar
      9
      Faina09 June 10, 2012 at 12:10 am – Permalink

      To have a plugin of this great hack is two times as great!! Do you think to release it as a public plugin?

      • User's Gravatar
        10
        Zauker June 13, 2012 at 11:26 am – Permalink

        i wrote a first alpha plugin.
        The aim of my plugin is have a selective plugin loading between access from mobile device and not.
        In this case i’m able to disable a plugin if user browse my site from smartphone.
        i want add option for administrative only plugin, and sure i’m going to release it as public plugin.

  6. User's Gravatar
    12
    Luke January 5, 2013 at 6:53 am – Permalink

    If you do not want to hack the core wordpress files to achieve this, then you can use a WordPress must use plugin, as explained here:

    http://wptip.me/how-to-modify-active-wordpress-plugins

  7. User's Gravatar
    13
    Erlend Sogge Heggen January 31, 2013 at 8:32 am – Permalink

    CleanerPress appears to do something similar:
    http://wordpress.org/extend/plugins/cleanerpress/

    You restrict a plugin to only load on certain WP components like pages and posts, or restrict it to certain URLs.

  8. User's Gravatar
    14
    Deepan April 24, 2013 at 5:12 pm – Permalink

    Thanks, for your Excellent Plugin Filtering guide to WordPress performance, I am going to implement

  1. WordPress's Memory Usage, should it be one of your concerns? - Better WordPress

    [...] Plugin Loading. I have written a follow-up post regarding such solution, you can read it here: Selective Plugin Loading. The ideal scenario is, of course, the plugin authors change the way they load their plugins, by [...]

Speak Up Your Mind!

An asterisk (*) indicates a required field and must be filled.




  • Web page and e-mail addresses turn into links automatically.
  • Wrap codes in: <code lang=""></code> or <pre lang="" extra="">
  • Lines and paragraphs break automatically.

Next Post: