Make WordPress Core

Tagged: optimization Toggle Comment Threads | Keyboard Shortcuts

  • Joe McGill 3:46 pm on March 12, 2016 Permalink
    Tags: , , , , optimization,   

    Performance improvements for images in WordPress 4.5 

    WordPress 4.5 includes a few performance enhancements for images.

    Increased image compression for custom sizes

    WordPress 4.5 increases the amount of compression applied to intermediate sizes by changing the default quality in WP_Image_Editor from 90 to 82. As noted in the proposal for this change, this results in a noticeable reduction in file sizes with little change in visual quality. Developers can override the default image quality value using the wp_editor_set_quality filter.

    Improved resizing settings for ImageMagick

    For sites making use of ImageMagick, we’ve reduced file sizes further by resizing images  more efficiently in WP_Image_Editor_Imagick and by stripping extraneous metadata using the new WP_Image_Editor_Imagick::strip_image() method.

    For now, ‘icc’ and ‘icm’ color profiles are retained, along with ‘exif’, ‘xmp’, and ‘iptc’ profiles, which can contain copyright and orientation data. Those who want to retain additional metadata can disable profile stripping by adding a callback function to the image_strip_meta hook that returns false.

    Note that the original full sized images uploaded to WordPress are unaffected by these changes.

    Introduction of wp_get_upload_dir()

    As Jeremy Felt mentioned in his post on Multisite changes, wp_upload_dir() received a major performance overhaul in this release. Those changes were pared with the addition of a new function, wp_get_upload_dir(), which can be used as a more performant way to display information about the uploads directory on the front end. This is particularly useful when building URLs for images in templates. (See #34359)

    • petermolnar 5:56 pm on March 12, 2016 Permalink | Log in to Reply

      I don’t welcome the default EXIF stripping. It’s not optimization, it’s removing information from a picture.

      • Joe McGill 6:43 pm on March 12, 2016 Permalink | Log in to Reply

        Hi Peter,

        Thanks for your comment. To be clear, Exif data is not being stripped by default at this time. Please reread the section about metadata stripping, which lists all the profiles that are retained. Sorry if that was unclear.

    • petermolnar 5:58 pm on March 12, 2016 Permalink | Log in to Reply

      • Destac 6:07 am on March 13, 2016 Permalink | Log in to Reply

        You should again reread that link the images are not having the data stripped but the resizing doesn’t carry the exif data over.

        WordPress strips EXIF data from the auto-resized versions of the images as a side effect. What it’s actually doing is creating new images from the original, and not copying that data.

        However, the original image is saved as-is, with all EXIF information included. The original image is not modified in any way.

        • Marko Heijnen 3:10 pm on March 14, 2016 Permalink | Log in to Reply

          That’s copy/pasting from the topic. I’m sure Peter can read. His first statement is still correct since WordPress by default with Imagick will strip information from a picture. Not the EXIF information but other related information.

          For GD I have played a bit to see what options we have and the only workable option is storing EXIF data as IPTC.

          • Destac 1:06 pm on March 15, 2016 Permalink | Log in to Reply

            Not true. His original statement says.

            I don’t welcome the default EXIF stripping. It’s not optimization, it’s removing information from a picture.

            So my statement as was Joe’s were still correct.

            On this separate matter i don’t see the value of this information vs stripping it which is recommended for

        • petermolnar 11:21 am on March 31, 2016 Permalink | Log in to Reply

          resizing does carry EXIF over. GD used to strip it, imagick does not.

    • Kochhase 2:10 pm on March 15, 2016 Permalink | Log in to Reply

      hello, “along with ‘exif’, ‘xmp’, and ‘iptc’ profiles, which can contain copyright and orientation data”. in germany the there is a § for that. http://dejure.org/gesetze/UrhG/95c.html. so wordpress does not authorized to remove this information.

    • FolioVision 10:34 pm on March 28, 2016 Permalink | Log in to Reply

      This is great work Joe. Wonderful to have better core support of ImageMagick (IM really does make a huge difference in quality). Any chance we could get a Setting screen in the backend to handle the Media Library and these settings. Making them command line only seems pretty user unfriendly. Even if one has to flick a switch to make them available (i.e. add Advanced Media Settings checkbox somewhere visible by default).

      Alec Kinnear

      • Joe McGill 11:59 am on March 31, 2016 Permalink | Log in to Reply

        Thanks Alec,

        While we aren’t planning to add a screen to control specific ImageMagick settings in core, I think it would be a wonderful plugin for those who are interesting in controlling the fine details.


    • Bayu Angora 11:40 pm on April 13, 2016 Permalink | Log in to Reply

      So, we don’t need image compress plugin anymore?

      • Joe McGill 1:19 am on April 14, 2016 Permalink | Log in to Reply

        It’s likely that you still might get some benefit out of some compression plugins, but it shouldn’t be nearly as dramatic as it was before. Best thing to do is to evaluate the difference you’re seeing in quality and performance between WordPress defaults and what your compression plugin gives you and decide if it’s worth continuing to use a compression plugin in your particular use case.

    • ninjaunmatched 5:09 pm on April 15, 2016 Permalink | Log in to Reply

      Will the new compression be applied to existing images or only new uploads?

    • nekroido 8:28 pm on April 20, 2016 Permalink | Log in to Reply

      Are you planning on enhancing the resizer with focal points support? The feature is quite vital for custom themes and support for mobile apps.

    • Simon Pollard 3:39 pm on May 11, 2016 Permalink | Log in to Reply

      Apologies if this is a silly question – if a user uploads an image that is 1024 x 768 and I have a custom thumbnail size that is 1024 x 768 that I use in my code and request that version of the thumbnail. Will the image I get back be the original uncompressed image, or will I get an optimised one? If it is the original do I need to ask my user to upload images 1025 x 768 to enforce a compression? Hope that makes sense.

      • Simon Pollard 8:07 am on May 12, 2016 Permalink | Log in to Reply

        So it appears if the size of an image matches the size of a specified image size by add_image_size() it does not get created and thus not optimised. If I make the image 1px larger it will then create an optimised version. Is there any way to enforce optimisation on all images or enforce the creation of an optimised image size version?

    • Mikel King 3:48 pm on May 18, 2016 Permalink | Log in to Reply

      Is there a guide somewhere that explains how this works from the content creation to hydration process?

  • Andrew Ozz 8:10 pm on April 4, 2011 Permalink
    Tags: optimization   

    To the Directors of White Space 

    Dear Sirs,

    It has come to my attention that our White Space is running wild. Would it be possible to tame that beast back into submission please.

    Seriously, I would like to propose adding another rule to the coding standards: when outputting HTML directly, leave all white space in PHP. Currently we do something like this:

    if ( something ) {
        <div id=...>some more</div>
        <div id=...>even more</div>

    That’s all nicely readable on the PHP side but the outputted HTML is surrounded by quite a bit of redundant space. What I’m proposing is to stop/start PHP immediately around the HTML:

    if ( something ) {
        ?><div id=...>some more</div><?php
        ?><div id=...>even more</div><?php

    This doesn’t impact the readability on the PHP side and produces “tight” HTML with no white spaces as it should be for production. In fact the HTML source would be “pseudo-minified”.

    Of course the readability of the HTML source will be affected but not that much. Currently our HTML output is all over the place which makes it pretty hard to read. Considering that most people never look at the HTML source directly any more thanks to FIrebug and friends and all coding oriented text editors have a function to reformat HTML, I believe outputting “minified” HTML is an advantage. This also reduces the size of our output from 3% to 15% depending on the page.

    Of course I’m not proposing for everybody to rush and reformat the whole codebase if this is accepted. But we can apply it to new code and clean up functions that are being patched for other reasons.

    • Ken 8:20 pm on April 4, 2011 Permalink | Log in to Reply

      This would be fine with me, I also use firebug when examining html.

    • Joseph Scott 8:25 pm on April 4, 2011 Permalink | Log in to Reply

      Wouldn’t it be better to optimize for the code that is read more often (PHP)? For HTML there are plenty of options to minify automatically if you want to go that route.

      • Alex M. 8:44 pm on April 4, 2011 Permalink | Log in to Reply

        This is my thoughts as well. While pretty HTML is nice, pretty PHP should be the priority IMO. Stepping into PHP just to step right back out again on the next line seems like a waste and makes it a lot harder to read.

        As for size, if that’s a concern then gzip should be used.

      • Andrew Ozz 8:55 pm on April 4, 2011 Permalink | Log in to Reply

        Yes, we can minify the HTML automatically but that’s just another (although minimal) overhead. IMHO if we leave all white space in PHP we are optimizing both at the same time.

        Our code is already pretty much optimized for readability on the PHP side. If we accept this as coding standard, it would enhance the PHP side a bit (as we won’t have to think about HTML output formatting at all and can place it anywhere we need) and also enhance the HTML output a lot.

      • Andy Skelton 9:07 pm on April 4, 2011 Permalink | Log in to Reply

        I agree with Joseph. I spend so little time looking at the HTML output that I couldn’t care less what whitespace there is. When I’m looking at PHP, I don’t want to have to look at the beginning and end of every line. That’s even worse than reading a long column of echoes.

      • Andrew Nacin 11:17 pm on April 4, 2011 Permalink | Log in to Reply

        I agree with Joseph and Andy as well.

      • Brian Layman 2:28 pm on April 6, 2011 Permalink | Log in to Reply

        I’m in this camp too.

        Plus this may appear moderately readable with two lines but once you get into more it doesn’t hold up nearly as well. I’d rather be consistent in our handling and also save 7 bytes per line of code.

    • Jon Brown 8:36 pm on April 4, 2011 Permalink | Log in to Reply

      Isn’t what you’re proposing the opposite of the existing coding standards which are to open/close php around the actual PHP? More like:

      if ( something ) { ?&gt;
           &lt;div id=...&gt;some more&lt;/div&gt;
           &lt;div id=...&gt;even more&lt;/div&gt;
      &lt;?php }

      Which is compact and doesn’t needlessly open and close php (although I’m pretty sure that’s been shown not to be a performance issue, right?)

      • Ramoonus 12:33 pm on April 5, 2011 Permalink | Log in to Reply

        this is what I prefer, much easier to read
        and most programs can do color coding with this format

    • Mike Schinkel 8:50 pm on April 4, 2011 Permalink | Log in to Reply

      Here’s a question I don’t know the answer to: Is there any performance penalty for excessive context switches between PHP and HTML? Also, rather than context switching, why not use HEREDOCs instead?

      • Andrew Ozz 8:59 pm on April 4, 2011 Permalink | Log in to Reply

        As far as I can tell, no. No performance penalty for switching in and out of PHP at all. IMHO HEREDOC is quite hard to read and is inflexible in many cases.

    • scribu 9:06 pm on April 4, 2011 Permalink | Log in to Reply

      We should avoid context switches, not for site performance, but for developer performance, as Joseph Scott already mentioned.

      Adding more characters to reduce whitespace doesn’t seem like a sweet deal to me. A standard in this area would be good, but not that one.

      How about:

      if ( something ) {
          &lt;div id=...&gt;
          &lt;div id=...&gt;&lt;?php inline_call(); ?&gt;&lt;/div&gt;

      Multi-line blocks should never be indented.

      • Alex M. 9:09 pm on April 4, 2011 Permalink | Log in to Reply

        This is how I write and prefer code.

      • Andy Skelton 9:12 pm on April 4, 2011 Permalink | Log in to Reply

        I recently banished all thoughts of pretty HTML and decided to focus on PHP indentation. So I indent the PHP tags. Here’s my example:

        if ( $lines ) {
            &lt;div id=&quot;lines&quot;&gt;
            foreach ( $lines as $line ) {
                &lt;p class=&quot;line&quot;&gt;&lt;/p&gt;
    • Ken 9:09 pm on April 4, 2011 Permalink | Log in to Reply

      Alternatively, we can recommend NOT using indents for html blocks, but rather line-breaks and comments:

                  if ( something ) { ?&gt;
      &lt;!-- #someid --&gt;
      &lt;div id=&quot;someid&quot;&gt;some more&lt;/div&gt;
      &lt;div id=...&gt;even more&lt;/div&gt;
      &lt;!-- /#someid --&gt;
                  php }

      I’d just be happy with any standard.

      • Brian Layman 2:30 pm on April 6, 2011 Permalink | Log in to Reply

        I imagine my preferred standard of making the HTML indented to the correct level when the HTML source is viewed would be generally hated by all 🙂

    • miqrogroove 9:24 pm on April 4, 2011 Permalink | Log in to Reply

      The only time this white space has ever mattered to me is when dealing with textarea elements, which have a required trailing linefeed. At any other time, I would prefer the former syntax for simplicity and let the HTML look slightly out of alignment. I would never try to minify my HTML.

      • Ken 9:30 pm on April 4, 2011 Permalink | Log in to Reply

        There was a trac ticket a while back about white space between Nav LIs that caused styling issues… He was setting the menu items to display: inline. That and your textareas are the only things I can think of.

    • demetris 10:12 pm on April 4, 2011 Permalink | Log in to Reply

      I think the gain in size is not worth it because, when the document is gzipped, the reduction in percentage is much smaller: 2 or 3 percent at most. (Which, in absolute numbers, is an even smaller gain.)

      My personal preference at present is to always stay in PHP mode. I use echoes with a line feed at the end of the string. So, the only white space in the generated HTML is line feeds. (One reason I started using this style is that HTML highlighting with a PHP document distracts me.)

      • Andrew Ozz 10:33 pm on April 4, 2011 Permalink | Log in to Reply

        Agreed. Assuming that most hosting companies gzip HTML by default the gain will be even smaller: about 0.1% and under as white space compresses extremely well.

      • Jan Fabry 6:47 am on April 5, 2011 Permalink | Log in to Reply

        Indeed, I also prefer to stay in PHP mode. With this proposal the difference will be even smaller, so if there would be a change, I propose it is to PHP-with-echo everywhere.

    • arena 10:59 pm on April 4, 2011 Permalink | Log in to Reply

      ok for me and please please remove the trailing and useless ?> in most wordpress php files

      • Peter Westwood 7:15 am on April 5, 2011 Permalink | Log in to Reply

        It’s not useless – it is good practice in my opinion and makes it easier to identify when people have uploaded part of a file by FTP

        • Mike Schinkel 7:21 am on April 5, 2011 Permalink | Log in to Reply

          I’ve seen whitespace after a trailing ?> cause syntax errors. I’ve never seen those same syntax errors occur when there is not a trailing ?>. FWIW.

        • Peter Westwood 7:24 am on April 5, 2011 Permalink | Log in to Reply

          Syntax errors seems unlikely, Headers already sent is probably what you saw.

        • Mike Schinkel 7:28 am on April 5, 2011 Permalink | Log in to Reply

          Possibly. Either way it was a fiddly error that can take a while for many people to track down. Again, FWIW.

        • Dion Hulse (dd32) 8:50 am on April 5, 2011 Permalink | Log in to Reply

          Mike: Thats the exact reason why user editable files in WordPress don’t have the closing php marker (wp-config-sample.php and themes functions.php)

          But for all other files, no user should edit them, so its a useless argument there

        • Mike Schinkel 8:57 am on April 5, 2011 Permalink | Log in to Reply

          @dd32 – Although it’s not worth debating as an attempt to change the opinions of the core team related to the source files in WordPress, as a point of note it is not completely useless.

          People accidentally modify files all the time. If they open a core file to learn what it does but accidentally add white space to the end they can spend quite a bit of time trying to figure out why their site code now fails although they can’t “see” any difference.

          Again, FWIW.

    • arena 11:28 am on April 5, 2011 Permalink | Log in to Reply

      having or not having a ?> at the end of a file do not mean you have reached the end of the file ….
      then change the
      trailing ?>
      /* end of file */

    • John James Jacoby 1:22 am on April 12, 2011 Permalink | Log in to Reply

      I’m against the grain with everyone here. Go figure. 🙂

      I think having pretty HTML output is important, because scanning through randomly indented HTML output is as irritating as scanning through randomly indented PHP. Call me old school, but I miss the days of having poetically formatted HTML when viewing HTML source on a site. 🙂

      I also prefer not to echo out HTML from inside PHP, and rather close out of PHP and output raw HTML. PHP is a scripting language that essentially provides logic to HTML. Using it to output complete lines or blocks of HTML seems counter-intuitive to me, so it’s reserved in my toolbox for special cases where I may want to filter that chunk of HTML through a WordPress filter.

      This was one of my original kvetches about WordPress when I stopped lurking and started posting in the support forums. (Embarrassing reading my tone back then as an outsider to the community.)

      The problem arrises from having tabs in front of the PHP open brace. It’s good for PHP code readability, but bad for HTML output readability.

      This example taken from index.php of twentyten:

      &lt;?php get_header(); ?&gt;
      		&lt;div id=&quot;container&quot;&gt;
      			&lt;div id=&quot;content&quot; role=&quot;main&quot;&gt;
      			/* Run the loop to output the posts.
      			 * If you want to overload this in a child theme then include a file
      			 * called loop-index.php and that will be used instead.
      			 get_template_part( 'loop', 'index' );
      			&lt;/div&gt;&lt;!-- #content --&gt;
      		&lt;/div&gt;&lt;!-- #container --&gt;
      &lt;?php get_sidebar(); ?&gt;
      &lt;?php get_footer(); ?&gt;

      …should really be…

      &lt;?php get_header(); ?&gt;
      		&lt;div id=&quot;container&quot;&gt;
      			&lt;div id=&quot;content&quot; role=&quot;main&quot;&gt;
      			/* Run the loop to output the posts.
      			 * If you want to overload this in a child theme then include a file
      			 * called loop-index.php and that will be used instead.
      			get_template_part( 'loop', 'index' );
      			&lt;/div&gt;&lt;!-- #content --&gt;
      		&lt;/div&gt;&lt;!-- #container --&gt;
      &lt;?php get_sidebar(); ?&gt;
      &lt;?php get_footer(); ?&gt;

      The differences being the whitespace before the opening and closing PHP braces is gone, and there is an additional empty line before and after the context switch to ensure the output of get_template_part() has breathing room. In the above example, the next problem is that loop.php starts out only indented 1 tab in, rather than 4, which starts the cycle of messy HTML whitespace over again.

    • John James Jacoby 1:35 am on April 12, 2011 Permalink | Log in to Reply

      Maybe we should write a plugin to format the HTML output for us?


  • Matt Mullenweg 4:45 pm on April 1, 2009 Permalink
    Tags: optimization   

    Idea: We should do a branch prior to rel… 

    Idea: We should do a branch prior to release (we do this anyway) and then commit to that branch a minimization of all JS and CSS, so trunk always has pretty-formatted, and release branches always have minimized.

    Or this might not be needed with Andrew’s new stuff.

    • Denis de Bernardy 8:08 pm on April 1, 2009 Permalink | Log in to Reply

      Isn’t there a way to add an svn hook on tag?


      That way, branches would also be pretty formatted, and only actual released versions would be minified.

    • DD32 10:04 pm on April 1, 2009 Permalink | Log in to Reply

      Its a thought, But many run on trunk daily anyway.

      I cant remember what the constant is to use non-compressed scripts, Maybe if WP_DEBUG is enabled, then non-compressed scripts could be used instantly?

    • Xavier 8:37 am on April 2, 2009 Permalink | Log in to Reply

      Sounds like a must to me.

      Also, why not go one step further? Keep trunk’s PHP code clean and commented, and minimize that too in the release branche.
      Of course, that would mean those why want to explorer WP’s inner-working would have to grab the trunk, and that older full-version of WP wouldn’t be fully available.

      So (typing while thinking here), would it be cool to cater to everyone : provide a fully-minimized archive (PHP, CSS, JS) for default users, and keep a “maximized” archive as-well, for further reference?

      (unless, it’s all part of an elaborate April-fools scheme, in which case, well, my case still holds 🙂 )

      • Gmcosta 5:45 pm on April 2, 2009 Permalink | Log in to Reply

        too much work I suppose.

      • Peter Westwood 6:20 pm on April 7, 2009 Permalink | Log in to Reply

        Minimising too much in the branch/tag will just make patching / generating patches too much work.
        I can see the benefit of js/css minification but not php.

      • Xavier 2:50 pm on April 10, 2009 Permalink | Log in to Reply

        @Peter: obviously, and likewise for CSS and JS, at a lesser level. Hence my suggestion for two archives per tag: a fully-minimized as default (for those who won’t look into the code), and an untouched one (for devs and the curious at heart).

        I’m not suggesting minimizing in the branche, since that’s the basis for any further minor version, but for the the tag, which is meant to be definitive – or so I understand.

        I could be way off, obviously. And the profit could me meaningless, but hey, we’re here to discuss 🙂

    • Robert Accettura 12:59 pm on April 2, 2009 Permalink | Log in to Reply

      IMHO this should be part of tagging. There’s a few advantages here:

      1. Less overhead for last minute changes on branch.
      2. Most people who want optimization and polish and can’t do it themselves run tags anyway.
      3. minimized code is harder to debug. If your not using a tag, you should have easy debug abilities.

      Why not just automate the creation of a tag with a make/ant/shell/configure/whatever script that creates minimized versions of js/css (use the format [name].min.[ext]) when a tag is made and changes a flag in wp-config.php to prefer the .min if it exists. This has a few nice things:

      1. Tagging is as simple as running a script which will create the tag, minify, and commit.
      2. No worries about forgetting to update minified and non-minified code like on a branch since tags are (or should be) final.
      3. By using a flag in wp-config.php to prefer minified version of js/css you can just change the flag to use the non-minified versions… This is awesome for when you want to debug.
      4. Theme/plugin authors can utilize the wp-config flag to ensure their theme/plugin offer a minified/non-minified verisons.
      5. As a bonus, you could include the minifier in WP to make it even easier when editing css/js via wp-admin.

      Just my $0.02

    • Nate Moore 9:18 am on April 12, 2009 Permalink | Log in to Reply

      I agree

    • Simon Wheatley 1:53 pm on April 18, 2009 Permalink | Log in to Reply

      How about having the JS in two states: uncompressed (which the default enqueuing stuff uses if a constant, maybe reuse WPDEBUG?, is specified in wp-config.php) and compressed which is used by default. Uncompressed is used for dev, and an SVN post-commit hook script could automagically compress/minify/pack/whatever’s-currently-best the committed uncompressed JS files. An SVN ignore property could be set to ignore all *.cmp.js files (or some other filenaming schema for compressed files) to ensure they don’t get committed accidentally.

    • Andrew Ozz 1:51 am on April 20, 2009 Permalink | Log in to Reply

      Currently both the minimized (.js) and the non-minimized (.dev.js) versions of all custom scripts are included. This was mainly so we can test if minimizing works well. If we decide to go with two builds per release: “production” and “development”, we can remove the non-minimized scripts form the first (will have to change script-loader there too). This will reduce the download size/number of files in the install package a little bit, not sure if it’s worth it…

      Stripping all PHPDoc/PHP comments would reduce the download size a lot more.

  • Andrew Ozz 4:41 pm on February 6, 2009 Permalink
    Tags: optimization   

    Script loader updates 

    There are several updates to the script loader currently in WordPress 2.8-bleeding-edge that enhance and optimize loading of external JavaScript and CSS files.

    Probably the most important change is that scripts can be queued for loading in the footer for both the admin and the front-end. This is done with an optional argument. To enqueue a script for the footer:

    wp_enqueue_script( 'name', 'url/to/file.js', array('dependency'), 'version', true );

    where “true” means enqueue for the footer (“false” is the default and is optional).

    When a script is enqueued for the footer all dependencies will be added (if not already present) and will be printed before the script. Some may be in the head, others also in the footer. By default only jQuery is printed in the head but when a script is enqueued for the head, all dependencies would also be printed in the head. Almost all external scripts would run onload or after the page has loaded, so there’s no real need to queue anything for the head.

    Scripts queued for the front-end footer depend on wp_footer(); being present in the current theme. Unfortunately some themes don’t include it. The best way to remedy this would be to bring awareness among users and theme designers as suggested by several plugin developers.

    To make queueing of scripts easier two new actions have been added: "wp_enqueue_scripts" that runs in the front-end head where all is_page(), is_home(), etc. functions are available and "admin_enqueue_scripts" that runs in the admin head and has the current page hook as argument, so scripts can be queued only for specific pages.

    Another major new feature is that all core admin scripts are concatenated and compressed before sending them to the browser. This feature can easily be extended to include scripts added by plugins and to use server side caching, however that would require some changes to the server settings (.htaccess on Apache).

    Since compression from php can be problematic on some hosts there are several “switches” (constants) that manage it: define('CONCATENATE_SCRIPTS', false); would turn off both concatenating and compressing of all scripts. It’s intended for script debugging, define('COMPRESS_SCRIPTS', false); can be used to turn off compression for JavaScript and define('COMPRESS_CSS', false); for CSS files. Compression is set to “deflate” by default since it’s faster and uses a little less server resources. Gzip can be forced by setting define('ENFORCE_GZIP', true);

    There is a test if compressing from php works as expected on the server and whether the server compresses scripts by default. It runs only once and saves the result in an option “can_compress_scripts”. It would run again if the option is deleted.

    In addition all core scripts are minified. All custom scripts are included in two versions: .dev.js is the non-minified script and .js is the minified one. The constant define('SCRIPT_DEBUG', true); would load the .dev.js versions of the scripts making them easier to debug.

    Possible changes: removing the COMPRESS_CSS switch and using only COMPRESS_SCRIPTS, using deflate for compression but adding the gzip file header and serving it as “Content-Encoding gzip” since it seems more compatible with the various web servers and proxyes (all modern browsers support deflate well).

  • Andrew Ozz 3:07 am on January 15, 2009 Permalink
    Tags: optimization   

    Optimizing script loading, implementation 

    The “first run” of the script loading optimization is in trunk. It uses both methods: splits the scripts queue in head and footer parts, then concatenates and compresses them before sending them to the browser. Most CSS is also concatenated and compressed.

    There are two new constants that disable concatenating and compression: CONCATENATE_SCRIPTS and COMPRESS_SCRIPTS. Setting the first to false would disable both concatenating and compression, the second disables compression only. There is also a simple AJAX method to test if compressing from PHP works as expected on the server. It is run only once and the result is saved as an option. It will run again if that option is deleted.

    For plugin authors there are two new actions in the admin footer: do_action('admin_print_footer_scripts'); and do_action("admin_footer-$hook_suffix");. The order of execution is:

    1. "admin_footer" can be used to print scripts before the default footer scripts
    2. "admin_print_footer_scripts" used to print the default scripts followed by any external scripts that were queued for the footer
    3. "admin_footer-$hook_suffix" can be used to print scripts that should appear on a specific admin page only

    The preferable way for plugins to add scripts to admin pages would be either to enqueue them properly (which is a must if the script depends on a default script) or to use the $hook_suffix hooks to add them only where needed.

    New hook(s) may also be needed in the functions dealing with splitting or concatenating the script queue. Suggestions are welcome either here as comments or on trac as enhancements tickets.

    Update: added do_action('admin_enqueue_scripts', $hook_suffix); allowing plugins to easily queue scripts on the exact pages. To find out the value for $hook_suffix on a specific page, echo it from your function and visit the page.

    Queueing a script for the footer follows the same syntax as in script loader:

    $scripts-&gt;add( 'handle', 'full/url/to/file.js', array( 'dependency' ), 'version' );
    $scripts-&gt;add_data( 'handle', 'group', 1 );

    Group 1 means queue for the footer, group 0 (zero) is the default.

    • GaMerZ 8:09 am on January 15, 2009 Permalink | Log in to Reply

      Hmm, any idea how do I queue script for the footer?

    • Andrew Ozz 9:00 am on January 15, 2009 Permalink | Log in to Reply

      Just updated the post with an example.

    • GaMerZ 9:09 am on January 15, 2009 Permalink | Log in to Reply

      Thanks =D What about the footer for the normal pages?

      perhaps modify wp_enqueue_script to accept 1 more argument which is group?

      So that one can do this
      wp_enqueue_script('wp-postratings', plugins_url('wp-postratings/postratings-js.js'), array('jquery'), '1.50', 1);

    • GaMerZ 9:37 am on January 15, 2009 Permalink | Log in to Reply

      I managed to enqueue stylesheets to specific pages in WP-Admin with the following code:

      ### Function: Enqueue Ratings Stylesheet In WP-Admin
      add_action('admin_enqueue_scripts', 'ratings_stylesheets_admin');
      function ratings_stylesheets_admin($hook_suffix) {
      	$postratings_admin_pages = array('wp-postratings/postratings-manager.php', 'wp-postratings/postratings-options.php', 'wp-postratings/postratings-templates.php', 'wp-postratings/postratings-uninstall.php');
      	if(in_array($hook_suffix, $postratings_admin_pages)) {
      		wp_enqueue_style('wp-postratings-admin', plugins_url('wp-postratings/postratings-admin-css.css'), false, '1.50', 'all');

      As stylesheet will always be in the head, this will work beautifully.

      Most people register JavaScripts via wp_enqueue_script() or a combination of wp_register_script() and wp_print_scripts(). Accessing $wp_scripts and setting the group via add_data() is a little bit weird at least from a plugin author point of view.

      If we can get wp_enqueue_script() to have a “group” argument. The script loader will know whether when the JavaScript will be loaded at the header or footer and load it accordingly while still hooking onto “wp_print_styles” or even “init”.

      In order to print JavaScript onto a normal page (outside WP-Admin), currently I have to hooked onto “wp_footer”, calling wp_register_script() and then calling wp_print_scripts().

    • Andrew Ozz 10:44 am on January 15, 2009 Permalink | Log in to Reply

      Agreed, will add the extra param to wp_enqueue_script() and wp_register_script().

      The front-side problem is a harder one. Many themes don’t seem to have the “wp_footer” call. The “get_footer” action can be used instead but that makes printing scripts there less effective as it runs too early, before the footer HTML. Even seen a few themes that don’t have a consistent footer and don’t use “get_footer”.

    • Frank 11:13 am on January 15, 2009 Permalink | Log in to Reply

      Thanks, i wait so long for this function.

    • GaMerZ 1:33 pm on January 15, 2009 Permalink | Log in to Reply

      @Andrew: Yea, some themes does not even have wp_head() in their header.php as well. The only way around this is to bring awareness I think.

    • Frank 6:33 pm on January 15, 2009 Permalink | Log in to Reply

      Hello Andrew,
      i hope you write over the new paramters for hook in the footer of frontend. This is very nice for better perfromance and control the js in footer. I like the wp_enqueue_* functions and i hope more themes-developer use thsi for intecrate the js-libraries. I see so much themes with a lot of plugins and many plugins load the sam js-library in the head and the site is slow and the user can not read the content. T think, wp_enqueue* is a very nice function for control js and css in the site. Very good for backend in plugins and also for hook in frontend.
      *sorry for my bad english

    • bttv 3:43 pm on May 9, 2009 Permalink | Log in to Reply

      I hope this optimization work without errors in version 2.8.

    • Kim 6:03 pm on February 17, 2010 Permalink | Log in to Reply

      Super duper writeup on how to use the built-in wp_scripts and wp_styles hooks… Also I learned about the JS footer thing 😉

      Thanks again!

    • Tsafi 10:51 am on March 9, 2010 Permalink | Log in to Reply

      Thanks Andrew you realy save me alot of time with this post.

  • Andrew Ozz 12:35 pm on January 7, 2009 Permalink
    Tags: optimization   

    Optimizing script loading, part II 

    After more tests and research it seems the best two options for the WordPress admin are either minifying all scripts and loading most in the footer or concatenating and compressing them on per page basis.

    Minifying and loading scripts in the footer gives slightly slower performance with both cold and primed cache and would depend on the ability to set appropriate caching headers on the server. On the plus side this method would be compatible with the current plugins and wouldn’t introduce higher server load.

    On the down side the loading speed improvement with primed cache would depend on the availability of mod_headers and/or mod_expires (presuming most installations are on Apache). It seems many hosts have either one or both modules installed but that still leaves a lot of installations without proper caching headers. In these cases the browser would keep checking for updated content which would increase the loading time with primed cache considerably.

    Concatenating and compressing all scripts would give better speed improvement and we will be able to set all needed headers. The last couple of days I’ve been testing a method that uses a separate php file similar to how the Gears manifest is produced. This is the same basic method used by many “website php compressors”, a stand-alone php function that gets as argument the names of the needed scripts then concatenates and compresses them. It doesn’t use server side caching (that proved to be problematic on some servers) since the cold cache page hits on the admin are relatively few.

    The advantage is that WordPress is not run second time on every cold cache page load so it uses a lot less server CPU time and memory. The disadvantage is that it would work only for the default scripts whose paths are included in the script loader. This also seems to be compatible with all existing plugins as any additional scripts are loaded after the single script and all requirements are satisfied.

    Another disadvantage is that a few hosts seem to compress all php output in a non-standard way that may result in double compression. This method would also need “Optimization options” screen with a few checkboxes that would allow the user to enable/disable the concatenating and compression as it won’t be needed when using Gears.

  • Andrew Ozz 3:12 am on December 27, 2008 Permalink
    Tags: optimization   

    Optimizing script loading 

    WordPress is using more and more JavaScript. A lot of features use AJAX and nearly all UI customizations and enhancements depend on it. In 2.7 there is some optimization for caching, especially when Turbo (Gears) is used all pages load in under 1 sec. However the cache control was left to the server and there seem to be a lot of servers with less than perfect settings for it.

    There are many ways to optimize script loading in 2.8. Listing several of them roughly in order of ease of implementation/most effective:

    • Minify (but not “pack”) all js files. Although the file size is larger, minified js loads faster than “packed” js, as it takes the browser some time to “unpack” it. Here’s a nice post on the subject. In 2.8 we should replace all “packed” js with minified and also minify all custom js when building the release.
    • Load most js in the footer. Even with 15 – 20 js files a page will load a lot faster when most are in the footer. In theory we can load all but jQuery in the footer. There’s a ticket and patch for the script loader to do this. However in practice that will interfere with many plugins that load any of the default js files on admin pages. Seems that if we load jQuery and any jQuery UI parts in the head, the great majority of plugins won’t be affected. Another option would be to queue all UI parts for the footer but move them to the head if a plugin loaded js lists them as dependencies (that would complicate the script loader a bit).
    • Setting custom caching headers in .htaccess. Although this may not work on all servers, chances are that the great majority of installations would benefit. There are several settings that can be added: the “expire far in the future” is a must, either configuring or disabling Etags for the js, css and image files is advisable, also several of the HTTP 1.0 cache control headers would be beneficial. Of course this would need testing on different production servers, but it would degrade gracefully (just wouldn’t work), so counting it as “must implement”.
    • Adding all js and css files in both compressed and uncompressed state and setting the server (.htaccess) to use the compressed versions whenever possible. This would greatly improve the initial loading of all scripts (cold cache), but is not as trivial to set up as the cache control headers. Still worth a try even if not all WordPress installations would benefit. It is possible to set the server to compress “on the fly” or compress by using php, but both methods use a lot more of server CPU time/memory on each page load. Since this affects only cold cache hits, not sure if it’s worth it. The typical user case for the admin is the same user on the same computer and in the same browser accessing the admin at least several times per week. So making sure caching works best is a priority.
    • Concatenating all default js files on per page basis so there’s only one js file to load. This combined with compressing the file would give the fastest loading time for both cold and hot cache, although for hot cache with proper cache control the difference is almost unnoticeable. It is possible to do this when building the release and include two versions of each file: compressed and uncompressed, then use .htaccess to output the compressed version when possible. However when there is a plugin that loads js and depends on other default js files, the performance degrades quickly and most blogs seem to have at least one such plugin. The workaround is to dynamically generate the concatenated file for each page, compress it and store it on the server. That would mean doing something similar to WP Super Cache but only for the js and css files in the admin. There seem to be at least one plugin that attempts to do this, also several regular WordPress contributors are interested in making such plugins. Perhaps for now it’s better to leave this for a plugin as there seem to be many server configurations where it would be difficult to set up or won’t work properly. We can also add some hooks in script loader to facilitate this if needed.

    In terms of performance the concatenating and compressing of all js and css files for each page gives the best results, closely followed by the loading of most js files in the footer. If we decide not to do the concatenating/compressing, we should revisit it in about a year (for WordPress 3.0?) as most Web hosts would have upgraded to php 5 by then. The actual php version wouldn’t affect this, but it seems that while upgrading the hosts also improve their server and php configurations too.

    • Gregory 3:57 am on December 29, 2008 Permalink | Log in to Reply

      It would be great if wordpress was compatable with mod_concat and mod_jsmin. I have attempted to implement both apache modules with 2.7 with limited results

    • Jacob Santos 3:58 pm on December 29, 2008 Permalink | Log in to Reply

      If hosting servers don’t support PHP5 now, then they’ll probably won’t in another year or two.

    • Rahul Boss 10:44 am on December 30, 2008 Permalink | Log in to Reply

      mainly now all hosting servers support php5.

    • miloandrew 11:03 pm on December 31, 2008 Permalink | Log in to Reply

      Many of your ruminations are understandably taking into account the huge array of available WP plugins. While this is absolutely necessary, maybe taking a bit of a different tack can open up some options?

      I have often wished that I could manage the load order of plugins and control which loads before another, or even WHEN a plugin loads at all. Could it be that implementing more internal plugin declaration and control could help with the overall compatibility of this optimization initiative?

      If we make it possible for the system to detect the way certain plugin scenarios will affect optimization efforts, then the system can adapt on its own. Rather than making global decisions on optimization based upon what COULD exist with certain plugins, maybe taking the tack of allowing the plugins to tell the system what they load and require would do the trick?

      The plugin header could potentially be extended to either allow the developer to state when the plugin should be loaded, or at least to specify other items that it either requires or loads itself. A “Loads:” field along with a “Requires:” field could go a long way to helping WP understand what the activated plugins require. It could also help the user make intelligent decisions by allowing the system to report if the activation of a specific plugin will necessitate the disabling of a specific optimization technique that would otherwise be used by the core.

      Alternatively (or in addition to the above), you could allow the WP admin to specify where and when all active plugins are loaded. While I would love to see this type of completely configurable plugin management, I think that even just the additional declarations could be extremely helpful.

      Sorry – I don’t mean to digress from optimization to plugin management, but it seems that there may be a few strong ties between the two.

      Thanks for listening!


    • Andrew Ozz 10:22 am on January 3, 2009 Permalink | Log in to Reply

      @Jacob Santos, @Rahul Boss yes, but most hosts require the user to manually switch to php 5, sometimes by directly editing .htaccess. Don’t think that most users are comfortable doing that or even aware of it.

      @miloandrew almost all of these features already exist in the API. In the case of script loading, plugins can enqueue both js and css and require any of the scripts included in WordPress. Unfortunately not all plugins use the script loader, but most do.

      The optimization will have to be transparent for the plugins. For example setting appropriate caching headers for js, css and images in .htaccess would affect all scripts.

      The load order can be managed from the filter/action priority quite well. The blog admin can edit the plugin’s file and change that if needed or have a small plugin that would set it up for the rest.

      BTW the first step is already implemented. All js has been minified reducing the size by about 30% – 35%.

    • Milan 1:31 pm on March 22, 2009 Permalink | Log in to Reply

      I am not sure where to post this, but I’ll start from here since title of this post describes my intention.

      When new comment threading for 2.7 was introduced, you recommended call to comment-reply.js in this form.

      But problem with this is that comment-reply.js is called on all pages in all cases even there are many cases when it shouldn’t be called because it is simply not needed:

      • when comments are turned off on site wide level
      • when threaded comments are not enabled (this is default option)
      • when comments are not enabled on that entry
      • when there is no comments on that entry
      • when page is used as front page (in reading options)

      In all those situations comment-reply.js is loaded even though there is no need for it. Yes, it is cached after first page view, but what if visitor lands on that particular page that doesn’t need this file and that page already has ten javascript files? It will just increase page load time and you know that visitors that come from search engines or from links on other sites have low tolerance and don’t want to wait to much.

      So what we need is that this script is loaded only when there is need for it and my suggestion is that you make some function that should be checked and that will return true or false value when asked if there is need for comment-reply.js. Maybe that script can’t solve all problems but at least it can return false value if comments are globally turned off or comment threading is not enabled (I’m quite sure it can do this).

      Example of how this should work in theme’s files:

      if ( comment_threading_entry_status() ) wp_enqueue_script( 'comment-reply' );

      Example of functions:
      function comment_threading_entry_status() {
      if (((get_option('default_comment_status')) == "open") && ((get_option('thread_comments')) == "1") && ( !is_front_page() ) && ( comments_open() ) && ( have_comments() )) {
      return true;
      } else
      return false;

      This function doesn’t work like this (it works without last two conditions), but you got a point.

      I hope that you’ll at least respond me in reasonable time 🙂

      (btw, why we don’t have subscribe to comments here, it should be enabled on wp.com?)

    • John Biddle 8:39 pm on April 2, 2009 Permalink | Log in to Reply

      This is a great idea. The problem is even bigger than you describe. It’s true that for second and subsequent pageloads the javascript is is the cache, it’s also true that unless the files has an expired header the browser still has to contact the host to determine if the file in cache is current. There won’t be a download for current files, but the round trip to the server just to check the currentness wastes time for every page. This problem exists for losts of files in lots of plugins and probably contributes to a 1 or 2 second page delay for the average page.

compose new post
next post/next comment
previous post/previous comment
show/hide comments
go to top
go to login
show/hide help
shift + esc
Skip to toolbar