Category Archives: autoptimize

Autoptimize CSS defer switching to loadCSS (soon)

Historically Autoptimize used its own JS-implementation to defer the loading of the main CSS, hooking into the domContentLoaded event and this has worked fine. I knew about Filament Group’s loadCSS, but saw no urgent reason to implement it as I saw no big advantages vs. my homegrown solution. That changed when criticalcss.com’s Jonas contacted me, pointing out that the best way to load CSS is now using the rel="preload" approach, which as of loadCSS 1.3 is also the way loadCSS works;

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">

As rel="preload" currently is only supported by Chrome & Opera (both Blink-based), a JS polyfill is needed for other browsers which uses loadCSS to load the CSS. Hopefully other browsers catch up on rel="preload" because it is a very elegant solution which allows the CSS to load sooner then with the old code while still being non-render blocking. What more could one which for (“Unicorns” my 10yo daughter might say, but what does she know)?

Anyways; I have integrated this new approach in a separate branch on GitHub, you can download the zip-file here to test this and all the other fixes and improvements since 2.1.0. Let me know what you think. Happy preloading!

How to make Autoptimize (even) faster

Less blogposts here lately, mostly because I’m doing custom Autoptimize-development for a partner (more on that later) and because I get a lot of support-questions on the wordpress.org support forums (with approx. between 1500-2000 downloads/ weekday that is to be expected). One of the more interesting questions I got there was about Autoptimize being slow when JS optimization was active and what would be the cause of that. The reply is of interest for a larger audience and is equally valid for CSS optimization;

Typically the majority of time spent in Autoptimize is mainly in the actual minification of code that is not minified yet (purely based on filename; if the filename ends in .min.js or -min.js).

So generally speaking, the way to avoid this is;
1. have a page cache to avoid requests triggering autoptimize (as in that case the cached HTML will have links to cached CSS/JS in it)
2. for uncached pages; make sure AO can re-use previously cached CSS/ JS (from another page), in which case no minification needs to be done (for that you will almost always want to NOT aggregate inline JS, as this almost always busts the cache)
3. for uncached CSS/ JS; make sure any minified file is recognizable as such in the filename (e.g. .min.css -min.js), this can lighten the minification-load considerably (I’ll add a filter in the next version of AO so you can tell AO a file is minified even if it does not have that in the name).

So based on this, some tips;
* make sure you’re not aggregating inline JS
* for your own code (CSS/ JS); make sure it is minified and that the filename confirms this. if you can convince the theme’s developer to do so, all the better (esp. the already minified but big wp-content/themes/bridge/js/plugins.js is a waste of precious resources)
* you could try switching to the legacy minifiers (see FAQ) to see if this improves performance
* you can also check if excluding some un-minified files from minification helps performance (e.g. that bridge/js/plugins.js)

WordPress 4.7 custom background image bug & workaround

If you encountered this bug but are not using Autoptimize, leave a comment below or contact me here. Your info can help understand if the regression has an impact outside of Autoptimize as well!


Gotta love Sarah, but there’s a small bug in Vaughan’s (WordPress 4.7) that breaks (part of the CSS) when Autoptimized. If you have a theme that supports custom backgrounds (e.g. TwentySixteen) and you set that custom background in the Customizer, the URL ends up escaped (well, they wp_json_encode() it actually) like this;

body{background-image: url("http:\/\/localhost\/wordpress\/wp-content\/uploads\/layerslider\/Full-width-demo-slider\/left.png");}

Which results in the Autoptimized CSS for the background-image being broken because the URL is not recognized as such. The bug has been confirmed already and the fix should land in WordPress 4.7.1.

If you’re impacted and can’t wait for 4.7.1 to be released, there are 2 workarounds:
1. simple: disable the “Aggregate inline CSS”-option
2. geeky: use this code snippet to fix the URL before AO has a change to misinterpret it;

add_filter('autoptimize_filter_html_before_minify','fix_encoded_urls');
function fix_encoded_urls($htmlIn) {
	if ( strpos($htmlIn,"body.custom-background") !== false ) {
		preg_match_all("#background-image:\s?url\(?[\"|']((http(s)?)?:\\\/\\\/.*)[\"|']\)?#",$htmlIn,$badUrls);
	  	if ($badUrls) {
			foreach ($badUrls[1] as $badUrl) {
				$htmlIn = str_replace($badUrl, stripslashes($badUrl), $htmlIn);
			}
		}
	}
  	return $htmlIn;
}

So how does Autoptimize work anyway?

A question that has come up a couple of times already is how Autoptimize and it’s cache work. So let’s do some copy/pasting of what I replied earlier on the wordpress.org support forum;

  1. AO intercepts the HTML created by WordPress for a request (using the output buffer)
  2. all references to JS (and CSS) are extracted from the HTML
  3. all original references to JS (and CSS) are removed from the HTML (the code in the original files is left as is, AO never changes those files)
  4. all JS (and CSS) is aggregated (JS in one string, CSS in as many strings as there were media types)
  5. the md5-hash (mathematical/ cryptographic function that generates a quasi-unique string based on another string) of the aggregated JS (and CSS) is calculated
  6. using the md5 AO checks if a cached file with that md5 exists and if so continues to step 8
  7. if no cached file is found, the JS (and CSS) is minified and cached in a new file, with the md5 as part of the filename
  8. the links to the autoptimized JS (and CSS) file in cache are injected in the HTML
  9. the HTML is minified (but not cached in Autoptimize)
  10. the HTML is returned to WordPress (where it can be cached by a page cache and sent to the visitor)

This is especially interesting if you want to understand why the cache size can “explode”; if in step 4 the code is even a bit different from previous requests, the md5-hash in step 5 will be different so the file will not be found in cache (step 6) and the code will be re-minified (which is relatively expensive) and cached (step 7).

And that, my friends, is how Autoptimize works.

How to fix CSS media-types impacting Autoptimized CSS order

pixeldima-forum-screenshotAdel of Pixeldima contacted me to look into a problem with some of the styles not being applied after autoptimization on the forum-page in his beautiful OKAB-theme. I had seen similar problems before, but decided to dig in this time to understand the root cause. That root cause turned out to be 2 CSS-files, one overriding the style of the other, having a different media-type, which messed up the load order once autoptimized. This can either be fixed at the theme-level, at AO configuration level or with a couple of lines of code hooking into AO’s API.

The problem

Without Autoptimize (which one can trigger by simply adding ?ao_noptimize=1 to the URL), these 2 relevant files were loaded (among many others obviously):

  • bbpress.css (the default bbpress css-file) was loaded first with media=”screen”
  • okab/bbpress-styles.css (part of the theme) is loaded second with media=”all”, overriding some of the CSS in bbpress.css

Autoptimize honors the media-types, resulting in 2 Autoptimized CSS-files;

  • autoptimize_1a002577cefe349767025a16201f37a9.css with media=”all” is loaded first (because the very first CSS-file encountered in the HTML had media=”all”) which contains okab/bbpress-styles.css
  • autoptimize_8e3c7dac90177214b6583286ddaa141f.css is loaded second with media=”screen”, containing bbpress.css

So due to the mediatype the code in bbpress-styles.css was loaded before the CSS in bbpress.css when Autoptimized, resulting in styles being overwritten the wrong way (bbpress-styles.css is overwritten by bbpress.css instead of the other way around).

The solution(s)

As Adel was the theme developer, he could immediately attack the root issue by enqueuing bbpress-styles.css with media=”screen”. This way both files share the same media-type and go in the same autoptimized CSS-file, resulting in the CSS of bbpress.css getting properly overwritten by the CSS of okab/bbpress-styles.css.

If you’re not the theme developer you’ll probably not want to change the theme’s code (although you could dequeue and re-enqueue in a child-theme’s functions.php), in which case you have two workarounds at your disposal: the easiest workaround being simply excluding the CSS-file that gets overwritten from CSS optimization (i.e. in this case simply adding okab/bbpress-style.css to the list of CSS optimization exclusions). Easy indeed, but on the downside you’ll have one non-optimized CSS-file. That’s why it’s a good thing we have our precious little API, allowing us to override the media-type of the offending file with just a couple of lines of code, like this;

add_filter('autoptimize_filter_css_tagmedia','check_mediatype',10,2);
function check_mediatype($media,$tag) {
  if ( strpos($tag,"okab/bbpress-styles.css") !== false ) {
	$media=array("screen");
  }
  return $media;
}

Conclusion

As Autoptimize honors the original CSS’s media-types, 2 CSS-files that ought to be loaded in a specific order might end up being loaded in the wrong order if their media-type is different. This can be fixed in the theme or worked around by excluding a specific CSS-file or using AO’s API to override the media-type for the offending CSS-file.

Autoptimize cache size: the canary in the coal mine

Update 23/06/2017: if you came here looking for solutions to Autoptimize cache-size problems after having (been) updated to AO 2.1.1; there’s a bug in that specific version, please update to either 2.1.2 or to the most recent stable version (currently 2.2.1).


another-canary-in-a-coal-mine
Copy/ pasted straight from a support question on wordpress.org;

Auto-deleting the cache would only solve one problem you’re having (disk space), but there are 2 other problems -which I consider more important- that auto-cleaning can never solve:
1. you will be generating new autoptimized JS very regularly, which slows your site down for users who happen to be the unlucky ones requesting that page
2. a visitor going from page X to page Y will very likely have to request a different autoptimized JS file for page Y instead of using the one from page X from cache, again slowing your site down

So I actually consider the cache-size warning like a canary in the coal mines; if the canary dies, you know there’s a bigger problem.

You don’t (or shouldn’t) really want me to take away the canary! :)