WordPress: How to only load scripts if widget is displayed

I have written a few WordPress plugins to which I keep adding functionality. Very often the number of scripts and styles I need to load to support these enhancements keep growing. Usually they are still not so large. But if you have pages where the widgets are not displayed, you’re just loading scripts and style that are actually not required and thus slowing down the page load without any additional benefit.

So I was looking for a way to only load the scripts and styles I require for one of my plugin when the widget provided by this plugin is actually displayed. Pretty quickly I came across the WordPress built-in is_active_widget Widget function. This is the description of this function in the WordPress codex:

This Conditional Tag checks whether widget is displayed on the front-end.

Sounds like exactly what I was looking for ! Unfortunately the description of the function is wrong. As the name of the function says, it tells you whether a widget is active, not whether it is displayed on this particular page (or on any page for that matter). An active widget is a widget which has been instantiated in a sidebar. This means that you created an instance of the widget in a sidebar but it doesn’t tell you whether this sidebar is displayed anywhere and even less whether this sidebar is displayed in the current page.

So you will probably find some suggestions to handle the problem using something like:

function check_widget() {
    if(is_active_widget( '', '', 'my_widget_id')){
        wp_enqueue_script(...);

    }
}
add_action('wp_footer', 'check_widget');

The only case I can think of where this will effectively prevent your scripts from being unnecessarily loaded is if you do not use this widget in any sidebar. Of course, if the sole purpose of your plugin is to provide this widget, your users could just deactivate it instead of relying on this method…

But if the widget exists in a sidebar and a full-width page (without sidebar) is being displayed, it will still load the scripts.

On the other hand, if you allow your users to display you widgets only outside of a sidebar by using a short code or by calling a PHP function displaying the same contents as the widget, the scripts will not be loaded and it will not work anymore…

So the solution I went for is a different one. This might not work for all plugins but for the one I was updating, it works perfectly. All you need to do is not to enqueue the scripts in wp_head or before it, but to enqueue them when displaying something (whether as a widget or a short code).

I have done the following:

  1. Add a plugin setting called do-not-load-scripts which allows the administrator to defined that the scripts should not be loaded using the wp_enqueue_scripts hook but only when a widget is being displayed.
  2. In my wp_enqueue_scripts hook, I check the value of this setting. If it’s set, I enqueue scripts and styles if is_admin() returns true.
  3. In the widget() function of my widget, I check the value of the setting. If set, I enqueue the scripts and styles.

If multiple instances of the widget are displayed. the enqueue functions will be called multiple times but it will still only output the scripts and styles only once. Of course you could also set a global variable to only enqueue once but I doubt this would have much of a positive impact on performance or load.

Since my short code or the PHP function I provide basically just call the widget() function with some parameters, this will handle all cases where the widget is displayed whether in a sidebar or not.

When using this method, you need to make sure that your widget doesn’t rely on the scripts and styles being loaded in header (because they will be loaded in the footer).

The code for the wp_enqueue_scripts hook looks like this:

if ( is_admin() ) {
	wp_enqueue_style( ... );
	wp_enqueue_script( ... );
} elseif (<setting NOT set by admin>) {
	wp_enqueue_style( ... );
	wp_enqueue_script( ... );
}

And the code in the widget() function like this:

if (<setting set by admin>) {
	wp_enqueue_style( ... );
	wp_enqueue_script( ... );
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *