Back to Top

WordPress Minify – Best Practices

Previous Post:

WordPress Minify – Best Practices

Everyone wants their pages to load fast because that makes visitors and search engines happy. WordPress itself is lightweight and optimized for speed, but when plugins and themes come into play, performance can suffer a lot.

As I have pointed out in a previous article, speeding up WordPress is firstly a developer’s duty. The thing is, if a huge number of plugins are loaded on a single page, it’s nearly impossible for anyone to speed up a WordPress site simply by optimizing codes.

One of the most significant components of the World Wide Web that affects page load time is HTTP request. The number of HTTP requests, the time they take to get responses from a server, as well as the size of responses all contribute to your site’s sluggish performance.

WordPress Minify to our rescue

The first thing most webmasters would do to improve page load time is reduce the number of HTTP requests for Javascript and CSS files, simply because they are accounted for most of the slowness of your WordPress site, i.e. they block other requests.

To do that a method called “Minifying” can be used, which consists of two consecutive steps:

Step 1: Minify files contents. Definition from Wikipedia:

Minification is the process of removing all unnecessary characters from source code without changing its functionality. These unnecessary characters usually include white space characters, new line characters, comments, and sometimes block delimiters, which are used to add readability to the code but are not required for it to execute.

Step 2: Combine minified files (concatenation). It is the process of joining several files into one so that they can be served using just one HTTP request.

WordPress users often use an on-the-fly minifying solution as it provides the most dynamic approach: plugins or themes can be activated/deactivated whenever needed and minified contents are updated automatically. For that reason, minifying in this article is understood as on-the-fly minifying.

Once Javascript and CSS files are minified, your website should rank better in PageSpeed/YSlow or similar tools. However, this doesn’t always guarantee a better page load time because you still have response time and response size to take into account. A smaller number of HTTP requests consisting of heavier requests sometimes can decrease your website’s performance instead of helping.

Best Practices: Minify with care

Many users activate a minify plugin and expect it to just work. This is simply wrong on many levels.

Minifying is like a driving a Formula One car, it’s extremely fast but dangerous at the same time. If your site has more than 40 Javascript files, or a huge number of daily visitors, an on-the-fly minifying solution (such as one provided by BWP Minify) must be used with great responsibility.

Problematic files

Not all files can be minified, i.e. they simply break when minified. Some are minifiable but break as soon as they are combined with other files (see BWP Minify’s compatibility report for more info).

This is one of the main reasons why a Javascript function does not work at all or your site look messed up when minifying is active. To resolve that, you need to identify what files are causing troubles.

Problematic files can be detected by excluding files one by one in the minification list. If you are using BWP Minify, navigate to BWP Minify > Manage Enqueued Files and try excluding (i.e. ignoring) files there. It is recommended that you ignore 3-5 files at a time to make this process a little bit faster.

Pre-minified files

Files that are already minified should not be minified again, to save processing time and in turn improve server response time. Typical examples are files enqueued internally by WordPress, such as jquery and jquery-migrate.

If you’re using BWP Minify, there’s a trick to not minify pre-minified files but still combine them: simply put ‘min‘ in the files’ names, e.g. my.file.min.js or my-file-min.js. Note that this applies to both Javascript and CSS files.

For filenames that you don’t have control over, you have to again navigate to BWP Minify > Manage Enqueued Files and ignore them entirely. Note that ignored files are handled by WordPress and will not be combined with other files for now.

Less is more

WordPress minifying is done via PHP, which means your server will have to pass the request to PHP before it can return something sensible. For static assets like Javascript and CSS files that can increase page load time significantly if no caching is in place.

On-the-fly minifying means the minifying script must locate, minify, and combine each enqueued file every time it is requested. For that reason, an initial load (mostly without cache) can spike up to 9-12 seconds, or even higher, in processing time. It’s like opening several files on your computer and then trying to replace all linebreaks with blank spaces in all opened files at once (you know how slow that could be).

An easy solution is to reduce the number of files that are combined in one go. So instead of minifying 40 files in one single request, you should have four requests with 10 files combined each. This makes use of parallel download capability of browsers, like using a download manager. 4 smaller requests that are downloaded at the same time is much better than one heavy request that could result in timeout.

See Connections per Hostname column on this page to know the parallel download limit for some major browsers.

More Best Practices – Minify the Jedi-Master way

Cache-expiry headers

Minifying without cache-expiry headers is like (again) driving a racing car without a brake.

If you have no idea what a cache-expiry header means, check out this useful article for a brief introduction.

For minifying to work best, you will need either the Cache-Control header or the Expires header. With these headers properly set, a HTTP request for minified contents is only needed when cached contents has expired.

Setting the value of a cache-expiry header to a far future date is highly recommended, especially on live environments. It’s enough to use just Cache-Control, but it’s safe to use both. Note that Cache-Control will take precedence in modern browsers.

You can add cache-expiry headers via PHP1 or via server config files (for e.g. apache2, nginx3). If you use BWP Minify, cache-expiry headers are added automatically for you.

Dynamic to static

Instead of serving minified contents directly via PHP, let the server does the job. That sounds easy and obvious, but how do you keep the dynamic nature of plugins/themes at the same time?

The answer is to generate minified contents normally, but cache them somewhere and then make them publicly accessible for all future requests. PHP is only needed when the cache is invalid (not found or expired) or a forceful request is issued.

Such approach not only eliminates the needs to make a roundtrip to PHP every time, but also allows you to use nice names for minified contents, such as minify-javascript.js, and that makes CDN happy.

On a side note, the best place to put minified contents for WordPress is inside wp-content. If you use a cache plugin, chances are there’s already a cache directory there, ready to be utilized.

Most minifying plugins provide this feature, but since I’m biased, check out BWP Minify’s Friendly Minify Url feature, which has the same implementation as described above.

Use different caching mechanisms

When you first hear about caching, the most likely presented mechanism is file caching where contents are cached by storing them as files on disks. If your site has a fairly high number of visitors per day, this caching mechanism can be inefficient (it’s disk I/O after all, and it’s slow).

It’s much better to use memory caching mechanism to store and serve cached contents. Just think of your server as a regular PC, and your softwares will obviously run faster when they read data from memory instead of disks.

There are many ways to serve minified contents using memory caching. If Minify is the PHP library you’re using, you can customize its config file to use a specific PHP accelerator such as APC or XCache. You must of course properly configure the desired accelerator on your server prior to modifying the config file.

If you’re new to memory caching, APC’s documentation can be a good start.

Pre-minify for the win

Whatever approach you take to serve minified contents, an initial load can still be an issue. Any visitor that views your site when cache is invalid will surely notice a slowdown in page load time. To save that poor soul, you need to find something else to carry such burden, and cron job is the way to go.

The idea is to use a cron job to periodically visits a few unique pages on your site to force a refresh and cache on minified contents, so that when a visitor pays a visit it’s the cached version that he/she sees. Your site’s homepage, a post, a page or any other special ones can be considered unique.

You can use a real cron job4 or WordPress-simulated one5 for this task. The frequency of the cron job depends on how often your minified contents are updated, for e.g. daily or weekly.

If you want to refresh minified contents every time you activate/deactivate a plugin, simply call your refresh function every time upgrader_process_complete action hook is fired, using add_action6.

Conclusion

“With great power comes great responsibility”. To fully enjoy the benefits of Minifying, you need to understand common pitfalls and make sure that you follow best practices whenever possible.

I hope you find this article useful, and as always, comments and feedbacks are welcomed!

If you want to know more about HTTP requests and how they affect site performance, check out this classic: Steve Souders’ High Performance Web Sites.

References

  1. http://www.php.net/manual/en/function.header.php []
  2. http://httpd.apache.org/docs/2.2/mod/mod_headers.html []
  3. http://nginx.org/en/docs/http/ngx_http_headers_module.h ... odule.html []
  4. http://www.centos.org/docs/5/html/Deployment_Guide-en-U ... tasks.html []
  5. http://codex.wordpress.org/Function_Reference/wp_schedu ... dule_event []
  6. http://codex.wordpress.org/Function_Reference/add_actio ... add_action []

Take Social Sharing to
the Next Level with Monarch!

Take Social Sharing to the Next Level with Monarch!
Print Article Trackback Trackback to this Article   Subscribe to Comments RSS Subscribe to Comments RSS

21 Opinions for WordPress Minify – Best Practices (8 Trackbacks)

  1. User's Gravatar
    1
    Test July 11, 2014 at 4:01 pm – Permalink

    Excellent article!

  2. User's Gravatar
    2
    Kit July 16, 2014 at 1:33 pm – Permalink

    Wow! That was such a clearly-worded and well-organised article. I went from knowing almost nothing about minifying to feeling I know all that I need.

    Great work!

  3. User's Gravatar
    4
    Rabindra October 28, 2014 at 7:40 pm – Permalink

    Well, that was something useful. Thanks for the tips.

  4. User's Gravatar
    5
    Dalibor Sojic January 2, 2015 at 6:36 am – Permalink

    Firstly, I want to say “great” plugin in terms of minifying/combine a css/js files.

    I have following scenario, and need to fix the plugin… (probably there is a bug).

    The server has 2 IP addresses, running apache and nginx on each.

    Apache is for wordpress, nginx is for faster serving static files (let say cdn).

    In theme styles, there is:
    background: url(“../images/player/ff0000.png”)
    BWP Minify has: CDN hostname (primary) -> static.domain.com/theme (nginx server, theme points to wp-content/themes/theme/)

    Eventhough I have configured “CDN”, after minifying, background url is replaced with:
    background:url(“/wp-content/themes/soundwave/images/player/ff0000.png”).

    I was expecting all css images to be replaced with:
    background:url(“http://static.domain.com/theme/images/player/ff0000.png”)

    and of course, loading minified css to be from “cdn” instead of http://domain.com/cache/

  5. User's Gravatar
    7
    Hassan April 10, 2015 at 3:05 pm – Permalink

    BWP Minify is a great plugin. Works splendidly and might be one of the very few that actually dont break up everything. However according to my experience i have one issue with it. It works very well with websites which do not have too much traffic at a specific moment. This is because if its generating the minified files, those processes are quite low. However, for high load websites which have several hundred users any minute of the day, cache flushing becomes a pain in the head because right after the cache flushes, it spikes the server and is unable to generate minified cache files and just keeps on spiking the server until the plugin has to be de-activated.

    If the DEV team can somehow only initiate the minification process just once and wait until its completed while serving other users with older (or non minified) CSS files and once the minification is done, move all users towards the newer cached files. This issue can be resolved.

    • User's Gravatar
      8
      Khang Minh August 20, 2015 at 11:18 am – Permalink

      There’s one solution that doesn’t require code changes (for now): create a script that temporarily changes the cache directory to something like /path/to/cache/_minify (using a filter), then visit most important pages (it can simply be a list of URLs) so that cached files are generated in the temporary cache directory. Finally, remove the old cache directory and rename /path/to/cache/_minify to /path/to/minify. It should be pretty fast and its done just once.

      The above mentioned script should be executed via CLI or you can just append some kinds of tokens to a URL (e.g. http://example.com/?action=flush-minfy&token=secret). All visited URLs should have the action and token appended so that the script knows that it should use the temporary cache dir.

      That does sound like a lot of work for a user, though.

  6. User's Gravatar
    10
    Michael July 28, 2015 at 1:41 am – Permalink

    Thank you, for a good article!

  7. User's Gravatar
    11
    Yves September 17, 2015 at 8:17 pm – Permalink

    Hi Khang and thank you for this great article.

    I’m confused the pre-minified files and 2 things you wrote:

    • “Files that are already minified should not be minified again”
    • If you’re using BWP Minify, there’s a trick to not minify pre-minified files but still combine them: simply put ‘min‘ in the files’ names, e.g. my.file.min.js or my-file-min.js.

    Does it mean that we should select those “file-min.js” files then choose the “Not to minify” option. Or should we leave them as they are (i.e. “Minified in footer”) and let BWP do the job for us?

    Thank you for your answer.

    • User's Gravatar
      12
      Khang Minh September 20, 2015 at 1:23 pm – Permalink

      That means for scripts/styles that you develop yourself, you can put “min” in the files’ names to tell the plugin to NOT try minifying them again, thus achieving “Files that are already minified should not be minified again”.

  8. User's Gravatar
    13
    Flo October 5, 2015 at 6:49 pm – Permalink

    Hi,
    Im still confused.
    Lets try again with “Files that are already minified should not be minified again”:
    – ¿we have to put this word (min) in to “Scripts to NOT minify”?

    Regards.

    • User's Gravatar
      14
      Flo October 5, 2015 at 7:35 pm – Permalink

      Or exclude one by one?

      If I have to exclude one by one is very difficult because on windows where are .css &.js files the path is not visible even if mouse hover.
      I mean:
      for this url: wordpress/wp-content/themes/nametheme/design/js/portfolio-item.js

      on window/screen the link is cut like this:
      wordpress/wp-content/themes/cityguide/design/js/portfo

      So, is a pain to copy one by one and paste into a archive .txt to see if is .min.js or not.

      • User's Gravatar
        15
        Khang Minh October 6, 2015 at 12:28 am – Permalink

        You don’t have to cut and paste anything, what I suggested was meant for files that you yourself develop. For example you’re creating a theme, you would create some files such as style.css, window.css. In order for those files to be combined but not minified, you would enqueue them normally, but rename them to style.min.css and window.min.css.

        I will improve this by allowing you to specify a pattern to combine but not minify, please follow updates here: https://github.com/OddOneOut/bwp-minify/issues/34

        Hope that makes sense.

  9. User's Gravatar
    16
    FanRang October 7, 2015 at 12:41 pm – Permalink

    Im still confused.

  1. Better WordPress Minify:Best WordPress Minify Plugin

    […] I would suggest you to read WordPress Minify Best Practices […]

  2. tao of badass seduction blueprint pdf

    tao of badass seduction blueprint pdf WordPress Minify - Best Practices - Better WordPress

  3. How to Score 100 on Google PageSpeed Insights

    […] examples are files enqueued internally by WordPress, such as jQuery and jQuery-migrate.” – “WordPress Minify – Best Practices” by Khang […]

  4. Khang Minh on "[Plugin: Better WordPress Minify] Minify Files Wait 15 Seconds at Random" * Best Wordpress Themes - Reviews

    […] It could be the initial minification process that was slow. Take a look at this article for more info: http://betterwp.net/wordpress-minify-javascript-css/ […]

  5. Better WordPress Minify | Gdrive.fr

    […] http://prntscr.com/98arkb […]

  6. Khang Minh on "[Plugin: Better WordPress Minify] Plugin slows down my site" * Best Wordpress Themes - Reviews

    […] First of all, please give this article a read: http://betterwp.net/wordpress-minify-javascript-css/ […]

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: