admin-plugins author calendar category facebook post rss search twitter star star-half star-empty

Tidy Repo

The best & most reliable WordPress plugins

Adding Front-end Performance Options to WordPress Plugins

Adding Front-end Performance Options to WordPress Plugins

Jay Hoffmann

October 7, 2014 (modified on May 25, 2018)

Blog

I was listening to Shop Talk Show a couple weeks ago, and an interesting question came up. In the episode, a listener asked how to avoid render blocking CSS and JS when using a plugin in WordPress. If you’re keeping an eye on performance, you know that external stylesheets and scripts adds another two HTTP requests, and puts these files in the “render-blocking” category. That means these files will need to be loaded before a page is shown to users, which adds time to the first byte and has some negative effects on Pagespeed.

I ran into this problem recently myself. In my redesign, I went through a lot of work to ensure that all of the CSS and Javascript was loaded in properly. This required an entire front-end build process, and I used a combination of Codekit and Grunt to make everything snap into place.

And it can all be undone with one plugin.

Chris Coyer proposed a rather unique solution I thought. He suggested adding a checkbox in a plugin’s settings which allows developers to choose whether or not to load in CSS or Javascript, or perhaps whether or not to load JS in the footer. If a user chooses “no”, then a text area can drop-down with the contents of the plugin’s stylesheet or Javascript, which front-end developers can copy and paste to their existing build process. It’s a novel idea, and one I think it warrants further discussion.

Here’s the thing

Plugins have to serve several different use cases simultaneously. They have to ensure that for the average WordPress user, a plugin just plains works anywhere. It shouldn’t matter what theme is installed, or what other plugins coexist. In other cases, users will turn to plugins like W3 Total Cache or Better WP Minify to automatically concatenate Javascript files and stylesheets from plugins into one big file, and load them all in at once. This is a great solution for some people and can go a long way towards speeding up your site’s front-end.

But then there’s this outlier use case. The one discussed above. Front-end developers that want to take performance into their own hands. The web development community is focusing more and more on speed and performance, and there are some pretty cutting edge techniques out there. This requires a custom build process, and WordPress isn’t always set up to handle it. At the moment, this most likely represents only a small number of WordPress sites. But I can only imagine that this number is growing. And we don’t have a solution to this yet.

The Current Process

If you’re a developer trying to solve this problem right now, the process can be a bit unwieldy. For me, the problem was that too many separate Javascript and CSS files were being loaded in simultaneously. What I wanted to do was take all of these external files, concatenate and minify them in one single file, and then load this asynchronously.

First, I needed to gather a list of all of the external files that were being loaded in. Fortunately, Helpful Information is a developer plugin that listed these for me. Once I did that, I gathered all of the handles and then used the wp_dequeue_script and wp_dequeue_style to remove these files, one by one. In practice, that ends up looking like this.


function dequeue_all_scripts() {
wp_dequeue_script( 'plugin-script-handle' );
wp_dequeue_style( 'plugin-style-handle' );
}
add_action( 'wp_enqueue_scripts', 'dequeue_all_scripts', 100 );

After that, I had to go and grab all of these files and bring them into my own build process so they could be loaded asynchronously. I won’t go into the details of this, that probably warrants another post. But, at best, this process is hacky and feels just the slightest bit unnatural.

What Plugin Developers Can Do

These are already a few established best practices for plugin development that can go a long way to making this process easier for front-end developers. Most (if not all) of the plugins that I use and review on this site make it about as easy as they can for front-end developers by following just a few basic principles.

First and foremost, plugins should use the wp_enqueue_scripts action to register CSS and JS. This makes it easier to hook into later. When using jQuery, the version packaged with WordPress is almost always best. Above all, please, please do not load scripts and stylesheets directly in the header.

Also, a single CSS stylesheet and a single Javascript file are best. There are also some plugins that provide both minified and unminified version of these files. This makes grabbing these files and bringing them into a separate build process a lot easier.

These are great first steps, but they don’t always go far enough.

We Need a Best Practice

I believe we can do better. We need to give front-end developers a way to remove external loading altogether in a way that’s not too burdensome for plugin developers. I think Chris’ suggestion feels prudent here. Developers can add a couple of options to their settings screen which gives users the ability to turn off external loading, essentially blocking “wp_enqueue_scripts” altogether. When they do, plugin’s can load in the contents of these files into a text area so that a WordPress developer can copy and paste this into their own front-end process.

The problem, of course, is that this option has the power to essentially nuke a whole plugin. If not used properly, it can disable essential functionality and break the layout. So we need to make sure that this option is only used by those that know what they are doing. But there is a precedent. A lot of plugins already feature a “developer” section, where users can flip on or off debug mode or enable advanced features. This can be a simple addition to this section, with a warning attached to it.

“Beware, checking these boxes might break the plugin. This is for developers only.”

Or maybe something more subtle. But in any case, the “Developer” section makes the options less approachable for the average user and is already used in practice with great results.

Implementing this in your code is also not too difficult. In the end, you just have to add a couple of settings to your admin options view. It might look something like this.

<tr valign="top">
  <th scope="row">
     <?php _e('Load CSS?', 'plugin-name'); ?>
  </th>
  <td>
     <label><input type="checkbox" name="plugin_name[load_css]" value="1" <?php checked($opts['load_css'], 1, true); ?> > <?php _e('Yes'); ?></label> &nbsp;
    <br>
    <small><?php _e('Loads an external stylesheet in header. Uncheck to use CSS in your own build process', 'plugin-name'); ?>
    </small>
  </td>
</tr>

<tr valign="top">
  <th scope="row">
    <label for="plugin_css"><?php _e('Raw CSS', 'plugin-name'); ?></label>
  </th>
  <td>
    <textarea style="width: 100%; height: 20em;">
    <?php
      $css_path = plugins_url( '/assets/css/' , dirname(__FILE__) . 'styles.css';
      $css_contents = esc_textarea(file_get_contents($css_path));
      echo $css_contents;
    ?>
    </textarea>
  </td>
</tr>

With a little bit of jQuery, you can hide or show the text area based on whether or not the box is checked.

Then, depending on the value of a load_css or load_js option, you can enqueue scripts and styles, or leave them out. I’m sure that the content in the text area can be sanitized a bit better, but it should be an easy enough affair to simply pull the content of stylesheets and scripts automatically to the admin. And if developers stick to the one JS file, one CSS file, it is that much more effective.

This is just step one. Code recommendations and amendments are very welcome. I’m far from a prolific plugin developer, and I’d love to hear opinions about how this should be implemented or whether it even should.

Chris put together some of his thoughts in a Gist. If you’d like to join the conversation, that’s a great place to start.

Ultimately, if we can agree on a best practice, then we can hopefully start rolling it into documentation. Maybe it can be a part of the WordPress plugin boilerplate. Or maybe it just needs to be passed around a bit. Either way, I think this is a use case that we are going to see more and more. And I, for one, want to see WordPress stay on the cutting edge in everything we do.

If you have an opinion, please share it. This is just the beginning.

UPDATE: There are some thoughts that this feature can be rolled into a separate plugin instead of each individual plugin. Nate Wright put together a first version which you can download and test out. Read more about it on the above list.